自定义依赖属性没有得到绑定的输入

本文关键字:绑定 输入 依赖 属性 自定义 | 更新日期: 2023-09-27 18:10:30

我正在创建一个UserControl与DependencyProperty,但DependencyProperty没有得到调用者传递的值。

我在自己的调查中发现了以下内容

  • 如果我使用内置的用户控件,如TextBlock,一切工作。这将问题缩小到我的UserControl的实现(而不是调用UserControl的代码)

  • 我的属性改变回调,我注册甚至没有被调用(好吧…至少断点没有被击中)

  • 如果只看到这个问题,当我使用绑定提供依赖属性,所以这不起作用:

    <common:MyUserControl MyDP="{Binding MyValue}"/>
    

    但是我没有问题,如果我摆脱绑定和硬编码的值,所以这工作:

    <common:MyUserControl MyDP="hardCodedValue"/>
    

下面是我的UserControl的代码:

public partial class MyUserControl : UserControl
{
    public string MyDP
    {
        get { return (string)GetValue(MyDPProperty); }
        set { SetValue(MyDPProperty, value); }
    }
    public static readonly DependencyProperty MyDPProperty =
        DependencyProperty.Register(
            "MyDP", 
            typeof(string), 
            typeof(MyUserControl),
            new FrameworkPropertyMetadata(
                "this is the default value",
                new PropertyChangedCallback(MyUserControl.MyDPPropertyChanged)));
    public static void MyDPPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        ((MyUserControl)obj).MyDP = (string)e.NewValue;
    }
    public MyUserControl()
    {
        InitializeComponent();
        this.DataContext = this;
    }
}

这里是xaml

<Grid>
    <TextBlock Text="{Binding MyDP}"/>
</Grid>

因为我能够使用内置的用户控件,如TextBlock,我不认为错误在于我的主机代码,但这里是,只是为了让你有一个完整的画面:

<StackPanel>
    <common:MyUserControl MyDP="{Binding MyValue}"/>
</StackPanel>
public class MainWindowViewModel
{
    public string MyValue { get { return "this is the real value."; } }
}
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainWindowViewModel();
    }
}

自定义依赖属性没有得到绑定的输入

UserControl中的这一行是错误的:

this.DataContext = this;

这使得UserControl成为它自己的DataContext,所以绑定在UserControl上寻找一个名为MyValue的属性,而这个属性不存在。您希望DataContext作为您的视图模型。如果你不显式地设置它,它将从它的容器(在这个例子中是Window)继承DataContext。

删掉那一行,你会离得更近。你也不需要那个回调;

你可以这样更新你的控件的视图代码:

 <Grid>
        <TextBlock x:Name="_textBlock"/>
    </Grid>

并在MyDPPropertyChanged方法中设置_textBlock的文本属性:

public static void MyDPPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var control = ((MyUserControl)obj);
        control.MyDP = (string)e.NewValue;
        control._textBlock.Text = control.MyDP;
    }

请在控件和视图模型中实现INotifyPropertyChanged和PropertyChangedEventHandler。其次,使用SetCurrentValue方法在控件类中设置值,而不是直接设置