Silverlight的用户控件自定义属性绑定(Silverlight UserControl Cu

2019-08-17 08:41发布

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

每“页”在Silverlight在技术上是一个用户控件(它们是从用户控件类派生)。 当我在这里说的用户控件,我的意思是一个自定义用户控件,将在许多不同的情况很多不同的页面(类似于ASP.NET用户控件)内使用。

我想自定义用户控件支持绑定,而不是依赖于它被绑定到属性的名称,始终是相同的。 相反,我希望用户控件本身具有的用户控件绑定到内部的控件和的ViewModels的用户控件外还绑定到一个属性。 (请参见下面的示例)

UserControl中结合工作时,内部的MainPage结合工作,结合我建立和的MainPage的用户控件之间不起作用。 特别是这一行:

<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:命名你的用户控件-在PropertyChangedCallback方法再次添加绑定使用的ElementName,设置自定义属性: 通过数据绑定在用户控件设置自定义属性

不使用自定义属性,依赖于底层的datacontext名字(我不喜欢这个解决方案): WPF的用户控件使用依赖属性的麻烦

Answer 1:

我把它理解为你的控制没有收到来自残废页的新值的原因是您正在设置控件的DataContext的。 如果你没有那么控制的DataContext的,将从其父,在这种情况下,主页被继承。

为了得到这个工作我去掉你控制的DataContext的设置,增加了一个X:名称给每个控制和使用[名] .SetBinding方法设置控件的构造函数的结合。

我确实在构造函数的结合,因为我无法弄清楚设置声明性绑定的源属性在XAML到自我的一种方式。 即{[这里自一些如何]结合SelectedText,模式=双向,源=}。 我曾尝试使用的RelativeSource = {自我的RelativeSource}没有快乐。

注:这一切都是SL3。



Answer 2:

问题是用户控件被扔一个数据绑定错误(可见在输出窗口在调试时)

因为用户控件的DataContext的是在自己的XAML设置为“自动”,它一直在寻找自己的范畴内MainPageSelectedText(这是不是“的MainPage”,这是你可能会认为它看起来内寻找MainPageSelectedText,因为当你在物理写/望着那就是在“背景”的代码)

我能“工作”的设置绑定代码背后得到的。 设置在代码中绑定的背后是设置用户控件本身作为绑定的“源”的唯一途径。 但是,如果绑定双向这仅适用。 单向绑定将打破这个代码。 更好的解决方案完全是创建一个Silverlight 控件 ,而不是用户控件

也可以看看:

http://social.msdn.microsoft.com/Forums/en-US/silverlightcontrols/thread/052a2b67-20fc-4f6a-84db-07c85ceb3303

http://msdn.microsoft.com/en-us/library/cc278064%28VS.95%29.aspx

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">
 <Grid>
  <StackPanel>
   <TextBox x:Name="UserControlTextBox" />
   <Border BorderBrush="Black" BorderThickness="1">
    <TextBlock x:Name="UserControlTextBlock" 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();

               //SEE HERE
   UserControlTextBox.SetBinding(TextBox.TextProperty, new Binding() { Source = this, Path = new PropertyPath("SelectedText"), Mode = BindingMode.TwoWay });
   UserControlTextBlock.SetBinding(TextBlock.TextProperty, new Binding() { Source = this, Path = new PropertyPath("SelectedText") });
               //SEE HERE
  }

  private static void SelectedText_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
   //empty
  }

 }
}


Answer 3:

取而代之的数据上下文绑定到自己,你可以通过添加在XAML中设置的绑定x:Name为用户控件,然后在用户控件XAML如下结合:

<UserControl
  x:Class="SilverlightCustomUserControl.MyCustomUserControl" 
  x:Name="myUserControl
  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">
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding SelectedText, ElementName=myUserContol, Mode=TwoWay}" />
            <Border BorderBrush="Black" BorderThickness="1">
                <TextBlock Text="{Binding SelectedText,ElementName=myUserControl}" Height="24"></TextBlock>
            </Border>
        </StackPanel>
     </Grid>
</UserControl>


文章来源: Silverlight UserControl Custom Property Binding