1

我正在创建一个带有 DependencyProperty 的 UserControl,但 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();
    }
}
4

3 回答 3

1

UserControl 中的这一行是错误的:

this.DataContext = this;

这使得 UserControl 成为自己的 DataContext,因此绑定正在 UserControl 上查找名为 MyValue 的属性,而该属性不存在。您希望 DataContext 成为您的视图模型。如果您没有明确设置它,它将从其容器(在本例中为 Window)继承 DataContext。

删除那条线,你会更接近。你也不需要那个回调;也删除它。

于 2013-04-23T05:21:03.780 回答
1

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

 <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;
    }

那会成功的。

于 2013-04-23T06:19:26.617 回答
0

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

于 2013-04-23T05:22:14.803 回答