Допустим есть некий WPF UserControl, который содержит в себе 2 дочерних элемента, например оба типа Button. Как можно достучаться до конкретного дочернего элемента ?
Хотелось бы получить примерно в таком виде
<uc:MyUserControl>
<uc:MyUserControl.ButtonOK Foreground="Green">
</Button>
<uc:MyUserControl.ButtonCancel Foreground="Red">
</Button>
</uc:MyUserControl>
Пробовал объявлять соотвествующие кнопки как публичные свойства у MyUserControl, не сработало.
Здравствуйте, Аноним, Вы писали:
А>skipped
Если я правильно понял то, чего вы хотите добиться, то вам нужны
dependency properties.
Пример:
1) контрол:
а) code-behind:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public Brush ButtonOkForeground
{
get { return (Brush)GetValue(ButtonOkForegroundProperty); }
set { SetValue(ButtonOkForegroundProperty, value); }
}
public static readonly DependencyProperty ButtonOkForegroundProperty =
DependencyProperty.Register("ButtonOkForeground", typeof(Brush), typeof(UserControl1),
new UIPropertyMetadata(new SolidColorBrush(SystemColors.ControlTextColor)));
public Brush ButtonCancelForeground
{
get { return (Brush)GetValue(ButtonCancelForegroundProperty); }
set { SetValue(ButtonCancelForegroundProperty, value); }
}
public static readonly DependencyProperty ButtonCancelForegroundProperty =
DependencyProperty.Register("ButtonCancelForeground", typeof(Brush), typeof(UserControl1),
new UIPropertyMetadata(new SolidColorBrush(SystemColors.ControlTextColor)));
}
б) разметка:
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="54" d:DesignWidth="179"
x:Name="userControl1">
<StackPanel>
<Button Content="OK" Foreground="{Binding ElementName=userControl1, Path=ButtonOkForeground}"/>
<Button Content="Cancel" Foreground="{Binding ElementName=userControl1, Path=ButtonCancelForeground}"/>
</StackPanel>
</UserControl>
2) использование:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:UserControl1 ButtonOkForeground="Green" ButtonCancelForeground="Red" />
</Grid>
</Window>
Здравствуйте, HowardLovekraft, Вы писали:
HL>Здравствуйте, Аноним, Вы писали:
А>>skipped
HL>Если я правильно понял то, чего вы хотите добиться, то вам нужны dependency properties.
HL>Пример:
HL>1) контрол:
HL>а) code-behind:
Спасибо, но не совсем так хотелось на самом деле
Нужно именно вытащить полностью кнопку, что-то типа такого
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public static readonly DependencyProperty ButtonOKProperty = DependencyProperty.Register(
"ButtonOK", typeof(Button), typeof(UserControl1) );
public Button ButtonOK
{
get { return GetValue( UserControl1.ButtonOneProperty) as Button; }
set { SetValue( UserControl1.ButtonOneProperty, value );
}
}
Затем в разметке уже использовать как
<uc:UserControl1>
<uc.UserControl1.ButtonOK>
// тут меняем любые свойства что есть у Button
</uc.UserControl1.ButtonOK>
</uc:UserControl1>
Но не совсем понятно как ButtonOK засунуть в исходную разметку UserControlа
Здравствуйте, Аноним, Вы писали:
А>Нужно именно вытащить полностью кнопку
AFAIK, так не получится — вы не сможете задавать свойства у значения свойства.
А>что-то типа такого
А>skipped
А>Но не совсем понятно как ButtonOK засунуть в исходную разметку UserControlа
DP типа Button объявить можно, но вы должны понимать, что такая разметка:
<local:UserControl1>
<local:UserControl1.ButtonOK>
<Button Content="Hello, world!" />
</local:UserControl1.ButtonOK>
</local:UserControl1>
задает этому свойству
новое значение.
Если это устраивает, то сделать так, чтобы вновь заданная кнопка отображалась в контроле, не сложно:
public static readonly DependencyProperty MyButtonProperty =
DependencyProperty.Register("MyButton", typeof(Button), typeof(UserControl1),
new UIPropertyMetadata(null, MyButton_Changed));
private static void MyButton_Changed(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
var control = (UserControl1)target;
if (args.OldValue != null)
{
control.ButtonsPanel.Children.Remove((Button)args.OldValue);
}
if (args.NewValue != null)
{
control.ButtonsPanel.Children.Add((Button)args.NewValue);
}
}
Здесь ButtonsPanel — это StackPanel, у которой задано имя. Можно обойтись и без задания имени, например, найти в дереве элемент нужного типа и добавить кнопку к нему.