一个视图的建议,可以有两种viewmodel模式

时间:2014-01-14 00:47:35

标签: c# wpf mvvm catel

也许我甚至没有以正确的方式思考这个问题,所以我愿意接受建议,但我想在创建和编辑时使用完全相同的视图。我不想说创建/编辑实体,因为它比这更复杂。我有嵌套视图(使用Catel实现),因此每个嵌套视图也有自己的viewmodel。但是,执行的内部状态和命令会有所不同,具体取决于您是创建还是编辑(在父视图和嵌套视图中)。立即想到的两个想法是:

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

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

建议?

2 个答案:

答案 0 :(得分:3)

MVVM模式允许您为单个ViewModels提供多个View。通常它指的是View,它可以有多个动作/状态。在ViewModels之间切换可以“手动”或使用不同的模式,例如使用策略

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

<强> Using the strategy pattern

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

  • 徒步
  • 骑自行车
  • 乘汽车/巴士旅行

所有这些都可以归结为单一策略,其中包括几种解决特定任务的方法。允许从“四人帮”一书中引用战略模式的适用性:

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

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

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

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

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

结构图:

enter image description here

Conclusion for Strategy pattern

如果您针对不同类型使用多个操作(C reate R emove U pdate D elete),例如:添加图片,添加用户信息,添加文件,也可以有子类型,然后我认为该策略适合你。

<强> Using several ViewModels for one View

正如我上面提到的,MVVM模式允许一个ViewModels多个View。在我看来,最好使用DataTemplate和选择器DataTemplateSelector,它将根据条件返回所需的模板。 DataTemplate适用于ViewModel的视觉呈现。就个人而言,我使用动态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的情况下),因为它将更容易和更方便。 / p>

答案 1 :(得分: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 
    }
}