Wpf 改变视图的有效方法 mvvm

Wpf efficient way of changing the view mvvm

我正在尝试实施 mvvm,但我正在努力寻找一个简单问题的干净解决方案。视图可以有 3 种不同的状态:NewEditable、DisplayOnly、Editable。这个想法是,在每个状态下,按钮的标签和内容将根据状态而变化,例如,按钮将分别为:"Add"、"Edit" 和 "Save"。

目前,vm 具有根据控件状态更新的可绑定属性,但这看起来非常混乱,尤其是在添加了 vm 的其余逻辑时。就像,它只是在玩弦乐。

有没有更好、更简洁的方法?也许耦合将状态作为输入和字符串作为输出的转换器?

您如何根据虚拟机的状态更改视图?

我当前的 ViewModel 仅用于视图逻辑,您可以看到大量样板文件:

public class ViewModel : NotifyPropertyChangedBase
{
    public enum State { New, Edit, DisplayOnly }

    public ViewModel()
    {
        // Set commands
        Edit = new CommandHandler(param => EditAction(), () => true);
        EndEdit = new CommandHandler(param => EndEditAction(), () => true);

        /*
         * Some more logic to set up the class 
         */
    }

    public ICommand Edit { get; private set; }
    public ICommand EndEdit { get; private set; }

    public State DisplayState
    {
        get { return _displayState; }
        private set { SetProperty(ref _displayState, value, nameof(DisplayState)); } // from the base to simply the logic
    }

    public string ControlTitle
    {
        get { return _controlTitle; }
        private set { SetProperty(ref _controlTitle, value, nameof(ControlTitle)); } // from the base to simply the logic
    }

    public string ButtonTitle
    {
        get { return _buttonTitle; }
        private set { SetProperty(ref _buttonTitle, value, nameof(ButtonTitle)); } // from the base to simply the logic
    }

    private State _displayState = State.New;
    private string _controlTitle = CONTROL_TITLE_NEW;
    private string _buttonTitle = BUTTON_TITLE_NEW;

    public const string CONTROL_TITLE_NEW = "New Object"; // Could be removed as used once in the example
    public const string CONTROL_TITLE_DISPLAY = "Display Object";
    public const string CONTROL_TITLE_EDIT = "Edit Object";

    public const string BUTTON_TITLE_NEW = "Create"; // Could be removed as used once in the example
    public const string BUTTON_TITLE_DISPLAY = "Edit";
    public const string BUTTON_TITLE_EDIT = "Save";

    private void EditAction()
    {
        DisplayState = State.Edit;
        ControlTitle = CONTROL_TITLE_EDIT;
        ButtonTitle = BUTTON_TITLE_EDIT;

        // Some business logic
    }

    private void EndEditAction()
    {
        DisplayState = State.DisplayOnly;
        ControlTitle = CONTROL_TITLE_DISPLAY;
        ButtonTitle = BUTTON_TITLE_DISPLAY;

        // Some business logic
    }

    /*
     * Rest of the logic for the class 
     */
}

我会将您的 VM 分成 4 个,"the common functionality VM" 和 3 个用于您的不同状态,这样您就不必编写开关来更改状态。相反,您将在 VM 之间切换(并且可能在视图之间切换)。

这个问题有多种解决方法。

  1. 最简单的方法是在 viewmodel 上拥有 2 个属性:ButtentText 和 LabelText。 returns 值绑定到 UI 并使用内部开关 select 它应该是什么文本。
  2. 'More correct' 方法是有 2 个转换器,它们基本上做同样的事情:将枚举转换为某种显示值(按钮和标签)。我不建议这样做,因为第一种方法更简单。
  3. 每个状态有 3 个 viewModel 看起来不错,但只是有想法,未来这些 viewModel 会发生不同的事情,它们会分开。如果不是-那就太过分了。如果未来会有所不同,您可以随时更改实施方式

我会选择第一个解决方案,除非你的 viewModel 是 +500 行并且很难维护

如果您想根据视图模型更改视图,我建议您阅读有关 DataTemplate 和 DataType 的内容。但在这种方法中,将有 1 个父视图模型,它保存它应该显示的状态,以及 3 个子视图模型。然后使用绑定的当前 viewModel(3 个之一)创建 parentView 和内部控件,并使用数据类型显示正确的视图