如何创建/使用在读取时生成其值的DependencyProperty?

问题描述:

我想创建一个DependencyProperty,每次读取它时都会生成一个值;例如例如:如何创建/使用在读取时生成其值的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的值时,它将返回其缓存值,而不是从RandomNumber中检索该值。

我想将不同的参数绑定到不同的按钮,并让每个按钮执行相同的命令;因此我尝试使用CommandParameters而不是从ExecuteShowMessage中读取RandomValue

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

+1

依赖属性是不应该这样的。它的CLR包装器不得在get和set访问器中调用GetValue和SetValue以外的其他任何东西。但是,如果该属性作为绑定的来源,则不需要是依赖项属性。 – Clemens

+0

您不能确保CLR包装器总是用于检索依赖项属性的值。而GetValue和SetValue方法不是虚拟的,所以你不能覆盖它们。无论你想要做什么,你都应该考虑另一种方法。 – mm8

+0

最后一个参数是DP - 'new PropertyMetadata(-1)'是默认值。如果您可以找出一种方法来返回预先创建的静态随机值而不是-1,那么您可能会成功采用这种方法。 –

如何实现能够在WPF数据绑定中使用的是 产生其值在每次读出时间的属性?

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

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

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

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