简体   繁体   English

如何使用 PRISM、Mef、DI 将视图模型链接到选项卡控件内的用户控件?

[英]How to link a viewmodel to a usercontrol inside a tabcontrol using PRISM, Mef, DI?

I am writing an app with a MS Office style tab ribbon on top.我正在编写一个顶部带有 MS Office 样式选项卡功能区的应用程序。 This tabcontrol is placed in a region in the shell which is set up by the Mef.此选项卡控件位于外壳中由 Mef 设置的区域中。

Code in shell.xaml: shell.xaml 中的代码:

...
<ContentControl Name="TabRegion" prism:RegionManager.RegionName="TabRegion"/>
...

Code in TabRegionView.xaml: TabRegionView.xaml 中的代码:

<UserControl x:Class="Ensor.Studio.View.TabRegionView"
             etc...>
    <TabControl Margin="5" BorderThickness="0" Background="White" ItemsSource="{Binding Path=Tabs}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Title}"/>
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ContentControl Content="{Binding Content}"/>
            </DataTemplate>
        </TabControl.ContentTemplate>         
    </TabControl>
</UserControl>

Code in tab content: ProjectTabView.xaml选项卡内容中的代码:ProjectTabView.xaml

<UserControl x:Class="Ensor.Studio.View.Tabs.ProjectTabView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:ap="clr-namespace:Ensor.Studio.ViewModel.CustomControls"
             xmlns:vm="clr-namespace:Ensor.Studio.ViewModel.Tabs"
             mc:Ignorable="d" 
             d:DesignHeight="110" d:DesignWidth="800">

    <StackPanel Orientation="Horizontal">
        <Button Name="button_ProjectBrowse" Command="{Binding ProjectBrowseCommand}" 
                     Style="{StaticResource BigTabButton}" Margin="5,10                  
                     ap:ButtonProperties.Image="pack:.../ButtonIcons/open.png" 
                     Content="Browse"/>
        <Rectangle Margin="5,10" Stroke="Silver"/>
...

When I run the app, this tabcontrol renders fine, but the usercontrols are not linked with the right view model... When the shell initializes the following error pops up in the output:当我运行应用程序时,此选项卡控件呈现良好,但用户控件未与正确的视图模型链接......当外壳初始化时,输出中会弹出以下错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'ProjectBrowseCommand' property not found on 'object' ''TabRegionViewModel' (HashCode=37840511)'. BindingExpression:Path=ProjectBrowseCommand; DataItem='TabRegionViewModel' (HashCode=37840511); target element is 'Button' (Name='button_ProjectBrowse'); target property is 'Command' (type 'ICommand')

Which means that the view looked for a ProjectBrowseCommand in the TabRegionViewModel, which is the viewmodel of the whole tab control, while it actually should have looked in ProjectTabViewModel.这意味着视图在 TabRegionViewModel 中查找了 ProjectBrowseCommand,它是整个选项卡控件的视图模型,而它实际上应该在 ProjectTabViewModel 中查找。

But the app keeps running so when I click on this first tab which makes the content of this tab appear and the following error pops up:但是该应用程序一直在运行,因此当我单击第一个选项卡时,会出现此选项卡的内容并弹出以下错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'ProjectBrowseCommand' property not found on 'object' ''ProjectTabView' (Name='')'. BindingExpression:Path=ProjectBrowseCommand; DataItem='ProjectTabView' (Name=''); target element is 'Button' (Name='button_ProjectBrowse'); target property is 'Command' (type 'ICommand')

Which means this time it looked for a ProjectBrowseCommand in the backend code of the view of the specific tab.这意味着这次它在特定选项卡的视图的后端代码中查找 ProjectBrowseCommand。

What I'm actually trying to do is link the usercontrol in the ProjectTab to ProjectTabViewModel.我真正想做的是将 ProjectTab 中的用户控件链接到 ProjectTabViewModel。 This is a class with multiple dependencies so I'd rather not use DataContext = new ProjectTabViewModel(...);这是一个具有多个依赖项的类,所以我宁愿不使用 DataContext = new ProjectTabViewModel(...);

So my question is, why did the view look in the wrong classes to find it's bindings.所以我的问题是,为什么视图在错误的类中查找以找到它的绑定。 And how can I hook it up to ProjectTabViewModel with Dependency Injection?以及如何通过依赖注入将其连接到 ProjectTabViewModel?

What I would do is bind the ItemsSource to a ViewModel property of eg ObservableCollection<object> ( object can also be a base class for all tabs ViewModel).我要做的是将 ItemsSource 绑定到一个 ViewModel 属性,例如ObservableCollection<object>object也可以是所有选项卡 ViewModel 的基类)。

Then use DataTemplate to tell WPF how to represents the different ViewModels:然后使用 DataTemplate 告诉 WPF 如何表示不同的 ViewModel:

For example likes this:例如喜欢这个:


public class ViewModel
{
    public ObservableCollection<object> Tabs { get; } = new ObservableCollection<object>();

    public ViewModel()
    {
        Tabs.Add(new FirstViewModel());
    }
}

<TabControl ItemsSource="{Binding Path=Tabs}"></TabControl>

Resources:资源:

<DataTemplate DataType="{x:Type viewModels:FirstViewModel} ">
    <views:FirstView/>
</DataTemplate>

UPDATE更新

Using dependency injection:使用依赖注入:


public class ViewModel
{
    public ObservableCollection<TabViewModelBase> Tabs { get; } = new ObservableCollection<object>();

    public ViewModel(IEnumerable<TabViewModelBase> tabs)
    {
        Tabs.Add(tabs);
    }
}

public class FirstViewModel : TabViewModelBase
{
    
}

I assume that you know how to configure a container in the root of your application.我假设您知道如何在应用程序的根目录中配置容器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM