我正在使用x:Bind
和INotifyPropertyChanged
更新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));
}
}
答案 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}"/>