Как правильно реализовать пользовательские свойства в Silverlight UserControls?
Каждая «Страница» в Silverlight технически является UserControl (они являются производными от класса UserControl). Когда я говорю здесь UserControl, я имею в виду пользовательский UserControl, который будет использоваться на разных страницах в разных сценариях (аналогично ASP.NET UserControl).
Я бы хотел, чтобы Custom UserControl поддерживал привязку и не полагался на имя свойства, к которому оно привязано, чтобы оно всегда было одинаковым. Вместо этого я хотел бы, чтобы сам UserControl имел свойство, с которым связываются элементы управления внутри UserControl, а также привязывают ViewModels за пределами UserControl. (см. пример ниже)
Связывание в UserControl работает, Связывание в MainPage работает, Связывание, которое я установил между MainPage и UserControl, не работает. Конкретно эта строка:
<myUserControls:MyCustomUserControl x:Name="MyCustomControl2"
SelectedText="{Binding MainPageSelectedText, Mode=TwoWay}"
Width="200" Height="50" />
пример вывода:
MainPage.xaml
<UserControl x:Class="SilverlightCustomUserControl.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:myUserControls="clr-namespace:SilverlightCustomUserControl"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Canvas x:Name="LayoutRoot">
<StackPanel Orientation="Vertical">
<TextBlock Text="UserControl Binding:" Width="200"></TextBlock>
<myUserControls:MyCustomUserControl x:Name="MyCustomControl2" SelectedText="{Binding MainPageSelectedText, Mode=TwoWay}" Width="200" Height="50" />
<TextBlock Text="MainPage Binding:" Width="200"></TextBlock>
<TextBox Text="{Binding MainPageSelectedText, Mode=TwoWay}" Width="200"></TextBox>
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding MainPageSelectedText}" Width="200" Height="24"></TextBlock>
</Border>
</StackPanel>
</Canvas>
</UserControl>
MainPage.xaml.cs
namespace SilverlightCustomUserControl
{
public partial class MainPage : UserControl, INotifyPropertyChanged
{
//NOTE: would probably be in a ViewModel
public string MainPageSelectedText
{
get { return _MainPageSelectedText; }
set
{
string myValue = value ?? String.Empty;
if (_MainPageSelectedText != myValue)
{
_MainPageSelectedText = value;
OnPropertyChanged("MainPageSelectedText");
}
}
}
private string _MainPageSelectedText;
public MainPage()
{
InitializeComponent();
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
PropertyChangedEventHandler ph = this.PropertyChanged;
if (ph != null)
ph(this, new PropertyChangedEventArgs(name));
}
#endregion
}
}
MyCustomUserControl.xaml
<UserControl
x:Class="SilverlightCustomUserControl.MyCustomUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<StackPanel>
<TextBox Text="{Binding SelectedText, Mode=TwoWay}" />
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding SelectedText}" Height="24"></TextBlock>
</Border>
</StackPanel>
</Grid>
</UserControl>
MyCustomUserControl.xaml.cs
namespace SilverlightCustomUserControl
{
public partial class MyCustomUserControl : UserControl
{
public string SelectedText
{
get { return (string)GetValue(SelectedTextProperty); }
set { SetValue(SelectedTextProperty, value); }
}
public static readonly DependencyProperty SelectedTextProperty =
DependencyProperty.Register("SelectedText", typeof(string), typeof(MyCustomUserControl), new PropertyMetadata("", SelectedText_PropertyChangedCallback));
public MyCustomUserControl()
{
InitializeComponent();
}
private static void SelectedText_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//empty
}
}
}
Ссылки (как я дошел до этого):
использовать DependencyPropertys:
http://geekswithblogs.net/thibbard/archive/2008/04/22/wpf-custom-control-dependency-property-gotcha.aspx
используйте DependencyPropertys, добавьте x: Name в свой UserControl - добавьте Binding с ElementName, снова установите свойство Custom в методе PropertyChangedCallback:
Установка пользовательских свойств в UserControl через привязку данных
не использовать пользовательские свойства, полагаться на базовые имена текстовых данных (мне не нравится это решение):
wpf проблема с использованием свойств зависимостей в UserControl