2016-07-07 158 views
2

我已经简化了应用程序,以显示我的问题更改视图模型

当我点击按钮,它改变了ViewModelTextBlock.TextText属性更新。

MainPage.xaml中

<StackPanel> 
    <Button Click="ButtonBase_OnClick">Button to change text</Button> 
    <TextBlock Text="{x:Bind ViewModel.Text, Mode=OneWay}"></TextBlock> 
</StackPanel> 

MainPage.xaml.cs中

public MainPage() 
    { 
     ViewModel = new ViewModel(); 
     this.InitializeComponent(); 
    } 
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
    { 
     ViewModel.Text = "x:Bind works"; 
    } 

视图模型类具有一个字符串属性(文本)和实施INotifyPropertyChange接口。


问题启动时ViewModel没有在构造函数设置(即视图模型为空,并在运行时更改):

public MainPage() 
    { 
     //ViewModel = new ViewModel();//this line has been removed 
     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"; 
    } 

Complited 约束力不工作(文字不变)我无法弄清楚为什么它是这样的...我需要从null(vm为null,因为它正在等待一些实际应用中的数据)viewModel

+0

当然,因为没有那个视图模型已经改变的通知 –

+0

您的意思是ViewModel属性?我怎样才能通知变化 - 我不想在MainPage中实现INotifyPropertychange – Alamakanambra

+0

没有魔法,你必须通知页面ViewModel的内容已经改变。不管你如何做,但你必须 –

回答

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; 
} 

这对我的作品。

1

{x:绑定}绑定(通常称为编译绑定)使用生成的代码来实现其优点。在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; 
     } 
    } 
} 

在这里,我只是复制了一些有关您的问题的方法。从这些方法中,您可以发现在更新TextBlockPropertyChanged听众之前,它会检查ViewModel是否为null。如果是null,什么都不会做。所以要使{x:Bind}工作,我们必须在加载页面之前初始化ViewModel。这就是为什么{x:Bind}Button.Click事件中初始化ViewModel时不起作用。

要解决这个问题,你可以实现INotifyPropertyChanged接口ViewModel像菲利普说,这样,当改变ViewModel(从nullnew ViewModel())生成的代码可以被通知和更新你的UI。

但我想你可以在构造函数中初始化ViewModel。当初始化ViewModel,你可以设置你先等着到null喜欢的属性:

public MainPage() 
{ 
    ViewModel = new ViewModel() { Text = null }; 
    this.InitializeComponent(); 
} 

然后当你的约会准备更新这些属性。通过这种方式,您可以不在页面上实现INotifyPropertyChanged界面。

除了这些之外,还有另一种便宜的方式,你可以调用this.Bindings.Update();方法强制绑定更新初始化ViewModel喜欢以下后:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
{ 
    ViewModel = new ViewModel(); 
    ViewModel.Text = "x:Bind does not work"; 
    this.Bindings.Update(); 
}