2011-02-06 135 views
9

我是MVVM的新手,我决定继续前行,并在即将到来的项目中开始采用它。在MVVM中切换视图模式和编辑模式?

我已经阅读了这个相关的问题和答案,但我不知道这将如何与MVVM实现。

我希望我项目中的所有视图都有2种模式,编辑模式和视图模式。
我不希望用户在默认情况下查看所有字段的文本框,我宁愿让他们看到TextBlocks(或将所有TextBoxe s'设为IsReadOnly属性为true(通过样式等,你告诉我..)

当用户打开实体时,通常应该是TextBlocks,Labels(或只读文本框)等,如果他点击“编辑”(如果他有权限),它应该进入编辑模式,所有该字段的标签应该被反转,以文本框(RichTextBoxes等,组合框或其他任何可编辑的字段不只是标签)。

我敢肯定,我没有这个问题的唯一一个,我想听听从专家什么是切换b的最有效的方法在纯MVVM中使用这些模式,以及为它声明两个单独的视图是否很常见。

请参阅一篇很好的文章,解释如何做到这一点(也许它是由Visual State?IDK完成的)。

UPDATE
我想知道什么,而不是怎么样,我的问题是关于模式,是应该从我查看模式在任的V或虚拟机分开编辑模式 ? 所以请在回答中强调这些细节。

在此先感谢。

回答

10

使用IsReadOnly属性的文本框和绑定,为“编辑模式”属性:

<TextBox .... IsReadOnly={Binding IsViewMode} ... /> 

然后在您的视图模型:

public bool IsViewMode 
{ 
    get { return _IsViewMode; } 
    set 
    { 
     _IsViewMode= value; 
     // Call NotifyPropertyChanged when the source property is updated. 
     NotifyPropertyChanged("IsViewMode"); 
    } 
} 

IsViewMode默认为true和切换当用户点击“编辑”时到false。绑定将立即使所有文本框都可编辑。

您可以对其他控件执行相同的操作 - 尽管在这些情况下您将需要绑定的属性为IsEnabled - 尽管您已将控件变灰。

换出文本块和你的控制,你需要通过一对转换器的有由IsViewMode属性控制两种控制在网格共享相同的位置和自己的知名度:

<TextBlock Grid.Row="1" Grid.Column="2" ... 
      Visiblity={Binding IsViewMode, Converter=DirectConverter} ... /> 
<ComboBox Grid.Row="1" Grid.Column="2" ... 
      Visiblity={Binding IsViewMode, Converter=InvertedConverter} ... /> 

直接转换器:

return IsViewMode ? Visibility.Visible : Visibility.Collapsed; 

的反向转换器:

return IsViewMode ? Visibility.Collapsed : Visibility.Visible; 
+0

那么其他领域呢?我说我想要一些字段反转为DropDown,一些是滑块,一些是日期选择器,而在视图模式下,它们都是简单的TextBlocks /标签?这对我来说非常重要。 – Shimmy 2011-02-07 00:09:25

+0

@Shimmy - 对不起,我错过了那一点(不知道为什么)。您可以对ComboBoxes执行相同的操作,但它可能是您需要绑定到的`IsEnabled`属性。 – ChrisF 2011-02-07 00:11:17

+0

所以你基本上说我应该为编辑/视图模式制定一个共同的视图,让所有控件声明一个靠近另一个设置IsReadOnly或Visibility控件到VM上的IsViewMode(使用BooleanToVisibility转换器控件隐藏),是那对吗? **我已经添加了一些内容到我的问题。** – Shimmy 2011-02-07 00:50:03

2

Viewmodel:我绝对会保留一个ViewMode属性的Viewmodel,这很像ChrisF的回答中所述。单独的ViewModels只会不雅观。

查看:我看到它,至少有三个选项,各有利弊。

  1. 只读取所有控件,正如ChrisF的答案中所建议的那样。优点:最简单的事情。缺点:在我看来,这是一个丑陋的用户界面。

  2. 在不同的容器中创建显示和编辑控件。将容器的可见性绑定到ViewMode。优点:在这里可以体验到更令人愉快的用户体验。你甚至可以动画从一个到另一个的过渡。缺点:将控件的数量加倍(可能会损害非常大的窗口的性能)。将两个容器内的控件放置在完全相同的像素位置在流体UI中可能会变得有点不平凡。

  3. 对于xaml中的每个编辑控件,在其上放置一个显示控件。将可见性绑定到ViewMode属性。优点:至少没有重复的标签控制,所以稍微快一点。缺点:难以获得动画内容和其他视图调整的权利。

编辑:鉴于提供的澄清,我选择取代以前的答案,因为它几乎在很大程度上处理了如何而不是什么。

3

我这样想:View是它的样子,而ViewModel是它与用户交互的方式。由于只读接口具有与读/写接口显着不同的行为,因此应该有两种不同的ViewModel。

现在我确实创建了一个从ViewModel继承的编辑ViewModel,因为我认为编辑功能是显示功能的扩展。这适用于简单的CRUD类型的应用程序,用户直接编辑没有很多业务逻辑的字段。另一方面,如果您正在建模的业务流程(或工作流)更复杂,那么通常您操纵信息的方式与您想要查看的方式有很大不同。因此,我通常会将两个ViewModel分开,除非它只是CRUD。

3

如果你想要去IsReadOnly路线,ChrisF的答案很好。但是,如果您想要使用TextBlock-to-TextBox路由,最有效的方法是使用Control,它可以根据IsInEditMode或IsInViewModel属性的值通过触发器切换模板。

2

首先,我要实现的抽象基类为实现IEditableObject和暴露适当的命令为BeginEditEndEditCancelEdit我的视图模型。可能这三种方法的实际实现必须由派生类来完成,但这些命令可能存在于基类中。

在此方法中,EndEdit使用视图模型中的当前属性值更新模型。我想在基类中实现一个布尔值IsEditing属性,用于数据触发器,这样如果我想在没有(比如说)打开模式对话框的情况下在模式之间切换,我可以在样式中执行它。就前端的视觉设计而言,我发现只读视图只是一个只读控件的编辑视图是主要针对程序员的一种视图。一般而言,如果您只是向用户呈现对象,则该演示文稿的目标是向用户提供该对象中信息的信息丰富,清晰直观的表示形式。如果您让用户编辑对象,那么该演示文稿的目标就是尽可能简单明了地修改对象的所有可编辑属性。

这是两组非常不同的目标。例如,虽然一个人的性别,身高和体重可能是应用程序收集的重要信息,但系统在大多数情况下向用户显示该信息可能并不重要。如果你脑子里有什么,编辑模式就像显示模式一样,这似乎是一件很自然的事情。但是,如果你放置用户的需求,而不是程序员,前台和中心,那么根本不是正确的做法。