Silverlight UserControl Custom Property Binding

Jaki jest właściwy sposób wdrożenia niestandardowych właściwości w Silverlight UserControls?

Każda „strona” w Silverlight jest technicznie UserControl (pochodzą one z klasy UserControl). Kiedy mówię tutaj UserControl, mam na myśli Custom UserControl, który będzie używany wewnątrz wielu różnych stron w wielu różnych scenariuszach (podobnie jak w ASP.NET UserControl).

Chciałbym, aby Custom UserControl obsługiwał powiązanie, a nie polegał na nazwie właściwości, z którą jest powiązany, aby zawsze był taki sam. Zamiast tego chciałbym, aby sam UserControl miał właściwość, z którą kontrolki wewnątrz UserControl wiążą się, a ViewModels poza UserControl również się wiążą. (zobacz poniższy przykład)

Wiązanie w ramach prac UserControl, Binding w MainPage działa, Binding I skonfigurować między MainPage i UserControl nie działa. W szczególności ta linia:

<myUserControls:MyCustomUserControl x:Name="MyCustomControl2" 
    SelectedText="{Binding MainPageSelectedText, Mode=TwoWay}" 
    Width="200" Height="50" />

przykładowe wyjście:

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
  }
 }
}

Referencje (jak dotarłem tak daleko):

użyj DependencyPropertys:http://geekswithblogs.net/thibbard/archive/2008/04/22/wpf-custom-control-dependency-property-gotcha.aspx

użyj DependencyPropertys, dodaj x: Nazwa do twojego UserControl - dodaj Binding z ElementName, ustaw ponownie właściwość Custom w metodzie PropertyChangedCallback:Ustawianie niestandardowych właściwości w UserControl za pomocą DataBinding

nie używaj niestandardowych właściwości, polegaj na bazowych nazwach datacontext (nie podoba mi się to rozwiązanie):wpf kłopoty z wykorzystaniem właściwości zależności w UserControl

questionAnswers(3)

yourAnswerToTheQuestion