x:bind UI在UWP中的PropertyChanged时不更新

时间:2019-03-25 12:12:00

标签: c# mvvm uwp

我正在使用x:BindINotifyPropertyChanged更新UWP应用程序中的UI。但是,即使我将其设置为OneTime,它的行为也像OneWay绑定。

Bindings.Update()有效,但是我想知道为什么INotifyPropertyChanged失败。

XAML

<TextBlock Text="{x:Bind staffVM.Name, Mode=OneWay}"/>

隐藏代码:

private StaffViewModel staffVM;
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // I want to change staffVM according to ListView's selection.
    staffVM = staffListView.SelectedItem as StaffViewModel;
    staffVM.Update(); // If change this to Bindings.Update(), It works.
}

ViewModel:

public class StaffViewModel: INotifyPropertyChanged
{
    private Character character;
    public string Name => character.name == string.Empty ? null : character.name;
    public void Update()
    {
        RaisePropertyChanged(string.Empty);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged([CallerMemberName]string propName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

2 个答案:

答案 0 :(得分:0)

首先,您需要指定要更新的变量的名称:

public void Update()
{
    RaisePropertyChanged(nameof(Name));
}

文档和样本:https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.inotifypropertychanged.propertychanged

第二,默认情况下,x:Bind为OneTime 要修复此问题,请添加Mode="OneWay"

  

Mode将绑定模式指定为以下字符串之一:“ OneTime”,“ OneWay”或“ TwoWay”。默认值为“ OneTime”。请注意,这与{Binding}的默认设置不同,在大多数情况下,默认设置为“ OneWay”。

请阅读文档 https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup-extension

答案 1 :(得分:0)

这里的问题不在StaffViewModel类的级别上,而是在页面的级别上。当您这样做时:

staffVM = staffListView.SelectedItem as StaffViewModel;

UI不会通知staffVM字段已更改的事实。因此,绑定仍指向StaffViewModel的旧实例。因此,当您执行staffVM.Update()时,它确实会发出有关更改的通知,但UI不在侦听该实例-它仍在侦听有关第一个选定项目的通知。 Bindings.Update()修复了此问题,因为它完全重新评估了所有绑定,因此它将“获取” staffVM字段的新值。

解决方案是在INotifyPropertyChanged上实现Page并将staffVM封装在引发PropertyChanged事件的属性中。

但是理想情况下,我建议创建一个“根”视图模型,您只需设置一次即可,并且不会更改,并且将所选项目作为其属性。这样,您就不必在INotifyPropertyChanged中实现Page了,其后面的代码将更加简单。结果,您将在后面的代码中看到以下内容:

public RootViewModel VM {get;} = new RootViewModel();

在XAML中:

<TextBlock Text="{x:Bind VM.SelectedStaff.Name, Mode=OneWay}"/>