数据绑定到 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的主要内容,如果未能解决你的问题,请参考以下文章

WPF - 将 UserControl 可见性绑定到属性

将UserControl绑定到ViewModel(Caliburn Micro WPF)

ItemsControl 中 DataTemplate 中的 WPF UserControl - 如何绑定到 ItemsSource 的父级

从 Catel WPF UserControl 中的 ResourceDictionary 中绑定

WPF 从后面的代码添加的 UserControl 绑定到祖先

如何将 WPF DataGrid DataColumns 可见性绑定到 UserControl 的 ViewModel 上的属性?