首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DependencyObject没有更新视图

DependencyObject没有更新视图
EN

Stack Overflow用户
提问于 2017-06-29 07:07:28
回答 1查看 68关注 0票数 0

我有一个ViewModel,它是一个DependencyProperty不使用新值更新视图的DependencyObject

一个示例属性( get/set包装器按预期调用)

代码语言:javascript
复制
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被更改时调用)

代码语言:javascript
复制
private static void OnWeaponNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    WeaponSystemVM vm = d as WeaponSystemVM;
    if (vm != null)
    { vm.CommandAddWeaponSystem.RaiseCanExecuteChanged(); }
}

CanExecute Delegate (按预期运行并更新相关的Button)

代码语言:javascript
复制
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

代码语言:javascript
复制
<TextBox x:Name="NameInput" Text="{Binding WeaponName, Mode=TwoWay}" Margin="12,4" RelativePanel.Below="NameAdorner" RelativePanel.AlignLeftWithPanel="True"
                     RelativePanel.AlignRightWithPanel="True"/>

输出TextBlock (不使用新值更新,并且DataContext与输入TextBox相同)

代码语言:javascript
复制
<TextBlock Text="{Binding WeaponName}"/>

令人沮丧的是,似乎只有这个实现不起作用。

为了重现这个问题,我创建了一个独立的项目,没有与我的应用程序相关的所有额外信息,并且视图正在按预期进行更新。

我不明白的是,在这个实现中,哪些操作是不正确的。ViewModel正在按预期进行更新。根据LiveVisualTree,绑定是有效的。

有人能告诉我这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-29 11:10:52

您不应该在您的DependencyProperty中使用ViewModel:它是一个标记类,用于在视图端绑定。过度杀戮,超出了使用的范围。

您应该实现INotifyPropertyChanged,并在要通知UI的每个属性中触发INotifyPropertyChanged.PropertyChanged事件。

类似于:

您的ViewModel从

代码语言:javascript
复制
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中,定义您的属性如下

代码语言:javascript
复制
private string _weaponName;
public string WeaponName
{
    get { return this._weaponName; }
    set { SetAndRaiseIfChanged(ref this._weaponName, value); }
}

更简洁的CanAddSystem

代码语言:javascript
复制
private bool CanAddSystem()
{
    return 
        !string.IsNullOrWhiteSpace(WeaponName)
        && !string.IsNullOrWhiteSpace(WeaponLock)
        && !string.IsNullOrWhiteSpace(WeaponDamage)
        && !string.IsNullOrWhiteSpace(WeaponAttack);
}

使用实现ICommand接口的东西(类似于RelayCommand)构建ViewModel的命令

视图将是

代码语言:javascript
复制
<TextBlock Text="{Binding WeaponName}"/>

您已经完成了:当您将一个ICommand绑定到UI时,系统会自动更新从ViewModel读取它的CanExecute。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44818490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档