如何 create/use 读取时生成其值的 DependencyProperty?

How to create/use a DependencyProperty that generates its value when read?

我想创建一个 DependencyProperty 每次读取都会生成一个值;例如类似于:

private static Random _rng = new Random();

public int RandomNumber
{
    get
    {
        int x = _rng.Next();
        SetValue(RandomNumberProperty, x);
        return x;
    }
}
private static readonly DependencyPropertyKey RandomNumberProperty = DependencyProperty.RegisterReadOnly(nameof(RandomNumber), typeof(int), typeof(Window1), new PropertyMetadata(-1));

并用这个属性补一个CommandParameter;例如:

public static RoutedUICommand CmdRandomNumber = new RoutedUICommand() { Text = "Use a random number supplied as parameter." };

private void ExecuteShowMessage(object sender, ExecutedRoutedEventArgs e)
{
    MessageBox.Show($"And the winner is ... {(int)e.Parameter}" );
}

private void CanExecuteShowMessage(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

并在 XAML 中:

<Window DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Window.CommandBindings>
        <CommandBinding Command="{x:Static local:Window1.CmdRandomNumber}"
                        Executed="ExecuteShowMessage"
                        CanExecute="CanExecuteShowMessage" />
        </CommandBinding>
    </Window.CommandBindings>
    <Button Command="{x:Static local:Window1:CmdRandomNumber}"
            CommandParameter="{Binding RandomNumber}"/>
</Window>

但是,这不起作用:ExecuteShowMessage 总是收到初始值。可能是因为 DependencyProperty 没有收到有关值更改的通知,并且当 DependencyProperty 的值被请求时,它 returns 它的缓存值而不是从 RandomNumber 中检索它。

我想给不同的按钮绑定不同的参数,让每个按钮执行相同的命令;因此我尝试使用 CommandParameters 而不是从 ExecuteShowMessage.

中读取 RandomValue

如何实现可用于 WPF 数据绑定并在每次读取时生成其值的 属性?以及如何确保读取其支持属性而不是 DependencyProperty 依赖于其缓存值? (特别是在 CommandParameters 的上下文中。)

How to implement a property that can be used in WPF databindings that generates its value each time it is read?

WPF 绑定的来源 属性 可以是普通的 CLR 属性,像这样:

public int RandomNumber
{
    get { return _rng.Next(); }
}

如果您需要强制更新绑定以读取新的 属性 值,则拥有 属性 的 class 可以实现 INotifyPropertyChanged 接口,并在必要时触发 PropertyChanged 事件,例如:

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("RandomNumber"));