如何使用mvvm模式

时间:2017-02-20 16:14:35

标签: c# wpf button mvvm label

我尝试做一些简单的事情,但似乎我想念一些事情。当我点击按钮时,我尝试更改标签的内容。我使用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"
       />

ViewModel:

    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:改变的功能是因为我设置了一个断点来看。谢谢你的帮助

3 个答案:

答案 0 :(得分: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进行ViewModel

也会更好
public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

您可以在其中定义

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        this.VerifyPropertyName(propertyName);

        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

<强>替代

根据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);
    }

答案 1 :(得分: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

的值

<强>更新

正如评论中所指出的,在这种情况下,Dispatcher.Invoke不是必需的,因为它已经在UI线程上。

致电

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

答案 2 :(得分:0)

您正在更改以下值:

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中的setter从未被调用过:

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;

}