MVVM 模式让您可以ViewModels
为单个View
. 通常它指的是View
,它可以有多个动作/状态。可以“手动”切换,ViewModels
也可以使用不同的模式,例如使用Strategy。
下面我将讨论这两个原则。
Using the strategy pattern
此模式允许您拥有一组为特定策略实现算法的类。一个简单的例子:你需要从家里去上班(学习地点等)。这可以通过多种方式完成:
所有这些都可以归因于单一策略,其中包括解决特定任务的多种方法。引用《Gang of Four》一书中关于策略模式适用性的一句话:
在以下情况下使用策略模式:
许多相关类仅在行为上有所不同。策略提供了一种使用多种行为之一配置类的方法。
您需要算法的不同变体。例如,您可以定义反映不同空间/时间权衡的算法。当这些变体被实现为算法的类层次结构时,可以使用策略。
算法使用客户不应该知道的数据。使用策略模式来避免暴露复杂的、特定于算法的数据结构。
一个类定义了许多行为,这些行为在其操作中表现为多个条件语句。将相关的条件分支移到它们自己的Strategy
类中,而不是许多条件。
结构图:
Conclusion for Strategy pattern
如果您对不同类型使用多个操作(C
reate R
emove U
pdate D
elete),例如:添加图像、添加用户信息、添加文件,这些操作也可以有子类型,那么我认为该策略适合您。
Using several ViewModels for one View
正如我上面提到的,MVVM 模式允许多个ViewModels
用于一个View
. 在我看来,最好使用DataTemplate
, 和 selector来完成DataTemplateSelector
,这将根据其条件返回所需的模板。DataTemplate
视觉呈现的理想选择ViewModel
。就个人而言,我使用 dynamic DataTemplateSelector
,例如:
<ContentControl Name="DynamicContentRightPanel"
Style="{StaticResource ContentControlRightPanelStyle}"
Content="{Binding Path=ContentRightPanelModel.ContentType,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
面板中可能有不同的内容,这取决于用户的选择。
ContentControlRightPanelStyle
<Style x:Key="ContentControlRightPanelStyle" TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplateSelector" Value="{StaticResource MyTemplateSelector}" />
<Setter Property="DataTemplateSelectors:DynamicTemplateSelector.Templates">
<Setter.Value>
<DataTemplateSelectors:TemplateCollection>
<DataTemplateSelectors:Template Value="DateCalculator"
DataTemplate="{StaticResource DateCalcTemplate}" />
<DataTemplateSelectors:Template Value="Test"
DataTemplate="{StaticResource TestTemplate}" />
</DataTemplateSelectors:TemplateCollection>
</Setter.Value>
</Setter>
</Style>
DynamicTemplateSelector (taken and little reworked from CodeProject)
public class DynamicTemplateSelector : DataTemplateSelector
{
#region Templates Dependency Property
public static readonly DependencyProperty TemplatesProperty =
DependencyProperty.RegisterAttached("Templates", typeof(TemplateCollection), typeof(DataTemplateSelector),
new FrameworkPropertyMetadata(new TemplateCollection(), FrameworkPropertyMetadataOptions.Inherits));
public static TemplateCollection GetTemplates(UIElement element)
{
return (TemplateCollection)element.GetValue(TemplatesProperty);
}
public static void SetTemplates(UIElement element, TemplateCollection collection)
{
element.SetValue(TemplatesProperty, collection);
}
#endregion
#region SelectTemplate
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
string myStringItem = (string)item;
if (!(container is UIElement))
{
return base.SelectTemplate(item, container);
}
TemplateCollection templates = GetTemplates(container as UIElement);
if (templates == null || templates.Count == 0)
{
base.SelectTemplate(item, container);
}
foreach (var template in templates)
{
if (myStringItem.Equals(template.Value.ToString()))
{
return template.DataTemplate;
}
}
return base.SelectTemplate(item, container);
}
#endregion
}
#region TemplateCollection
public class TemplateCollection : List<Template>
{
}
#endregion
#region Template Dependency Object
public class Template : DependencyObject
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(Template));
public static readonly DependencyProperty DataTemplateProperty =
DependencyProperty.Register("DataTemplate", typeof(DataTemplate), typeof(Template));
public string Value
{ get { return (string)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } }
public DataTemplate DataTemplate
{ get { return (DataTemplate)GetValue(DataTemplateProperty); } set { SetValue(DataTemplateProperty, value); } }
}
#endregion
Conclusion for several ViewModels / one main View
如果用户的选择仅限于一种类型的操作,可能是几种,您可以简单地为每个类型创建ViewModel / View
(在 DataTemplate 的情况下),因为它会更容易和更方便。