我一直在使用MVVM(或我自己的风味)已经有一段时间了,但我还是要澄清其中的一个方面。
(免责声明:我之前看过一些与之类似的问题,但我还没有看到任何考虑到专门针对视图更改数据类型的优缺点。抱歉,如果我错过了一些大的但每个第3个网页似乎在某个地方有“MVVM”= p)
问题: 用户需要选择活动的持续时间。他们可以选择默认活动长度的倍数(也就是BlockSize),或者对于那些“特殊场合”,我们允许他们推翻这个并从5分钟间隔中选择。
对于UI,我们决定使用组合框和togglebutton。默认情况下,组合框将显示{“1 Block”,“2 Blocks”,“3 Blocks”},或者当选中“Custom Duration”ToggleButton时:{“5 Minutes”,“10 Minutes”,“15 Minutes” }
3可能的解决方案:
理想情况下(对于可扩展性),ViewModel会公开ObservableCollection<TimeSpan>
以将其绑定到Combobox。但在这种情况下,我应该如何后缀“Block / s”或“Minute / s”。一次使用的多值转换器可以工作,但这会产生大量的样板代码,而且我不太喜欢你必须实现多少类型检查,因为它们没有强类型。
另一种方法是使用ViewModel来公开ObservableCollection<string>
,但在这种情况下,我必须编写一个转换"3 Blocks" => new TimeSpan( 0, 3 * BlockSize, 0 )
的方法,这听起来比MultiConverter更有吸引力。在这种情况下,它是一个相当简单的1-1映射,但即便如此,我也很想创建4个属性和一种控制它的方法..这似乎是管理单个绑定的分配代码。
private Dictionary<string, TimeSpan> selectedDurationMap { get; set; }
private ObservableCollection<string> availableCustomDurations { get; set; }
private ObservableCollection<string> availableBlockDurations { get; set; }
public ObservableCollection<string> AvailableDurations { get; private set; }
private fillDurationLists( TimeSpan maximumDuration, TimeSpan blockDuration ) { }
另一个是拥有多个ComboBox,它们显示/隐藏取决于是否选择了“自定义持续时间”ToggleButton。两者都可以使用内置的StringFormat来附加“Blocks”或“Minutes”,而我可以将我的可用持续时间保持为TimeSpan格式。这是我到目前为止倾向于支持的那种解决方案,但是虽然简单的实现在所有方框中都有所体现,但它并不是非常可扩展的
例如,为了增加对多元化的控制(块与块)我需要一个ValueConverter,在这种情况下,解决方案1更具可扩展性,可读性和高效性(视觉元素的一半),同时用更少的代码实现相同的目标(好的,所以这是一个玩具问题,但这是我经历的一个相当典型的场景)答案 0 :(得分:1)
我赞成另一个解决方案,那就是为持续时间公开ObservableCollection
个视图模型。将TimeSpan
包装在一个ViewModel类中,该类通过ToString()
或属性发出其名称(例如“1块”)。
这意味着您的视图模型正在代码中生成文本,这是最简单的解决方案。如果你想要在XAML中保持面向用户的文本是纯粹的,那么你可以针对这种类型编写一个DataTemplate,但你仍然需要处理复数等。