2010-07-16 141 views
10

我有一个用户控件,我想参与数据绑定。我已经在用户控件中设置了依赖项属性,但无法使其工作。数据绑定到WPF中的UserControl

当我用静态文本(例如BlueText =“ABC”)调用它时,uc显示正确的文本。当我尝试将其绑定到本地公共属性时,它始终为空。

<src:BlueTextBox BlueText="Feeling blue" />   <!--OK--> 
<src:BlueTextBox BlueText="{Binding Path=MyString}" /> <!--UserControl always BLANK!--> 
<TextBox Text="{Binding Path=MyString}" Width="100"/> <!--Simple TextBox Binds OK--> 

我已经将代码煮成下面的简化示例。下面是用户控件的XAML:

<UserControl x:Class="Binding2.BlueTextBox" ... 
    <Grid> 
     <TextBox x:Name="myTextBox" Text="{Binding BlueText}" Foreground="Blue" Width="100" Height="26" /> 
    </Grid> 

这里是用户控件的代码后面:

public partial class BlueTextBox : UserControl 
{ 
    public BlueTextBox() 
    { 
     InitializeComponent(); 
     DataContext = this; // shouldn't do this - see solution 
    } 

    public static readonly DependencyProperty BlueTextProperty = 
     DependencyProperty.Register("BlueText", typeof(string), typeof(BlueTextBox)); 

    public string BlueText 
    { 
     get { return GetValue(BlueTextProperty).ToString(); } 
     set { SetValue(BlueTextProperty, value.ToString()); } 
    } 

这似乎是它应该是很容易的,但我不能使它发挥作用。谢谢你的帮助!

更多信息:当我尝试修复尤金建议的修复时,我注意到一些奇怪的行为。我为元数据添加了一个PropertyChangedCallback;这让我可以看到BlueText的价值。当将字符串设置为静态值(=“感觉蓝色”)时,PropertyChanged事件触发。数据绑定的情况下不会触发PropertyChanged。我认为这意味着数据绑定值不会发送到UserControl。 (我认为构造函数在静态情况下不会被调用)

解决方案:问题被Arcturus和jpsstavares正确识别。首先,当在控件的构造函数中设置DataContext = this时,我覆盖了数据绑定。这阻止了数据绑定值的设置。我还必须命名控件x:Name = root,并指定Binding ElementName = root int XAML。为了获得TwoWay绑定,我需要在调用者中设置Mode = TwoWay。下面是正确的代码:

<src:BlueTextBox BlueText="{Binding Path=MyString, Mode=TwoWay}}" /> <!--OK--> 

现在XAML的用户控件:

<UserControl x:Class="Binding2.BlueTextBox" x:Name="root"... 
    <Grid> 
     <TextBox x:Name="myTextBox" Text="{Binding ElementName=root, Path=BlueText}" Foreground="Blue" Width="100" Height="26" /> 
    </Grid> 

最后我删除了的DataContext =这在用户控件的构造函数。

public BlueTextBox() 
    { 
     InitializeComponent(); 
     //DataContext = this; -- don't do this 
    } 

感谢大家的巨大帮助!

回答

11

您设置的DataContext在控制自身,从而使用于其他控制这种控制时覆盖的DataContext。以你的例子在您的具体情况结合:

<src:BlueTextBox BlueText="{Binding Path=MyString}" /> 

一旦加载所有的DataContext设置,它会寻找你的BlueTextBox事情控制路径的MyString由于你在DataContext设置它。我想这不是你打算如何工作;)。

解决方案:

更改文本结合要么2个绑定之一:

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type src:BlueTextBox}}, Path=BlueText} 

名称控件的根(或类似的东西)

<UserControl x:Name="Root" 

{Binding ElementName=Root, Path=BlueText} 

并删除

DataContext = this; 

从您的用户控件的构造函数,它应该工作就像一个魅力..

0

可能需要将您的属性FrameworkPropertyMetadata添加到指定FrameworkPropertyMetadataOptions.AffectsRender和AffectsMeasure的位置。

FrameworkPropertyMetadataOptions enumeration MSDN article

+0

尝试设置两个AffectsRender和AffectsMeasure期间,但是这并没有任何影响。谢谢。 – RaoulRubin 2010-07-16 14:37:48

2

我认为在这种情况下,你需要设置ElementName属性的绑定。事情是这样的:

<UserControl x:Class="Binding2.BlueTextBox" x:Name="blueTextBox"... 
<Grid> 
    <TextBox x:Name="myTextBox" Text="{Binding ElementName=blueTextBox, Path=BlueText}" Foreground="Blue" Width="100" Height="26" /> 
</Grid> 
0

我知道这是一个老话题,但仍。

还提到了在UIPropertyMetadata的PropertyChangedCallback注册您的DP