我有一个ViewModel,它是一个DependencyProperty不使用新值更新视图的DependencyObject。
一个示例属性( get/set包装器按预期调用)
public static readonly DependencyProperty WeaponNameProperty = DependencyProperty.Register(
"WeaponName",
typeof(string),
typeof(WeaponSystemVM),
new PropertyMetadata(null, new PropertyChangedCallback(OnWeaponNameChanged)));
public string WeaponName
{
get { return (string)GetValue(WeaponNameProperty); }
set { SetValue(WeaponNameProperty, value); }
}Callback (当WeaponName被更改时调用)
private static void OnWeaponNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
WeaponSystemVM vm = d as WeaponSystemVM;
if (vm != null)
{ vm.CommandAddWeaponSystem.RaiseCanExecuteChanged(); }
}CanExecute Delegate (按预期运行并更新相关的Button)
private bool CanAddSystem()
{
if (string.IsNullOrWhiteSpace(WeaponName)) return false;
if (string.IsNullOrWhiteSpace(WeaponLock)) return false;
if (string.IsNullOrWhiteSpace(WeaponDamage)) return false;
if (string.IsNullOrWhiteSpace(WeaponAttack)) return false;
return true;
}输入TextBox
<TextBox x:Name="NameInput" Text="{Binding WeaponName, Mode=TwoWay}" Margin="12,4" RelativePanel.Below="NameAdorner" RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"/>输出TextBlock (不使用新值更新,并且DataContext与输入TextBox相同)
<TextBlock Text="{Binding WeaponName}"/>令人沮丧的是,似乎只有这个实现不起作用。
为了重现这个问题,我创建了一个独立的项目,没有与我的应用程序相关的所有额外信息,并且视图正在按预期进行更新。
我不明白的是,在这个实现中,哪些操作是不正确的。ViewModel正在按预期进行更新。根据LiveVisualTree,绑定是有效的。
有人能告诉我这个问题吗?
发布于 2017-06-29 11:10:52
您不应该在您的DependencyProperty中使用ViewModel:它是一个标记类,用于在视图端绑定。过度杀戮,超出了使用的范围。
您应该实现INotifyPropertyChanged,并在要通知UI的每个属性中触发INotifyPropertyChanged.PropertyChanged事件。
类似于:
您的ViewModel从
public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void SetAndRaiseIfChanged<T>(
ref T backingField,
T newValue,
[CallerMemberName] string propertyName = null)
{
if (!object.Equals(backingField, newValue))
return;
backingField = newValue;
this.RaisePropertyChanged(propertyName);
}
}在您的ViewModel中,定义您的属性如下
private string _weaponName;
public string WeaponName
{
get { return this._weaponName; }
set { SetAndRaiseIfChanged(ref this._weaponName, value); }
}更简洁的CanAddSystem
private bool CanAddSystem()
{
return
!string.IsNullOrWhiteSpace(WeaponName)
&& !string.IsNullOrWhiteSpace(WeaponLock)
&& !string.IsNullOrWhiteSpace(WeaponDamage)
&& !string.IsNullOrWhiteSpace(WeaponAttack);
}使用实现ICommand接口的东西(类似于RelayCommand)构建ViewModel的命令
视图将是
<TextBlock Text="{Binding WeaponName}"/>您已经完成了:当您将一个ICommand绑定到UI时,系统会自动更新从ViewModel读取它的CanExecute。
https://stackoverflow.com/questions/44818490
复制相似问题