Я использовал привязку данных в нескольких простых ситуациях с довольно хорошим успехом.Обычно я просто использую INotifyPropertyChanged, чтобы позволить моему codebehind изменять значения графического интерфейса на экране, а не реализовывать свойства зависимостей для всего.
Я играю со светодиодным элементом управления, чтобы узнать больше о привязке данных в пользовательских элементах управления, и меня заставилииспользовать свойства зависимостей, потому что VS2008 сказал мне, что я должен.Мое приложение простое - у меня есть окно, которое отображает несколько светодиодных элементов управления, каждый с номером над ним и, по желанию, один на своей стороне.Светодиоды должны быть определены с цветом по умолчанию, а также с измененным состоянием.
Я начал с написания элемента управления светодиодами, который, казалось, работал идеально.Сначала я начал с кода, подобного следующему:
LED.xaml
<UserControl x:Class="LEDControl.LED"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="Auto" Width="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- LED portion -->
<Ellipse Grid.Column="0" Margin="3" Height="{Binding LEDSize}" Width="{Binding LEDSize}" Fill="{Binding LEDColor}" StrokeThickness="2" Stroke="DarkGray" />
<Ellipse Grid.Column="0" Margin="3" Height="{Binding LEDSize}" Width="{Binding LEDSize}">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.5,1.0">
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1.5" ScaleY="1.5"/>
<TranslateTransform X="0.02" Y="0.3"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Offset="1" Color="#00000000"/>
<GradientStop Offset="0.4" Color="#FFFFFFFF"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!-- label -->
<TextBlock Grid.Column="1" Margin="3" VerticalAlignment="Center" Text="{Binding LEDLabel}" />
</Grid>
</UserControl>
Это отлично рисует светодиод.Затем я привязал LEDSize, LEDLabel и LEDColor к свойствам эллипса, установив this.DataContext = this
, как я всегда делаю:
LED.xaml.cs
/// <summary>
/// Interaction logic for LED.xaml
/// </summary>
public partial class LED : UserControl, INotifyPropertyChanged
{
private Brush state_color_;
public Brush LEDColor
{
get { return state_color_; }
set {
state_color_ = value;
OnPropertyChanged( "LEDColor");
}
}
private int led_size_;
public int LEDSize
{
get { return led_size_; }
set {
led_size_ = value;
OnPropertyChanged( "LEDSize");
}
}
private string led_label_;
public string LEDLabel
{
get { return led_label_; }
set {
led_label_ = value;
OnPropertyChanged( "LEDLabel");
}
}
public LED()
{
InitializeComponent();
this.DataContext = this;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged( string property_name)
{
if( PropertyChanged != null)
PropertyChanged( this, new PropertyChangedEventArgs( property_name));
}
#endregion
}
AtВ этот момент я могу изменить значения свойств и увидеть, что светодиод меняет размер, цвет и метку.Отлично!
Я хочу, чтобы светодиодный элемент управления можно было многократно использовать в других виджетах, которые я пишу со временем, и следующим шагом для меня было создание другого UserControl (в отдельной сборке), который называется IOView
.IOView
является довольно простым на данный момент:
IOView.xaml
<UserControl x:Class="IOWidget.IOView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:led="clr-namespace:LEDControl;assembly=LEDControl"
Height="Auto" Width="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" HorizontalAlignment="Center" Text="{Binding Path=Index}" />
<led:LED Grid.Row="1" HorizontalContentAlignment="Center" HorizontalAlignment="Center" LEDSize="30" LEDColor="Green" LEDLabel="Test" />
</Grid>
</UserControl>
Обратите внимание, что я могу изменять свойства светодиодов в XAML во время разработки, и все работаеткак и ожидалось:
![alt text](https://i.stack.imgur.com/y2hOl.png)
Затем я вслепую попытался связать данные LEDColor с моим IOView, и VS2008 любезно сказал мне «Невозможно установить« Binding »наСвойство «LEDColor» типа «LED». «Привязка» может быть установлена только для свойства DependencyProperty объекта DependencyObject. " Упс!Я даже не осознавал этого, так как раньше я не делал свои собственные элементы управления графическим интерфейсом.Так как LEDColor
уже привязан к базе данных эллипса, я добавил свойство DependencyProperty под названием Color.
LED.xaml.cs
public static DependencyProperty ColorProperty = DependencyProperty.Register( "Color", typeof(Brush), typeof(LED));
public Brush Color
{
get { return (Brush)GetValue(ColorProperty); }
set {
SetValue( ColorProperty, value);
LEDColor = value;
}
}
Обратите внимание, что я установилсвойство LEDColor
в установщике, так как именно так Ellipse знает, каким должен быть его цвет.
Следующим детским шагом была установка цвета светодиода в моем IOView путем привязки к IOView.InputColor:
IOView.xaml.cs:
/// <summary>
/// Interaction logic for IOView.xaml
/// </summary>
public partial class IOView : UserControl, INotifyPropertyChanged
{
private Int32 index_;
public Int32 Index
{
get { return index_; }
set {
index_ = value;
OnPropertyChanged( "Index");
}
}
private Brush color_;
public Brush InputColor
{
get { return color_; }
set {
color_ = value;
OnPropertyChanged( "InputColor");
}
}
private Boolean state_;
public Boolean State
{
get { return state_; }
set {
state_ = value;
OnPropertyChanged( "State");
}
}
public IOView()
{
InitializeComponent();
this.DataContext = this;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged( string property_name)
{
if( PropertyChanged != null)
PropertyChanged( this, new PropertyChangedEventArgs( property_name));
}
#endregion
}
и в IOView.xaml я изменил светодиод на это:
<led:LED Grid.Row="1" HorizontalContentAlignment="Center" HorizontalAlignment="Center" LEDSize="30" Color="{Binding InputColor}" />
Но это не работает, из-за следующей ошибки в окне вывода:
Ошибка пути BindingExpression: свойство 'InputColor' не найдено в 'объекте' '' LED '(Name =' ')'.BindingExpression: Path = InputColor;DataItem = 'LED' (Name = '');целевой элемент - «LED» (Name = '');Свойство target - 'Color' (тип 'Brush')
Хмм ... поэтому по какой-то причине моя DataBinding испорчена.Я могу заставить светодиод работать самостоятельно с привязкой к данным, но как только я помещаю его в другой элемент управления и устанавливаю его текстовый текст, он не работает.Я не уверен, что попробовать в этом пункте.
Я хотел бы получить как можно более подробный ответ.Я знаю, что мог бы просто повторно проверить CheckBox, чтобы получить те же результаты, но для меня это эксперимент, и я пытаюсь понять, как привязать данные к потомкам элементов управления.