Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将TabControl绑定到ViewModels集合?_C#_Wpf_Mvvm_Tabcontrol_Tabitem - Fatal编程技术网

C# 如何将TabControl绑定到ViewModels集合?

C# 如何将TabControl绑定到ViewModels集合?,c#,wpf,mvvm,tabcontrol,tabitem,C#,Wpf,Mvvm,Tabcontrol,Tabitem,基本上,我的MainViewModel.cs中有: ObservableCollection<TabItem> MyTabs { get; private set; } 我之所以这么问,是因为我正在从一个ViewModel中构造一个视图(AddressControl),对我来说,这听起来像是一个MVVM no-no.这不是MVVM。您不应该在视图模型中创建UI元素 您应该将选项卡的ItemsSource绑定到ObservaleCollection,这样就可以保存带有应创建选项卡信息

基本上,我的MainViewModel.cs中有:

ObservableCollection<TabItem> MyTabs { get; private set; }

我之所以这么问,是因为我正在从一个ViewModel中构造一个视图(AddressControl),对我来说,这听起来像是一个MVVM no-no.

这不是MVVM。您不应该在视图模型中创建UI元素

您应该将选项卡的ItemsSource绑定到ObservaleCollection,这样就可以保存带有应创建选项卡信息的模型

以下是表示选项卡页面的VM和模型:

public sealed class ViewModel
{
    public ObservableCollection<TabItem> Tabs {get;set;}
    public ViewModel()
    {
        Tabs = new ObservableCollection<TabItem>();
        Tabs.Add(new TabItem { Header = "One", Content = "One's content" });
        Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" });
    }
}
public sealed class TabItem
{
    public string Header { get; set; }
    public string Content { get; set; }
}

在Prism中,通常将选项卡控件设置为一个区域,这样就不必控制绑定的选项卡页面集合

<TabControl 
    x:Name="MainRegionHost"
    Regions:RegionManager.RegionName="MainRegion" 
    />
使用此方法允许您稍后在运行时创建视图,例如通过控制器:

RegionManager.RegisterViewWithRegion( "MainRegion", typeof( MyView ) );
IRegion region = this._regionManager.Regions["MainRegion"];

object mainView = region.GetView( MainViewName );
if ( mainView == null )
{
    var view = _container.ResolveSessionRelatedView<MainView>( );
    region.Add( view, MainViewName );
}
IRegion region=this.\u regionManager.Regions[“MainRegion”];
对象mainView=region.GetView(MainViewName);
if(mainView==null)
{
var view=_container.ResolveSessionRelatedView();
添加(视图,主视图名称);
}

因为您已经注册了视图的类型,所以视图被放置到正确的区域。

我有一个转换器来解耦UI和ViewModel,这就是下面的要点:

<TabControl.ContentTemplate>
    <DataTemplate>
        <ContentPresenter Content="{Binding Tab,Converter={StaticResource TabItemConverter}"/>
    </DataTemplate>
</TabControl.ContentTemplate>

该选项卡是我的TabItemViewModel中的枚举,TabItemConverter将其转换为真实的UI

在TabItemConverter中,只需获取值并返回所需的usercontrol。

可能是这样:

<UserControl x:Class="Test_002.Views.MainView"
         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:local="clr-namespace:Test_002.Views"
         xmlns:generalView="clr-namespace:Test_002.Views.General"
         xmlns:secVIew="clr-namespace:Test_002.Views.Security"
         xmlns:detailsView="clr-namespace:Test_002.Views.Details"
         mc:Ignorable="d" 
         d:DesignHeight="400" d:DesignWidth="650">
<Grid>
    <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Margin="2,5">
            <Button Command="{Binding btnPrev}" Content="Prev"/>
            <Button Command="{Binding btnNext}" Content="Next"/>
            <Button Command="{Binding btnSelected}" Content="Selected"/>
        </StackPanel>
        <TabControl>
            <TabItem Header="General">
                <generalView:GeneralView></generalView:GeneralView>
            </TabItem>
            <TabItem Header="Security">
                <secVIew:SecurityView></secVIew:SecurityView>
            </TabItem>
            <TabItem Header="Details">
                <detailsView:DetailsView></detailsView:DetailsView>
            </TabItem>
        </TabControl>
    </DockPanel>
</Grid>

我想这是最简单的方法。
MVVM兼容吗

+1个好问题。在PRISM指南中,他们并没有真正涉及到这种情况。他们在手册中没有涉及到,但在参考实现中涉及到。这是一个纯粹的C#/WPF/MVVM问题,即PRISM是否集成/使用。嗯,选项卡的内容是一个用户控件,那么,我不会还在ViewModel中创建新的UI实例吗?@michael:在您的示例中,您实际上是在ViewModel中创建了一个UI元素。在我的示例中,我正在创建TabItem类型的模型。在您的示例中,TabControl(假设)将获取ViewModel实例化的TabItems并将其显示给用户。在我的视图中,它查看其ItemsSource,为每个项创建一个选项卡,并根据视图中元素的配置和显示的项的类型绑定每个选项卡的各个部分。这是一个主要的区别。你明白吗?我花了一段时间才把这个标记为答案,但我最终明白了你所说的DataTemplates部分的意思。只要我定义了DataTemplate,WPF就会根据选项卡中的ViewModel类型自动连接视图/ViewModels。
TabItem
是一个UI元素。为什么要在视图模型中创建它?@Gusdor可以随意调用它。“团体”、“foo”、“迂腐的评论”。无论您的设计需要什么。
RegionManager.RegisterViewWithRegion( "MainRegion", typeof( MyView ) );
IRegion region = this._regionManager.Regions["MainRegion"];

object mainView = region.GetView( MainViewName );
if ( mainView == null )
{
    var view = _container.ResolveSessionRelatedView<MainView>( );
    region.Add( view, MainViewName );
}
<TabControl.ContentTemplate>
    <DataTemplate>
        <ContentPresenter Content="{Binding Tab,Converter={StaticResource TabItemConverter}"/>
    </DataTemplate>
</TabControl.ContentTemplate>
<UserControl x:Class="Test_002.Views.MainView"
         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:local="clr-namespace:Test_002.Views"
         xmlns:generalView="clr-namespace:Test_002.Views.General"
         xmlns:secVIew="clr-namespace:Test_002.Views.Security"
         xmlns:detailsView="clr-namespace:Test_002.Views.Details"
         mc:Ignorable="d" 
         d:DesignHeight="400" d:DesignWidth="650">
<Grid>
    <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Margin="2,5">
            <Button Command="{Binding btnPrev}" Content="Prev"/>
            <Button Command="{Binding btnNext}" Content="Next"/>
            <Button Command="{Binding btnSelected}" Content="Selected"/>
        </StackPanel>
        <TabControl>
            <TabItem Header="General">
                <generalView:GeneralView></generalView:GeneralView>
            </TabItem>
            <TabItem Header="Security">
                <secVIew:SecurityView></secVIew:SecurityView>
            </TabItem>
            <TabItem Header="Details">
                <detailsView:DetailsView></detailsView:DetailsView>
            </TabItem>
        </TabControl>
    </DockPanel>
</Grid>