2017-02-20 76 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; 

}