数据绑定到 WPF 中的 UserControl
Posted
技术标签:
【中文标题】数据绑定到 WPF 中的 UserControl【英文标题】:Data binding to a UserControl in WPF 【发布时间】:2010-07-16 14:07:28 【问题描述】:我有一个想要参与数据绑定的 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-->
我已将代码简化为以下简化示例。这是 UserControl 的 XAML:
<UserControl x:Class="Binding2.BlueTextBox" ...
<Grid>
<TextBox x:Name="myTextBox" Text="Binding BlueText" Foreground="Blue" Width="100" Height="26" />
</Grid>
这是 UserControl 背后的代码:
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() );
这看起来应该很容易,但我无法让它工作。感谢您的帮助!
更多信息:当我尝试 Eugene 建议的修复时,我注意到了一些奇怪的行为。我在元数据中添加了一个 PropertyChangedCallback;这让我可以看到 BlueText 的值被设置。将字符串设置为静态值 (="feeling blue") 时,会触发 PropertyChanged 事件。数据绑定案例不会触发 PropertyChanged。我认为这意味着数据绑定值没有发送到 UserControl。 (我认为构造函数在静态情况下不会被调用)
解决方案:Arcturus 和 jpsstavares 正确识别了这些问题。首先,当在控件的构造函数中设置 DataContext=this 时,我覆盖了数据绑定。这阻止了数据绑定值的设置。我还必须将控件命名为 x:Name=root,并在 XAML 中指定 Binding ElementName=root。要获得 TwoWay 绑定,我需要在调用者中设置 Mode=TwoWay。这是正确的代码:
<src:BlueTextBox BlueText="Binding Path=MyString, Mode=TwoWay" /> <!--OK-->
现在是 UserControl 中的 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>
最后我删除了 UserControl 的构造函数中的 DataContext=this。
public BlueTextBox()
InitializeComponent();
//DataContext = this; -- don't do this
感谢大家的大力帮助!
【问题讨论】:
【参考方案1】:您将 Control 中的 DataContext 设置为自身,因此在其他控件中使用此 Control 时会覆盖 DataContext。以您的绑定为例:
<src:BlueTextBox BlueText="Binding Path=MyString" />
一旦加载并设置了所有 Datacontext,由于您将 DataContext 设置为它,它将在您的 BlueTextBox 事物控件中查找路径 MyString。我想这不是您想要的工作方式;)。
解决方案:
将文本绑定更改为 2 个绑定之一:
Binding RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type src:BlueTextBox, Path=BlueText
或
将您的控件命名为 Root(或类似名称)
<UserControl x:Name="Root"
Binding ElementName=Root, Path=BlueText
并删除
DataContext = this;
来自 UserControl 的构造函数,它应该像魅力一样工作..
【讨论】:
【参考方案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>
【讨论】:
【参考方案3】:您可能需要在属性 FrameworkPropertyMetadata 中添加指定 FrameworkPropertyMetadataOptions.AffectsRender 和 AffectsMeasure。
FrameworkPropertyMetadataOptions enumeration MSDN article
【讨论】:
尝试设置 AffectsRender 和 AffectsMeasure,但这没有任何效果。谢谢。【参考方案4】:我知道这是一个老话题,但仍然如此。
在注册您的 DP 时,还要提及 UIPropertyMetadata 上的 PropertyChangedCallback
【讨论】:
以上是关于数据绑定到 WPF 中的 UserControl的主要内容,如果未能解决你的问题,请参考以下文章
将UserControl绑定到ViewModel(Caliburn Micro WPF)
ItemsControl 中 DataTemplate 中的 WPF UserControl - 如何绑定到 ItemsSource 的父级
从 Catel WPF UserControl 中的 ResourceDictionary 中绑定
WPF 从后面的代码添加的 UserControl 绑定到祖先
如何将 WPF DataGrid DataColumns 可见性绑定到 UserControl 的 ViewModel 上的属性?