WPF MVVM:将不同的 ViewModel 绑定到每个 TabItem?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26218766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:35:40  来源:igfitidea点击:

WPF MVVM: Binding a different ViewModel to each TabItem?

c#wpfmvvm

提问by Hardgraf

I have a main window with a tab control containing 2 tabItems:

我有一个包含 2 个选项卡控件的主窗口tabItem

Main Window

主窗口

I currently have 1 ViewModelwhich services Tab1 & Tab2. This ViewModelis becoming a little bloated with blurred SOC. I want to split the logic into 2 viewmodels: ViewModel 1 & ViewModel2. My understanding is that you can set the Main Window DataContextto a Base ViewModel which holds a collection of ViewModels & then you can assert each TabItem to a different ViewModel.

我目前有 1 个ViewModel服务 Tab1 和 Tab2。由于ViewModelSOC 模糊,这变得有点臃肿。我想将逻辑拆分为 2 个视图模型:ViewModel 1 和 ViewModel2。我的理解是,您可以将主窗口设置DataContext为包含 ViewModel 集合的 Base ViewModel,然后您可以将每个 TabItem 断言到不同的 ViewModel。

The example's I've seen of these base ViewModels expose an ObservableCOllection like so:

我见过的这些基础 ViewModel 的示例公开了一个 ObservableCOllection,如下所示:

private ObservableCollection<ViewModel1> _viewModelCollection
Public Observable Collection<ViewModel1> ViewModelCollection
{
   get { return _viewModelCollection; }
   set
     {
        _viewModelCollection = value;
        OnPropertyChanged("ViewModelCollection");
     }
}

public BaseViewModel()
{
  ViewModelCollection = new ObservableCollection<ViewModel1>();
  ViewModelCollection.Add(new ViewModel1(Tab1);
  ViewModelCollection.Add(new ViewModel1(Tab2);
}

But how do I assign a different ViewModel to each TabItem? I would want Tab1= ViewModel1 & Tab2=ViewModel2?

但是如何为每个 TabItem 分配不同的 ViewModel?我想要 Tab1= ViewModel1 & Tab2=ViewModel2?

回答by Jakob Christensen

You can indeed add the view models for your tabs to a main view model. You can then bind to the child view models in the XAML for your tabs.

您确实可以将选项卡的视图模型添加到主视图模型。然后,您可以绑定到选项卡的 XAML 中的子视图模型。

Say that you have three viewmodels: MainViewModel, Tab1ViewModel, and Tab2ViewModel. On your MainViewModelyou keep a collection of your tab viewmodels:

你说你有三个的ViewModels: ,MainViewModelTab1ViewModelTab2ViewModel。在你MainViewModel的你的标签视图模型中保留一个集合:

class MainViewModel
{
    ObservableCollection<object> _children;

    public MainViewModel()
    {
        _children = new ObservableCollection<object>();
        _children.Add(new Tab1ViewModel());
        _children.Add(new Tab2ViewModel());
    }

    public ObservableCollection<object> Children { get { return _children; } }
}

After setting the DataContextof your main window to your MainViewModelyou can bind the DataContextof your tabs by referencing the Childrenproperty:

DataContext将主窗口的设置为您后,MainViewModel您可以DataContext通过引用Children属性来绑定选项卡:

<TabControl>
    <TabItem DataContext="{Binding Children[0]}" x:Name="Tab1" Header="Tab1" >
      <!-- Tab content -->
    </TabItem>
    <TabItem DataContext="{Binding Children[1]}" x:Name="Tab2" Header="Tab2" >
      <!-- Tab content -->
    </TabItem>
</TabControl>

回答by Varatharaj

class MainViewModel
{
    ObservableCollection<object> _children;

    public MainViewModel()
    {
        _children = new ObservableCollection<object>();
        _children.Add(new Tab1ViewModel());
        _children.Add(new Tab2ViewModel());
    }

    public ObservableCollection<object> Children { get { return _children; } }
}

Now in XAML bind the Children to ItemsSource. It will generate each Tab for every viewmodel we have added into the observable collection

现在在 XAML 中将 Children 绑定到 ItemsSource。它将为我们添加到可观察集合中的每个视图模型生成每个选项卡

    <TabControl ItemsSource="{Binding Children}"/>

回答by Mashton

I use a framework such as Prism, that allows you to define regions and use the RegionManager. You can then define a ContentControlas the 'ui' for the TabItem

我使用了一个框架,比如 Prism,它允许你定义区域并使用RegionManager. 然后,您可以将 a 定义ContentControlTabItem

Then you can use the RegionManager.RequestNavigateto populate a named region with a particular view (and our views import a viewmodel and set their datacontext).

然后您可以使用RegionManager.RequestNavigate用特定视图填充命名区域(我们的视图导入一个视图模型并设置它们的数据上下文)。

回答by Yann Duran

For people finding this page with the same question, I found a video on YouTube: WPF MVVM - Working with tab controls and tab content, by a guy from DCOM Engineering, LLC.

对于那些遇到相同问题的人,我在 YouTube 上找到了一个视频:WPF MVVM - 使用选项卡控件和选项卡内容,作者来自 DCOM Engineering, LLC。

It gives a very good explanation of "how to bind a different ViewModelto each TabItem", step by step, with downloadable code.

它通过可下载的代码一步一步地很好地解释了“如何将不同的绑定ViewModel到每个TabItem”。

"Learn how to create, open, and close tabs effectively using the MVVM pattern with WPF. Facilitates unit testing."

"了解如何使用 MVVM 模式和 WPF 有效地创建、打开和关闭选项卡。促进单元测试。"

回答by Pat M

No sure why the selected answer is suggesting to use ObservableCollection and create a collection of tabs and then reference them by index.

不确定为什么选择的答案建议使用 ObservableCollection 并创建选项卡集合,然后通过索引引用它们。

I find it more clean to do it this way:

我发现这样做更干净:

MainViewModel tab1= ConfigViewModel Tab2 = UserProfileViewModel

MainViewModel tab1= ConfigViewModel Tab2 = UserProfileViewModel

in MainViewModel:

在主视图模型中:

private ConfigViewModels _configVM;
public ConfigViewModels ConfigVM { get { return _configVM; } }

private UserProfileViewModel _userProfileVM;
public UserProfileViewModel UserProfileVM { get { return _userProfileVM; } }

public MainViewModel(){

_configVM = new ConfigViewModels();
_userProfileVM = new UserProfileViewModel ();
}

In th XAML file:

在 XAML 文件中:

<TabControl>
<TabItem DataContext="{Binding ConfigVM }" >
<TabItem DataContext="{Binding UserProfileVM }" >

I'm not sure I understand the benefit of doing this through an observable collection.

我不确定我是否理解通过 observable 集合执行此操作的好处。