MVVM 中查看模式和编辑模式之间切换?
我是 MVVM 的新手,我决定继续前进并开始在我即将进行的项目中采用它。
我已经阅读了这个相关的问题和答案,但我不知道如何用 MVVM 来实现。
我希望项目中的所有视图都有两种模式:编辑模式和查看模式。
我不希望用户默认看到所有字段的 TextBox,我宁愿他们看到 TextBlocks(或将所有 TextBoxe
s' 设置为 IsReadOnly
属性true(通过样式等,你告诉我......)。
当用户打开实体时,它通常应该是文本块、标签(或只读文本框)等,并且如果他单击“编辑”(如果他有权限),它应该进入编辑模式,并且所有字段的标签都应该反转为文本框(RichTextBoxes 等、组合框或不仅仅是标签的任何其他可编辑字段)
我很确定我不是唯一一个遇到此问题的人。想听听专家的意见,在纯 MVVM 中在这些模式之间切换的最有效方法是什么,以及为其声明两个单独的视图是否常见,
请向我推荐一篇解释如何执行此操作的好文章。它是由 Visual State 完成的
?? 我想知道什么而不是如何,我的问题是关于模式,并且是我应该分离编辑模式吗 从 V 或 VM 上的查看模式? 因此,请在您的回答中强调这一细节。
提前致谢。
I am new to MVVM and I've decided to move on and start adopting it in my upcoming projects.
I have read this related question and answer, but I don't know how this would be implemented with MVVM.
I want all the views in my project to have 2 modes, Edit Mode and View Mode.
I don't want the user by default to see TextBoxes for all the fields, I rather want them to see TextBlocks (or set all the TextBoxe
s' as IsReadOnly
property to true (via style etc. you tell me..).
When the user opens up the entity it should usually be TextBlocks, Labels (or readonly TextBoxes) etc., and if he clicks "Edit" (if he has permission to), it should go Edit Mode, and all the fields' labels should be inverted to TextBoxes (RichTextBoxes etc., ComboBoxes or any other editable fields that are not just labels).
I am pretty sure I am not the only one having this issue, I would like to hear from the experts what is the most efficient way to switch between these modes in pure MVVM, and whether it's is common to declare two separate views for it.
Please refer me to a good article that explains how to do it (maybe it is done by Visual State?? IDK).
UPDATE
I want to know WHAT rather than HOW, my question is about the pattern, and is should I separate Edit Mode
from View Mode at either the V or the VM?
So please emphasize this detail in your answer.
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用文本框的
IsReadOnly
属性并将其绑定到“编辑模式”属性:然后在视图模型中:
IsViewMode
默认为true
当用户单击“编辑”时,将切换为false
。绑定将立即使所有文本框可编辑。您可以对其他控件执行相同的操作 - 尽管在这些情况下您需要绑定到
IsEnabled
属性 - 尽管您会将控件灰显。要交换文本块和控件,您需要让两个控件在网格中共享相同位置,并且它们的可见性由
IsViewMode
属性通过一对转换器控制:直接转换器是
:逆变换器为:
Use the
IsReadOnly
property for your text boxes and bind that to the "edit mode" property:Then in your view model:
IsViewMode
defaults totrue
and is switched tofalse
when the user clicks "edit". The binding will instantly make all the text boxes editable.You could do the same for the other controls - though it will be the
IsEnabled
property you need to bind to in these cases - though you'd have greyed out controls.To swap out text blocks and your controls you'll need to have both controls sharing the same location in a grid and their visibility controlled by the
IsViewMode
property via a pair of converters:The direct converter is:
The inverted converter is:
我是这样想的:View 就是它的外观,ViewModel 就是它与用户交互的方式。由于只读接口的行为与读/写接口有很大不同,因此应该有两个不同的 ViewModel。
现在我确实创建了一个从显示 ViewModel 继承的编辑 ViewModel,因为我认为编辑功能是显示功能的扩展。这适用于简单的 CRUD 类型应用程序,其中用户直接编辑字段而无需大量业务逻辑。
另一方面,如果您正在建模更复杂的业务流程(或工作流程),那么通常您操作信息的方式与您想要查看信息的方式非常不同。因此,我通常会将两个 ViewModel 分开,除非它只是 CRUD。
I think about it this way: the View is what it looks like, and the ViewModel is how it interacts with the user. Since a readonly interface has substantially different behavior than a read/write interface, then there should be two different ViewModels.
Now I did created an edit ViewModel that inherited from a display ViewModel because I considered the editing functionality to be an extension of the display functionality. This works for simple CRUD type applications where the user is directly editing fields without a lot of business logic.
On the other hand, if you have a more complicated business process (or workflow) that you're modelling, then typically the way you manipulate information is very different from the way you want to view it. Therefore, I would generally separate the two ViewModels unless it was just CRUD.
如果您想走 IsReadOnly 路线,ChrisF 的答案很好。不过,如果您想采用 TextBlock 到 TextBox 的路线,最有效的方法是使用一个 Control,根据 IsInEditMode 或 IsInViewModel 属性的值,通过触发器切换其模板。
ChrisF's answer is fine if you want to go the IsReadOnly route. If you want to go the TextBlock-to-TextBox route, though, the most efficient way is have a Control which switches its Template, via triggers, based on the value of an IsInEditMode or IsInViewModel property.
Viewmodel:我肯定会只保留一个具有 ViewMode 属性的视图模型,就像 ChrisF 的答案中所描述的那样。单独的 ViewModel 会很不优雅。
观点:在我看来,你至少有三种选择,各有利弊。
按照 ChrisF 的回答中的建议,只读所有控件。优点:最简单的事情。缺点:在我看来,这是一个丑陋的用户界面。
在单独的容器中创建单独的显示和编辑控件。将容器的可见性绑定到 ViewMode。优点:这里可以提供更令人愉悦的用户界面体验。您甚至可以为从一种到另一种的过渡设置动画。缺点:控件数量加倍(可能会损害非常大的窗口的性能)。在流体用户界面中,将两个容器内的控件定位在完全相同的像素位置可能会变得有点不简单。
对于 xaml 中的每个编辑控件,将显示控件放置在其正上方。将可见性绑定到 ViewMode 属性。优点:至少没有重复的标签控件,因此速度稍快一些。缺点:很难正确调整动画内容和其他视图调整。
编辑:鉴于所提供的澄清,我选择替换之前的答案,因为它很大程度上涉及如何而不是内容。
Viewmodel: I would definitely keep just one viewmodel with a ViewMode property much as described in ChrisF's answer. Separate ViewModels would just be inelegant.
View: As I see it, you have at least three options, with various pros and cons.
Just readonly-ing all the controls, as suggested in the ChrisF's answer. Pros: Simplest thing to do. Cons: That is an ugly UI in my humble opinion.
Create seaparate display and edit controls in separate containers. Bind visibility of the containers to ViewMode. Pros: A more pleasing ui experience can be afforded here. You can even animate the transitions from one to the other. Cons: Doubles the number of controls (could hurt performance for very large windows). Positioning the controls inside the two containers at exactly the same pixel positions can become a bit non-trivial in a fluid ui.
For every edit control in the xaml, position a display control right on top of it. Bind visibility to the ViewMode property. Pros: No duplication of label controls at least, so slightly faster. Cons: Harder to get animation stuff and other view tweaks right.
Edit: In view of the clarification provided, I chose to replace the previous answer as it pretty much largely dealt with the how and not the what.
首先,我将为视图模型实现一个抽象基类,该基类实现了
IEditableObject
并为BeginEdit
、EndEdit
和公开了适当的命令>取消编辑
。这三个方法的实际实现可能必须由派生类决定,但命令可以存在于基类中。在此方法中,
EndEdit
使用视图模型中属性的当前值更新模型。我还在基类中实现了一个布尔
IsEditing
属性,用于数据触发器,这样如果我想在模式之间切换而不(比如说)打开模式对话框,我可以这样做以一种风格。就前端的视觉设计而言,我发现只读视图只是带有只读控件的编辑视图这一想法主要吸引程序员。一般来说,如果您只是向用户呈现一个对象,则该呈现的目标是为用户提供该对象中信息的信息丰富、清晰且直观的表示。如果您让用户编辑对象,则该演示文稿的目标是使修改对象的所有可编辑属性的任务尽可能简单明了。
这是两组截然不同的目标。例如,虽然一个人的性别、身高和体重可能是应用程序要收集的重要信息,但在大多数情况下,系统向用户呈现这些信息可能并不那么重要。如果您的脑海中认为编辑模式就像显示模式一样,那么这似乎是一件非常自然的事情。但是,如果您将用户的需求而不是程序员的需求放在首位和中心位置,那么这可能根本不是正确的做法。
First, I'd implement an abstract base class for my view models that implemented
IEditableObject
and exposed appropriate commands forBeginEdit
,EndEdit
, andCancelEdit
. It might be that the actual implementations for those three methods would have to be up to the derived classes, but the commands could live in the base class.In this approach,
EndEdit
updates the model with the current values of properties in the view model.I'd also implement a boolean
IsEditing
property in the base class, for use in data triggers, so that if I want to switch between modes without (say) opening a modal dialog, I can just do it in a style.As far as the visual design of the front-end goes, I find the idea that a read-only view is just an edit view with read-only controls is one that appeals primarily to programmers. Generally speaking, if you're simply presenting an object to a user, the goal of that presentation is to provide the user with an informative, clear, and intuitive representation of the information in that object. If you're letting the user edit an object, the goal of that presentation is to make the task of modifying all of the editable properties of the object as easy and clear as possible.
Those are two very different sets of goals. For instance, while a person's sex, height, and weight might be important pieces of information for an application to collect, it's probably not all that important for the system to present that information to the user in most contexts. It seems like a very natural thing to do if what you have in your head is that edit mode is just like display mode. But if you're placing the needs of the user, and not the programmer, front and center, it may not be the right thing to do at all.