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 之间切换(并且可能在视图之间切换)。
这个问题有多种解决方法。
- 最简单的方法是在 viewmodel 上拥有 2 个属性:ButtentText 和 LabelText。 returns 值绑定到 UI 并使用内部开关 select 它应该是什么文本。
- 'More correct' 方法是有 2 个转换器,它们基本上做同样的事情:将枚举转换为某种显示值(按钮和标签)。我不建议这样做,因为第一种方法更简单。
- 每个状态有 3 个 viewModel 看起来不错,但只是有想法,未来这些 viewModel 会发生不同的事情,它们会分开。如果不是-那就太过分了。如果未来会有所不同,您可以随时更改实施方式
我会选择第一个解决方案,除非你的 viewModel 是 +500 行并且很难维护
如果您想根据视图模型更改视图,我建议您阅读有关 DataTemplate 和 DataType 的内容。但在这种方法中,将有 1 个父视图模型,它保存它应该显示的状态,以及 3 个子视图模型。然后使用绑定的当前 viewModel(3 个之一)创建 parentView 和内部控件,并使用数据类型显示正确的视图
我正在尝试实施 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 之间切换(并且可能在视图之间切换)。
这个问题有多种解决方法。
- 最简单的方法是在 viewmodel 上拥有 2 个属性:ButtentText 和 LabelText。 returns 值绑定到 UI 并使用内部开关 select 它应该是什么文本。
- 'More correct' 方法是有 2 个转换器,它们基本上做同样的事情:将枚举转换为某种显示值(按钮和标签)。我不建议这样做,因为第一种方法更简单。
- 每个状态有 3 个 viewModel 看起来不错,但只是有想法,未来这些 viewModel 会发生不同的事情,它们会分开。如果不是-那就太过分了。如果未来会有所不同,您可以随时更改实施方式
我会选择第一个解决方案,除非你的 viewModel 是 +500 行并且很难维护
如果您想根据视图模型更改视图,我建议您阅读有关 DataTemplate 和 DataType 的内容。但在这种方法中,将有 1 个父视图模型,它保存它应该显示的状态,以及 3 个子视图模型。然后使用绑定的当前 viewModel(3 个之一)创建 parentView 和内部控件,并使用数据类型显示正确的视图