绑定值的依赖属性不起作用

12

我有一个具有依赖属性的用户控件。

public sealed partial class PenMenu : UserControl, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }         

    public bool ExpandCollapse
    {
        get
        {
            return false;
        }

        set
        {
            //code
        }
    }
public static readonly DependencyProperty ExpandCollapseProperty = DependencyProperty.Register("ExpandCollapse", typeof(bool), typeof(PenMenu), null);
//some more code
}

我在XAML页面中赋值如下:

<Controls:PenMenu x:Name="penMenu" Opened="Menu_Opened" 
                         ExpandCollapse="{Binding PenMenuVisible}" />

但它并没有触发用户控件中的ExpandCollapse属性的GET-SET部分。 因此,我添加了布尔转换器,只是为了检查绑定时传递的值,例如:

<Controls:PenMenu x:Name="penMenu" Opened="Menu_Opened" 
                         ExpandCollapse="{Binding PenMenuVisible, Converter={StaticResource booleanToBooleanConverter}}" />

在转换器中设置断点,我看到传递的值是正确的。为什么它没有分配给依赖属性可能的原因是什么?

另外,在 XAML 页面中如果我这样说:

<Controls:PenMenu x:Name="penMenu" Opened="Menu_Opened" 
                         ExpandCollapse="true"/>

然后它会进入用户控件中ExpandCollapse属性的GET-SET部分。我卡住了,感觉很奇怪,请帮忙。


常见问题。很抱歉你遇到了。请看下面我的答案。 - Jerry Nixon
对于开发人员,请注意当框架更新依赖属性时,它不使用CLR属性,而是直接读写dp,这就是为什么您必须使用更改事件的原因。 - Jerry Nixon
2个回答

23

这很令人沮丧,不是吗?首先,要包含一个已更改的事件处理程序。就像这样:

public string Title
{
    get { return (string)GetValue(TitleProperty); }
    set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
    DependencyProperty.Register("Title", typeof(string), 
    typeof(MyControl), new PropertyMetadata(string.Empty, Changed));
private static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var c = d as MyControl;
    // now, do something
}

那么,请阅读这篇文章,以便了解除此之外的其他问题:http://blog.jerrynixon.com/2013/07/solved-two-way-binding-inside-user.html

祝你好运!


太好了!那个东西起作用了。 但是MSDN上的例子 [http://msdn.microsoft.com/library/windows/apps/br242362] 在PropertyMetaData中传递null。 我认为这可以在没有绑定的情况下工作...非常感谢Jerry :) - ashish nirkhe
为什么,为什么会这样?我花了好几天时间解决这个问题。为什么设置UserControl本身的DataContext会表现出这样的行为? - Timo
1
哦,我的天啊...感谢你的博客文章!那在某种程度上帮了我很多。 - j00hi

5

依赖属性的getter和setter不能保证被执行,特别是WPF绑定引擎/XAML处理器已记录在文档中绕过这些。请参阅MSDN - getter/setter应该只是DependencyPropertyGetValue/SetValue的包装。

不要在属性的setter中做出反应,而是应在对DependencyProperty.Register的原始调用中添加属性更改处理程序,在那里您可以对新值进行操作。

(参见other questions)。


谢谢你,尼古拉斯,这解释了基础 :) - ashish nirkhe
令人困惑的是,如果您从代码后台访问CLR属性,它们将被使用,但在XAML中不会。因此,您可能会遇到似乎工作不一致的情况。为了完全避免这个问题,最佳实践是使CLR属性仅成为依赖属性的包装器。 - StayOnTarget

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接