如何修改依赖项属性的设置器值

本文关键字:属性 设置 依赖 何修改 修改 | 更新日期: 2023-09-27 18:06:57

我有一个简单的依赖属性。我有一个带有按钮的用户控件。我希望调用者设置一个名为MyName的属性为"Hello"。我希望依赖属性代码将字符串"World"附加到末尾。下面是我尝试的代码:

#region MyNAME DEPENDENCY PROPERTY
private string _myName;
public string MyName
{
    get { return this._myName; } //a breakpoint here never trips
    set
    {
        this._myName = value;
        this.OnPropertyChanged("MyName");
    }
}
public string MyName2 { get { return this._myName; } } //a breakpoint here will trip
public static readonly DependencyProperty MyNameProperty = DependencyProperty.Register("MyName", typeof(string), typeof(MyTabControl), new PropertyMetadata("", OnMyNamePropertyChanged));
private static void OnMyNamePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
    MyTabControl myUserControl = dependencyObject as MyTabControl;
    myUserControl.OnMyNamePropertyChanged(e);
    myUserControl.OnPropertyChanged("MyName");
}
private void OnMyNamePropertyChanged(DependencyPropertyChangedEventArgs e)
{
    this.MyName = (string)e.NewValue + " World";
}
#endregion //end MyNAME
我的按钮XAML代码看起来像:
<Button Content="{Binding Path=MyName, Mode=OneWay}" />

当我加载一个具有如下控件的页面时:

<local:MyTabControl MyName="Hello" />

我得到一个显示"Hello"的按钮,而不是显示"Hello World"的按钮。奇怪的是,如果我将按钮XAML代码改为使用MyName2,如下所示:

<Button Content="{Binding Path=MyName2, Mode=OneWay}" />

它的工作原理。getter代码是相同的(我在上面包含了它)。我猜获得_myName的代码比我预期的更早被调用。我也不希望MyName getter永远不会被调用。当我在这里放一个断点时,它不会出错。但是,当我将按钮绑定路径更改为使用MyName2时,该getter上的断点会出错。

我在这里做错了什么?我如何使用MyName属性并让我的按钮显示"Hello World"(当然不使用第二个getter)

编辑:添加新代码。

我接受了你的建议,把我的c#代码改成了这样:

public string MyName
{
    get { return (string)GetValue(MyNameCustomProperty); }
    set { SetValue(MyNameCustomProperty, value + " World"); }
}
public static DependencyProperty MyNameCustomProperty = DependencyProperty.Register("MyName", typeof(string), typeof(MyTabControl));

(我仍然是新的依赖属性)我仍然有相同的问题,因为我有我以前的代码。我能用这段代码做点什么吗?

如何修改依赖项属性的设置器值

看起来我需要强制值。我是这样做的:

public string MyName
{
    get { return (string)GetValue(MyNameCustomProperty); }
    set { SetValue(MyNameCustomProperty, value); }
}
public static DependencyProperty MyNameCustomProperty = DependencyProperty.Register("MyName", typeof(string), typeof(MyTabControl), new PropertyMetadata("", MyPropertyChanged, CoerceCurrentReading));
private static void MyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    //contains coerced value
}
private static object CoerceCurrentReading(DependencyObject d, object value)
{
    MyTabControl tab = (MyTabControl)d;
    return (string)value + " World";
}

这看起来是将XAML代码输入的值从"Hello"更改为"Hello World"的最干净的方法。

这里的部分问题是您没有使用真正的依赖属性。为了使用依赖属性,你需要使用实际的依赖属性存储,而不是一个字段。这个后备存储是binding等项的值所在的位置。将代码更改为以下内容,并删除后面的字段

public string MyName
{
    get { return (string)this.GetValue(MyNameProperty); }
    set { this.SetValue(MyNameProperty, value); }
}

您想要更改通知发生之前设置的值。最简单的解决方案是将后备字段的值设置为所需值,然后通知:

public string MyName
{
    get { return this._myName; } //a breakpoint here never trips
    set
    {
        this._myName = (string)value + "World!";
        this.OnPropertyChanged("MyName");
    }
}

您遇到的问题是您设置了支持字段。然后你通知,它告诉UI更新,以及触发OnNotifyPropertyChanged。OnNotifyPropertyChanged在属性改变后被调用,当你尝试改变后备字段时