Silverlight UserControl 自定义属性绑定(bind)

标签 silverlight binding user-controls

在 Silverlight 用户控件中实现自定义属性的正确方法是什么?

Silverlight 中的每个“页面”在技术上都是一个 UserControl(它们派生自 UserControl 类)。当我在这里说 UserControl 时,我的意思是一个自定义 UserControl,它将在许多不同场景中的许多不同页面中使用(类似于 ASP.NET UserControl)。

我希望自定义用户控件支持绑定(bind),而不是依赖于它绑定(bind)到的属性的名称,以始终保持相同。相反,我希望 UserControl 本身具有 UserControl 内的控件绑定(bind)到的属性,并且 UserControl 外的 ViewModel 也绑定(bind)到。 (请看下面的例子)

UserControl 内的绑定(bind)有效,MainPage 内的绑定(bind)有效,我在 MainPage 和 UserControl 之间设置的绑定(bind)不起作用。特别是这一行:

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

示例输出:
alt text

主页.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
  }
 }
}

引用资料(我是如何做到这一点的):

使用依赖属性:
http://geekswithblogs.net/thibbard/archive/2008/04/22/wpf-custom-control-dependency-property-gotcha.aspx

使用 DependencyPropertys,将 x:Name 添加到您的 UserControl - 添加与 ElementName 的绑定(bind),在 PropertyChangedCallback 方法中再次设置自定义属性:
Setting Custom Properties in UserControl via DataBinding

不要使用自定义属性,依赖底层数据上下文名称(我不喜欢这个解决方案):
wpf trouble using dependency properties in a UserControl

最佳答案

我将其理解为您的控件未从 maim 页面接收新值的原因是您正在设置控件的 DataContext。如果你没有,那么控件的 DataContext 将从它的父级继承,在这种情况下是主页面。

为了让它工作,我删除了控件的 DataContext 设置,为每个控件添加了一个 x:Name 并使用 [name].SetBinding 方法在控件的构造函数中设置绑定(bind)。

我在 ctor 中进行了绑定(bind),因为我无法找到将 xaml 中声明性绑定(bind)的 Source 属性设置为 Self 的方法。即 {Binding SelectedText, Mode=TwoWay, Source=[Self here some how]}。我确实尝试过使用RelativeSource={RelativeSource Self},但没有任何乐趣。

注意:所有这些都是 SL3。

关于Silverlight UserControl 自定义属性绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1526767/

相关文章:

silverlight - MVVM Light - 向后台代码发送通知

c# - 双向绑定(bind)不起作用

c# - 在 Silverlight 中检测 CapsLock 是打开还是关闭

c# - Silverlight HttpWebRequest 安全异常

javascript - 在不引起递归的情况下将两个 knockout 变量连接在一起

c# - Xamarin.Forms 如何将多个页面的 BindingContext 设置为同一个 ViewModel?

javascript - 查找元素的目标

.net - WPF:从 UserControl 转换为 CustomControl

asp.net - ASP.NET 中 Web 用户控件的事件冒泡

c# - VirtualizingStackPanel 和 TextWrapping 错误? Windows Mobile