在XAML中如何判断一个DependencyProperty是否被设置了值

10
我有一个控件,它暴露了一个叫做PlacementTarget的DP(它绑定到一个子Popup,FWIW)。我想要做的是,如果在XAML中未设置PlacementTarget,则(该控件会)将其设置为该控件所在的窗口。当我说“未设置”时,我不是指“为空”(这允许用户开发人员将PlacementTarget设置为null,而控件不会自动将其设置为窗口)。
我有一个名为placementTargetIsSet的字段,在Change事件处理程序中将其设置为true。
public readonly static DependencyProperty PlacementTargetProperty =
    DependencyProperty.Register(
        "PlacementTarget", typeof(UIElement), typeof(MyControl),
        new PropertyMetadata(new PropertyChangedCallback(PlacementTargetChanged)));

static void PlacementTargetChanged(
    DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    MyControl ctrl = (sender as MyControl);
    ctrl.placementTargetIsSet = true;
}

public UIElement PlacementTarget
{
    get { return (UIElement)GetValue(PlacementTargetProperty); }
    set { SetValue(PlacementTargetProperty, value); }
}

然而,我发现当OnApplyTemplate或Loaded事件发生时,更改事件是在它们之后发生的。也就是说,当OnApplyTemplate或Loaded发生时,placementTargetIsSet==false,无论是否已经设置了PlacementTarget(在XAML中)。

那么我什么时候可以安全地假定PlacementTarget尚未设置?

1个回答

17

不需要额外的placementTargetIsSet字段,因此也不需要PropertyChangedCallback

要想知道是否为PlacementTarget属性设置了值,只需要调用ReadLocalValue方法,并测试它是否返回DependencyProperty.UnsetValue:

bool placementTargetIsSet =
    ReadLocalValue(PlacementTargetProperty) != DependencyProperty.UnsetValue;

我来晚了,但是我无法表达对你的感谢之情。这个答案解决了我一年左右的问题,问题出在一个帮助类上,用于设置网格中所有元素的属性。 - Kilazur
哇...我断断续续地在WPF上工作了好几年,从来不知道这个方法的存在。 - TyCobb
如果您有一个带有自定义样式的控件,则不起作用。 我所有的属性都是“未设置”,即使其中一些具有绑定。 - Dominic Jonas
@DominicJonas 这不应该使用样式设置器中的值,因为它们不是本地值。 - Clemens
1
@Clemens 啊,那我可能误解了一些东西。是否也可以知道它是否设置在 xaml 中?否则我就得选择使用 propChanged 和 bool 标志的解决方法。 - Dominic Jonas
@Dominic 无论是 XAML 还是其他方式都不重要。它只需要是一个本地值,例如直接设置(在代码或 XAML 中)或通过绑定设置。请参见此处:https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/dependency-property-value-precedence#dependency-property-setting-precedence-list - Clemens

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