在TabControl中显示多个控件类型

时间:2013-08-30 13:30:22

标签: c# wpf mvvm tabcontrol

全部,我创建了一个TabControl来保存包含单一控件类型的TabitemMainWindow.xaml 的标记为,如下所示

...
<TabControl x:Name="tabControl" 
            ItemsSource="{Binding Path=Workspaces}" 
            SelectedIndex="{Binding SelectedIndex}"
            IsSynchronizedWithCurrentItem="true" 
            HorizontalContentAlignment="Stretch" 
            VerticalContentAlignment="Stretch" 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            TabStripPlacement="Top" 
            Margin="5,0,5,0">
    <TabControl.ItemContainerStyle>
        <Style TargetType="TabItem">
            <Setter Property="Header" Value="{Binding Path=DisplayName}"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        </Style>
    </TabControl.ItemContainerStyle>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <Views:ResourceControl DataContext="{Binding}" 
                                   HorizontalAlignment="Stretch" 
                                   VerticalAlignment="Stretch"/>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>
...

这对我的Views:ResourceControl很有用,但我现在想要扩展TabControl中显示的控件类型。为此,我创建了控件,这些控件都链接到从基础'WorkspaceViewModel'继承的视图模型,并且我创建了以下资源文件

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:ViewModels="clr-namespace:ResourceStudio.ViewModels"
                    xmlns:Views="clr-namespace:ResourceStudio.Views">
    <DataTemplate DataType="{x:Type ViewModels:ResourceDataViewModel}">
        <Views:ResourceControl />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:StartPageViewModel}">
        <Views:StartPageControl/>
    </DataTemplate>
    <DataTemplate x:Key="WorkspacesTemplate">
        <TabControl x:Name="tabControl" 
                    IsSynchronizedWithCurrentItem="true" 
                    ItemsSource="{Binding}" 
                    SelectedIndex="{Binding SelectedIndex}"
                    HorizontalContentAlignment="Stretch" 
                    VerticalContentAlignment="Stretch" 
                    HorizontalAlignment="Stretch" 
                    VerticalAlignment="Stretch" 
                    TabStripPlacement="Top" 
                    Margin="5,0,5,0">
            <TabControl.ItemContainerStyle>
                <Style TargetType="TabItem">
                    <Setter Property="Header" Value="{Binding Path=DisplayName}"/>
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
                </Style>
            </TabControl.ItemContainerStyle>
        </TabControl>
    </DataTemplate>
</ResourceDictionary>

现在在MainWindow.xaml我有

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="MainWindowResources.xaml" />
        </ResourceDictionary.MergedDictionaries>
        <Style x:Key="DescriptionHeaderStyle" TargetType="Label">
            <Setter Property="FontSize" Value="22" />
            <Setter Property="HorizontalAlignment" Value="Center" />
        </Style>
    </ResourceDictionary>
</Window.Resources>
...
<ContentControl
    Content="{Binding Path=Workspaces}" 
    ContentTemplate="{StaticResource WorkspacesTemplate}">
</ContentControl>

当标签显示相关标题时,绑定似乎注册了我想要显示的不同视图。但是,在我加载另一个表单之前,实际控件不会显示。似乎SelectedIndex没有绑定,并且在切换/加载选项卡项时未更新视图。

如何更改WorkspaceTemplate以解决此问题?

感谢您的时间。


编辑。请求有关MainViewModel的信息。

public class MainWindowViewModel : WorkspaceViewModel 
{
    private readonly IDialogService dialogService;
    private WorkspaceViewModel selectedWorkspace;
    private ObservableCollection<WorkspaceViewModel> workspaces;
    private Dictionary<string, string> resourceDictionary;

    public MainWindowViewModel()
    {
        base.DisplayName = "SomeStringName";
        resourceDictionary = new Dictionary<string, string>();
        dialogService = ServiceLocator.Resolve<IDialogService>();
        Contract.Requires(dialogService != null);
    }

    ...

    private void OnWorkspacesChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null && e.NewItems.Count != 0)
            foreach (WorkspaceViewModel workspace in e.NewItems)
                workspace.RequestClose += this.OnWorkspaceRequestClose;

        if (e.OldItems != null && e.OldItems.Count != 0)
            foreach (WorkspaceViewModel workspace in e.OldItems)
                workspace.RequestClose -= this.OnWorkspaceRequestClose;
    }

    private void OnWorkspaceRequestClose(object sender, EventArgs e)
    {
        WorkspaceViewModel workspace = sender as WorkspaceViewModel;
        workspace.Dispose();
        int currentIndex = Workspaces.IndexOf(workspace);
        this.Workspaces.Remove(workspace);
        if (this.Workspaces.Count > 0)
            this.SetActiveWorkspace(Workspaces[currentIndex - 1]);
    }

    private void SetActiveWorkspace(WorkspaceViewModel workspace)
    {
        Debug.Assert(this.Workspaces.Contains(workspace));
        ICollectionView collectionView = CollectionViewSource.GetDefaultView(this.Workspaces);
        if (collectionView != null)
            collectionView.MoveCurrentTo(workspace);
    }

    public WorkspaceViewModel SelectedWorkspace
    {
        get { return selectedWorkspace; }
        set { selectedWorkspace = value; }
    }   

    private int selectedIndex = 0;
    public int SelectedIndex
    {
        get { return selectedIndex; }
        set
        {
            if (selectedIndex == value)
                return;
            selectedIndex = value;
            OnPropertyChanged("SelectedIndex");
        }
    }

    /// <summary>
    /// Returns the collection of available workspaces to display.
    /// A 'workspace' is a ViewModel that can request to be closed.
    /// </summary>
    public ObservableCollection<WorkspaceViewModel> Workspaces
    {
        get
        {
            if (workspaces == null)
            {
                workspaces = new ObservableCollection<WorkspaceViewModel>();
                workspaces.CollectionChanged += this.OnWorkspacesChanged;
            }
            return workspaces;
        }
    }
    ...
}

1 个答案:

答案 0 :(得分:1)

我使用你的代码面对类似的东西。不确定它是否是同一个。当我的应用程序加载时,它显示第一个选项卡(第0个)及其正确的内容。选择第二个内容区域时,空白,没有任何反应。

我将Content="{Binding Path=Workspaces}"移到了TabControl,即

Content="{Binding}"

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

它开始显示标签的内容。我使用了更多精简版的VM。只是WorkSpaces

的集合