2016-07-07 193 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(); 
}