2017-02-20 32 views
0

我嘗試做一些簡單的事情,但似乎我錯過了一些東西。當我點擊一個按鈕時,我嘗試更改標籤的內容。我使用MVVM模式來做到這一點。這裏是我的代碼:如何使用mvvm模式更改標籤內容

查看:

<Button x:Name="buttonNext" 
     HorizontalAlignment="Center" 
     VerticalAlignment="Center" 
     Grid.Column="1" 
     Grid.Row="2" 
     Width="85" 
     Height="35" 
     Style="{StaticResource AccentedSquareButtonStyle}" 
     Command="{Binding Path=Next}"> 
     <TextBlock Text="Next" 
       TextWrapping="Wrap" 
       TextAlignment="Center" 
       HorizontalAlignment="Center" 
       VerticalAlignment="Center"/> 
    </Button> 
<Label Name="Path" 
     Grid.ColumnSpan="2" 
     HorizontalAlignment="Center" 
     VerticalAlignment="Center" 
     Content="{Binding path}" 
     FontWeight="Bold" 
     Foreground="DeepSkyBlue" 
     /> 

視圖模型:

public ICommand Next { get; set; } 
    private string _path; 
    public string path 
    { 
     get 
     { 
      return _path; 
     } 
     set 
     { 
      _path = value; 

      RaisePropertyChanged("path"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged = null; 

    protected virtual void RaisePropertyChanged(string propName) 
    { 
     if (PropertyChanged != null) 
     { 
      Task.Run(() => PropertyChanged(this, new PropertyChangedEventArgs(propName))); 
     } 
    } 

    public page4ViewModel(NavigationViewModel navigationViewModel) 
    { 
     _path = "etape1"; 
     Next = new BaseCommand(GoNext); 
    } 

    private void GoNext(object obj) 
    { 
     switch (_path) 
     { 
      case "etape1": 
       _path = "etape2"; 
       break; 
      case : "etape2" 
       _path = "etape3"; 
       break; 
      case "etape3": 
       _path = "etape4"; 
       break; 
      default: 
       _path = " "; 
       break; 

     } 

    } 

最初的標籤是「etape1」在構造函數中,但後來當我點擊下一步按鈕值不會改變。 ps:改變作品的功能,因爲我把一個斷點看。感謝您的幫助

+0

你爲什麼在任務中提升'propertychanged'異步? – Mat

回答

3

你必須使用的財產,不支持字段。

private void GoNext(object obj) 
{ 
    switch (_path) 
    { 
     case "etape1": 
      path = "etape2"; // without underscore 
      break; 
     case : "etape2" 
      path = "etape3"; 
      break; 
     case "etape3": 
      path = "etape4"; 
      break; 
     default: 
      path = " "; 
      break; 

    } 

這將提高通知的變化

編輯

它也更好地使用ViewModelBase您的視圖模型

public abstract class ViewModelBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

在這裏你可以定義

替代

this評論,我們可以引入CallerMemberName

protected virtual void RaisePropertyChanged<T>([CallerMemberName] string propertyName = null) 

另一個有用的變化是基於一個選擇,當你需要從不同的提高它的依賴屬性 setter

protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> selectorExpression) 
    { 
     if (selectorExpression == null) 
      throw new ArgumentNullException("selectorExpression"); 
     MemberExpression body = selectorExpression.Body as MemberExpression; 
     if (body == null) 
      throw new ArgumentException("The body must be a member expression"); 
     RaisePropertyChanged(body.Member.Name); 
    } 
+0

您可能還需要添加[CallerMemberName(https://msdn.microsoft。 com/en-us/library/system.runtime.compilerservices.callermembernameattribute(v = vs.110).aspx)屬性添加到您的RaisePropertyChanged方法中,以便可以在不顯式指定屬性名稱的情況下調用它(因此不需要驗證屬性名稱)。 – Clemens

+0

@Clemens當然,謝謝。既然有時候還需要從另一個setter調用依賴Property,我更願意在'ViewModelBase'中添加另一個版本'Expression > selectorExpression' – 2017-02-20 16:46:36

2

您需要在ui線程上引發屬性已更改的事件。

更換

if (PropertyChanged != null) 
    { 
     Task.Run(() => PropertyChanged(this, new PropertyChangedEventArgs(propName))); 
    } 

if (PropertyChanged != null) 
    { 
     Application.Current.Dispatcher.Invoke(() => PropertyChanged(this, new PropertyChangedEventArgs(propName))); 
    } 

還爲path值不_path

更新

正如評論,DISPA指出tcher.Invoke在這種情況下不是必需的,因爲它已經在UI線程中。

只需撥打

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
+0

你真的需要'Dispatcher'嗎?我幾乎肯定,如果你執行「NextCommand」,你已經在UI線程中... – Mat

+0

不,你說得對。它已經在UI線程中。我只是想特別避免使用Task.Run。 –

+0

這裏'Task.Run'和'Dispatcher.Invoke'都沒有意義。而不是檢查'PropertyChanged!= null',用'PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propName));' – Clemens

0

您a再在改變值:

private void GoNext(object obj) 
{ 
    switch (_path) 
    { 
     case "etape1": 
      _path = "etape2"; 
      break; 
     case : "etape2" 
      _path = "etape3"; 
      break; 
     case "etape3": 
      _path = "etape4"; 
      break; 
     default: 
      _path = " "; 
      break; 

    } 

但是當你正在設置_path,在path設置器還沒有被調用:

public string path 
{ 
    set ///This is never called 
    { 
     _path = value; 
     RaisePropertyChanged("path"); 
    } 
} 

更改爲:

switch (path) 
{ 
    case "etape1": 
     path = "etape2"; 
     break; 
    case : "etape2" 
     path = "etape3"; 
     break; 
    case "etape3": 
     path = "etape4"; 
     break; 
    default: 
     path = " "; 
     break; 

}