我已经简化了应用以显示我的问题
当我点击按钮时,它会更改Text
的{{1}}属性并更新ViewModel
。
MainPage.xaml中
TextBlock.Text
MainPage.xaml.cs中
<StackPanel>
<Button Click="ButtonBase_OnClick">Button to change text</Button>
<TextBlock Text="{x:Bind ViewModel.Text, Mode=OneWay}"></TextBlock>
</StackPanel>
ViewModel 类有一个字符串属性(Text)并实现了 INotifyPropertyChange 接口。
问题在ctor中未设置 public MainPage()
{
ViewModel = new ViewModel();
this.InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
ViewModel.Text = "x:Bind works";
}
时启动(即viewModel为null并在运行时更改):
ViewModel
Complited 绑定不起作用(文本未更改)我无法弄清楚为什么会这样...我需要从null更改viewModel(vm为null因为它正在等待真实应用中的一些数据)
答案 0 :(得分:2)
{x:Bind} 绑定(通常称为编译绑定)使用生成的代码来实现其好处。在XAML加载时, {x:Bind} 将转换为您可以将其视为绑定对象的内容,并且此对象从数据源上的属性获取值。这些生成的代码可以在 obj
文件夹中找到,其名称类似于(对于C#) <view name>.g.cs
强>
对于您的代码,生成的代码如下:
// Update methods for each path node used in binding steps.
private void Update_(global::UWP.BlankPage3 obj, int phase)
{
if (obj != null)
{
if ((phase & (NOT_PHASED | DATA_CHANGED | (1 << 0))) != 0)
{
this.Update_ViewModel(obj.ViewModel, phase);
}
}
}
private void Update_ViewModel(global::UWP.ViewModel obj, int phase)
{
this.bindingsTracking.UpdateChildListeners_ViewModel(obj);
if (obj != null)
{
if ((phase & (NOT_PHASED | DATA_CHANGED | (1 << 0))) != 0)
{
this.Update_ViewModel_Text(obj.Text, phase);
}
}
}
...
private global::UWP.ViewModel cache_ViewModel = null;
public void UpdateChildListeners_ViewModel(global::UWP.ViewModel obj)
{
if (obj != cache_ViewModel)
{
if (cache_ViewModel != null)
{
((global::System.ComponentModel.INotifyPropertyChanged)cache_ViewModel).PropertyChanged -= PropertyChanged_ViewModel;
cache_ViewModel = null;
}
if (obj != null)
{
cache_ViewModel = obj;
((global::System.ComponentModel.INotifyPropertyChanged)obj).PropertyChanged += PropertyChanged_ViewModel;
}
}
}
在这里,我只是复制一些与您的问题相关的方法。通过这些方法,您可以在更新TextBlock
或PropertyChanged
听众之前发现,它会检查ViewModel
是否为null
。如果是null
,则不会执行任何操作。因此,要使 {x:Bind} 工作,我们必须在加载页面之前初始化ViewModel
。这就是为什么 {x:Bind} 在ViewModel
事件中初始化Button.Click
时无效的原因。
要解决此问题,您可以为INotifyPropertyChanged
实施ViewModel
接口,例如Filip说,以便在ViewModel
更改时(从null
更改为{},可以通知生成的代码{1}})并更新UI。
但我认为你可以在构造函数中初始化new ViewModel()
。初始化ViewModel
时,您可以首先设置等待ViewModel
的属性:
null
然后在您的日期准备就绪时更新这些属性。这样,您就无法在页面上实现public MainPage()
{
ViewModel = new ViewModel() { Text = null };
this.InitializeComponent();
}
界面。
除了这些,还有另一种更便宜的方法,你可以调用INotifyPropertyChanged
方法来强制在初始化this.Bindings.Update();
之后更新绑定:
ViewModel
答案 1 :(得分:0)
您是否在页面上实现了INotifyPropertyChanged
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private ViewModel viewModel;
public ViewModel ViewModel
{
get { return viewModel; }
set
{
viewModel = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ViewModel)));
}
}
public MainPage()
{
ViewModel = new ViewModel { };
this.InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
ViewModel = new ViewModel { };//this line has been added
ViewModel.Text = "x:Bind does not work";
}
public event PropertyChangedEventHandler PropertyChanged;
}
这适合我。