在MVVM中切换视图模式和编辑模式?

时间:2011-02-06 23:51:48

标签: wpf silverlight xaml mvvm

我是MVVM的新手,我决定继续在我即将开展的项目中采用它。

我已阅读此相关问题和答案,但我不知道如何使用MVVM实现这一点。

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

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

我很确定我不是唯一有这个问题的人,我想听听专家们在纯MVVM中切换这些模式的最有效方法是什么,以及声明两个单独的视图是否常见为了它。

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

更新
我想知道什么而不是如何,我的问题是关于模式,并且我应该分开编辑模式 从V或VM的View Mode? 所以请在答案中强调这一细节。

提前致谢。

5 个答案:

答案 0 :(得分: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,并在用户点击&#34;编辑&#34;时切换为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;

答案 1 :(得分:3)

我这样思考:View就是它的样子,而ViewModel就是它与用户交互的方式。由于只读接口的行为与读/写接口的行为大不相同,因此应该有两个不同的ViewModel。

现在我创建了一个继承自显示ViewModel的编辑ViewModel,因为我认为编辑功能是显示功能的扩展。这适用于简单的CRUD类型应用程序,其中用户直接编辑字段而没有很多业务逻辑。

另一方面,如果您正在建模的业务流程(或工作流程)更复杂,那么您操作信息的方式通常与您想要查看的方式大不相同。因此,我通常将两个ViewModel分开,除非它只是CRUD。

答案 2 :(得分:3)

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

答案 3 :(得分:2)

Viewmodel:我肯定会保留一个带有ViewMode属性的viewmodel,就像ChrisF的回答中所描述的那样。单独的ViewModel只是不够优雅。

观点:正如我所看到的,你至少有三种选择,各有利弊。

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

  2. 在单独的容器中创建seaparate显示和编辑控件。将容器的可见性绑定到ViewMode。优点:这里可以提供更愉快的ui体验。您甚至可以设置从一个到另一个的过渡动画。缺点:控件的数量翻倍(可能会损害非常大的窗口的性能)。将控件放置在两个容器内完全相同的像素位置在流体ui中可能会变得有点不重要。

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

  4. 编辑:鉴于所提供的澄清,我选择取代之前的答案,因为它几乎主要涉及的是如何而不是什么。

答案 4 :(得分:2)

首先,我为实现IEditableObject的视图模型实现了一个抽象基类,并为BeginEditEndEditCancelEdit公开了适当的命令。可能是这三种方法的实际实现必须取决于派生类,但命令可以存在于基类中。

在这种方法中,EndEdit使用视图模型中属性的当前值更新模型。

我还在基类中实现了一个布尔IsEditing属性,用于数据触发器,这样如果我想在没有(比如说)打开模式对话框的情况下切换模式,我就可以这么做一种风格。

就前端的视觉设计而言,我发现只读视图只是一个只读控件的编辑视图,主要是程序员。一般来说,如果您只是向用户展示一个对象,那么该演示文稿的目标是为用户提供信息,清晰,直观的对象信息表示。如果您让用户编辑对象,则该演示文稿的目标是使修改对象的所有可编辑属性的任务尽可能简单明了。

这是两组完全不同的目标。例如,虽然一个人的性别,身高和体重可能是应用程序收集的重要信息,但系统在大多数情况下向用户提供该信息可能并不是那么重要。如果你脑子里的东西是编辑模式就像显示模式一样,这似乎是很自然的事情。但是,如果你需要用户,而不是程序员,前端和中心,那么根本不可能做到这一点。