分层视图模型,表示UI结构。什么是更好的方法?

时间:2016-08-06 22:22:50

标签: c# wpf xaml mvvm mvvm-light

对于冗长而描述性的问题感到抱歉,但很长一段时间它确实让我烦恼。我有MVVM模式的问题。

我写的应用程序确实有效,但我不认为它的风格很好。我的视图模型结构看起来像树:它引用了所有子视图模型,用于在ContentPresenter中呈现正确的视图。

看一下示例GUI:

主页标签

--------------------------------------
HOME    SETTINGS    ADMINPANEL
======---------------------------------
______________________________________
/////////
///////// Home content
/////////

“设置”标签

--------------------------------------
HOME    SETTINGS    ADMINPANEL
------============---------------------
______________________________________
settings1 > settings2 > other...

/////////
///////// Settings1 content
/////////

请注意仅在“设置”视图中显示的子菜单。每个可切换的视图都以某种方式依赖于模型类型。仅当model属性为Type.One时,settings1才可见,当属性为Type.Two时,settings2可见。

快速查看我当前的代码:每个视图的通用界面,我可以通过点击更改。 PageHeader显示在按钮更改内容视图上:

public interface IPageVM
{
    string PageHeader { get; set; }
}

并查看模型:

public class WindowVM : ViewModelBase
{
    public ObservableCollection<IPageVM> ViewModels { get; set; }
    public IPageVM CurrentTab { get; set; }
    public ICommand ChangeViewModel { get; set; }

    private Model _model;

    public WindowVM()
    {
        _model = new Model();

        ViewModels = new ObservableCollection<IPageVM>();
        ViewModels.Add(new HomeVM(model));
        ViewModels.Add(new SettingsVM(model));

        if(_model.Admin)
            ViewModels.Add(new AdminVM(model));
    }
}

public class HomeVM : ViewModelBase, IPageVM
{
    public string PageHeader { get { return "HOME"; } }
    string Property { get; set; }

    public HomeVM(Model model)
    {
        this.Property = model.Property;
    }
}

public class SettingsVM : ViewModelBase, IPageVM
{
    public string PageHeader { get { return "SETTINGS"; } }

    public ObservableCollection<IPageVM> Tabs { get; set; }
    public IPageVM CurrentTab { get; set; }
    public ICommand ChangeViewModel { get; set; }

    public SettingsVM(Model model)
    {
        Tabs = new ObservableCollection<IPageVM>();

        if(model.Type = Type.One)
            Tabs.Add(new Settings1VM(model));
        if(model.Type = Type.Two)
            Tabs.Add(new Settings2VM(model));

        Tabs.Add(new OtherSettingsVM());

        CurrentTab = Tabs[0];
    }
}

public class Settings1VM: ViewModelBase, IPageVM
{
    public string PageHeader { get { return "settings1"; } }

    public Settings1VM(Model model)
    {
    }
}

public class Settings2VM: ViewModelBase, IPageVM
{
    public string PageHeader { get { return "settings2"; } }

    public Settings1VM(Model model)
    {
    }
}

XAML: 在ItemsControl中显示按钮,这些按钮将更改CurrentViewModel并呈现绑定到视图模型的适当视图。按DataTemplate键入。

优点:

  • 它已经有效了
  • 我可以轻松地告诉我的GUI结构如何看,因为root viewmodel包含其子视图模型等等。
  • 通过构造函数很容易将数据模型注入子项。

缺点:

  • xaml代码全部是DataTemplate
  • UserControls在预览模式下为空,很难编辑GUI
  • 可怕的未来:如果我的应用程序会增长一些,我将如何查看我的viewmodels结构?

所以我决定将我的ViewModel改为看起来更像WPF MVVM的东西:

public class WindowVM : ViewModelBase
{
    public bool AdminMode { get; set; }

    public WindowVM()
    {
        _model = new Model();
        AdminMode = _model.Admin;
        AnotherTabVisibilityDependency = _model.Dependency;
    }
}

XAML:

<TabControl>
    <TabItem Header="HOME">
        <TabItem.DataContext>
            <vm:HomeVM/>
        </TabItem.DataContext>
    </TabItem>
    <TabItem Header="SETTINGS">
        <TabItem.DataContext>
            <vm:SettingsVM/>
        </TabItem.DataContext>
    </TabItem>
    <TabItem Header="ADMINPANEL" Visibility="{Binding AdminMode, Converter BoolToVisibility}">
        <TabItem.DataContext>
            <vm:AdminVM/>
        </TabItem.DataContext>
    </TabItem>
    <TabItem Header="DEPENDANT" Visibility="{Binding AnotherTabVisibilityDependency, Converter BoolToVisibility}">
    </TabItem>
</TabControl>

正如您可能看到的,一切都很干净,用户界面很简单;没有太多的模板可写。一切看起来都很好......但有一点我不明白:现在每个ViewModel都是一个不了解其父级的独立实例。我不能轻易通过模型。

问题:

  • 如何将数据模型注入每个视图模型?我不能通过xaml来做。我是否需要具有程序状态或IoC的全局静态类?也许另一种方式?
  • 任何替代方法?也许我的第二种方法也不好?
  • 重写我实际有效的逻辑是否有意义?我真的希望它(我讨厌我的viewmodels&#39;代码)。

0 个答案:

没有答案