2

也许我什至没有以正确的方式考虑这一点,所以我愿意接受建议,但我想使用完全相同的视图进行创建和编辑。我不想说创建/编辑实体,因为它比这更复杂。我有嵌套视图(使用 Catel 来实现),所以每个嵌套视图也有它自己的视图模型。但是,根据您是创建还是编辑(在父视图和嵌套视图中),内部状态和执行的命令会有所不同。立即想到的两个想法是:

1)有一个策略模式的视图模型,其中要执行的操作(创建相关或编辑相关)与激活视图的消息一起传递。

2)不知何故有2个可以与同一个视图关联的视图模型以及在它们之间切换的方法。

建议?

4

2 回答 2

3

MVVM 模式让您可以ViewModels为单个View. 通常它指的是View,它可以有多个动作/状态。可以“手动”切换,ViewModels也可以使用不同的模式,例如使用Strategy

下面我将讨论这两个原则。

Using the strategy pattern

此模式允许您拥有一组为特定策略实现算法的类。一个简单的例子:你需要从家里去上班(学习地点等)。这可以通过多种方式完成:

  • 走路
  • 骑自行车
  • 乘汽车/公共汽车旅行

所有这些都可以归因于单一策略,其中包括解决特定任务的多种方法。引用《Gang of Four》一书中关于策略模式适用性的一句话:

在以下情况下使用策略模式:

  • 许多相关类仅在行为上有所不同。策略提供了一种使用多种行为之一配置类的方法。

  • 您需要算法的不同变体。例如,您可以定义反映不同空间/时间权衡的算法。当这些变体被实现为算法的类层次结构时,可以使用策略。

  • 算法使用客户不应该知道的数据。使用策略模式来避免暴露复杂的、特定于算法的数据结构。

  • 一个类定义了许多行为,这些行为在其操作中表现为多个条件语句。将相关的条件分支移到它们自己的Strategy类中,而不是许多条件。

结构图:

在此处输入图像描述

Conclusion for Strategy pattern

如果您对不同类型使用多个操作(Create Remove Update Delete),例如:添加图像、添加用户信息、添加文件,这些操作也可以有子类型,那么我认为该策略适合您。

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 的情况下),因为它会更容易和更方便。

于 2014-01-14T07:46:57.717 回答
0

在选项 1 为您提供最多选项的情况下,我会尝试尽可能多地重用逻辑。你甚至可以想到这样的场景:

public void PersonViewModel()
{
    // Will be used when no model is available - create mode
    public PersonViewModel()
        : this(null) { }

    // Will be used when a model is available - edit mode
    public PersonViewModel(IPerson person) 
    { 
        // Here you check if you have a person object, if so, edit 
    }
}
于 2014-01-14T07:41:57.423 回答