Bindung der benutzerdefinierten Silverlight UserControl-Eigenschaft

Wie werden benutzerdefinierte Eigenschaften in Silverlight UserControls ordnungsgemäß implementiert?

Jede "Seite" in Silverlight ist technisch gesehen ein UserControl (abgeleitet von der UserControl-Klasse). Wenn ich hier UserControl sage, meine ich ein benutzerdefiniertes UserControl, das in vielen verschiedenen Seiten in vielen verschiedenen Szenarien verwendet wird (ähnlich einem ASP.NET-UserControl).

Ich möchte, dass das benutzerdefinierte Benutzersteuerelement die Bindung unterstützt und sich nicht auf den Namen der Eigenschaft verlässt, an die es gebunden ist, um immer gleich zu sein. Stattdessen möchte ich, dass das UserControl selbst eine Eigenschaft hat, an die die Steuerelemente innerhalb des UserControls und die ViewModels außerhalb des UserControls ebenfalls gebunden sind. (siehe folgendes Beispiel)

Die Bindung innerhalb des UserControls funktioniert. Die Bindung innerhalb der MainPage funktioniert. Die Bindung, die ich zwischen der MainPage und dem UserControl eingerichtet habe, funktioniert nicht. Speziell diese Zeile:

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

Beispielausgabe:

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

Referenzen (wie ich so weit gekommen bin):

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

Verwenden Sie DependencyPropertys, fügen Sie Ihrem UserControl x: Name hinzu, fügen Sie Binding with ElementName hinzu, und legen Sie die benutzerdefinierte Eigenschaft erneut in der PropertyChangedCallback-Methode fest:Festlegen benutzerdefinierter Eigenschaften in UserControl über DataBinding

verwende keine benutzerdefinierten Eigenschaften, verlasse dich auf zugrunde liegende Datenkontextnamen (mir gefällt diese Lösung nicht):Probleme mit der Verwendung von Abhängigkeitseigenschaften in einem UserControl

Antworten auf die Frage(3)

Ihre Antwort auf die Frage