View 集合中的 TabItems

发布于 2024-09-04 17:37:03 字数 1632 浏览 2 评论 0原文

我正在使用MVVM。我有一个选项卡控件。我将收集一些物品。我想将集合中的每个项目显示为选项卡项目。每个选项卡项中的视图都不同,并且可能有自己的视图模型。我该如何实现这一目标? 例如,我的收藏中有 3 件物品。 Tab 项模板包含一个 ItemControl。我现在想创建 3 个选项卡,并且每个选项卡内的 ItemControls 可能显示不同的视图。

我可以做的一种方法是为每个项目设置一个视图和视图模型。现在,根据某些条件,视图将显示不同的 UI 元素并表现不同。但恐怕这会让一段时间内的观点变得相当复杂。

编辑:下面的 Goblin 解决方案工作正常,但是当自定义样式应用于 TabControl 时我遇到了问题。

<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Template">
  <Setter.Value>
     <ControlTemplate TargetType="TabControl">
      <Grid>
         <Grid.ColumnDefinitions>
            <ColumnDefinition/> <ColumnDefinition />
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
            <RowDefinition Height="Auto" Name="RowDefinition0" />
            <RowDefinition Height="*" Name="RowDefinition1" />
         </Grid.RowDefinitions>
         <TabPanel Grid.Column="0" Grid.Row="0" />
         <Border Grid.Column="0" Grid.Row="1">
             <ContentPresenter Content="{TemplateBinding TabControl.SelectedContent}" ContentTemplate="{TemplateBinding TabControl.SelectedContentTemplate}" ContentStringFormat="{TemplateBinding TabControl.SelectedContentStringFormat}" ContentSource="SelectedContent" Name="PART_SelectedContentHost" Margin="{TemplateBinding Control.Padding}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
          </Border>
          </Grid>
          <ControlTemplate.Triggers>

编辑:通过将 ContentTemplateSelector 添加到上述 TabControl 样式中的 ContentPresenter 已解决此问题

I am using MVVM. I have a tab control. I will have a collection of items. I want to display each of this item in the collection as a tab item. The view in each tab item is different and may have its own viewmodel. How do I achieve this?
E.g. I have 3 items in the collection. The Tab item template contains an ItemControl. I would like to now have 3 Tabs created and the ItemControls inside each tabitem may be showing different views.

One way I could do is have a single view and viewmodel for each item. Now based on some condition the View will display different UI elements and behave differently. But I am afraid this will make the view quite complex over a period of time.

Edit: Goblin's solution below works fine but I have an issue when a custom style applied to TabControl.

<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Template">
  <Setter.Value>
     <ControlTemplate TargetType="TabControl">
      <Grid>
         <Grid.ColumnDefinitions>
            <ColumnDefinition/> <ColumnDefinition />
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
            <RowDefinition Height="Auto" Name="RowDefinition0" />
            <RowDefinition Height="*" Name="RowDefinition1" />
         </Grid.RowDefinitions>
         <TabPanel Grid.Column="0" Grid.Row="0" />
         <Border Grid.Column="0" Grid.Row="1">
             <ContentPresenter Content="{TemplateBinding TabControl.SelectedContent}" ContentTemplate="{TemplateBinding TabControl.SelectedContentTemplate}" ContentStringFormat="{TemplateBinding TabControl.SelectedContentStringFormat}" ContentSource="SelectedContent" Name="PART_SelectedContentHost" Margin="{TemplateBinding Control.Padding}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
          </Border>
          </Grid>
          <ControlTemplate.Triggers>

EDIT: This has been resolved by adding ContentTemplateSelector to the ContentPresenter in the above TabControl style

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

假扮的天使 2024-09-11 17:37:03

为每个视图创建一个数据模板。实现一个 DataTemplateSelector 类,给定一个项目返回正确的数据模板。如果项目集合称为 Items,您的 xaml 将如下所示

<TabControl 
    ItemsSource="{Binding Path=Items}"
    ContentTemplateSelector="{StaticResource MyTemplateSelector}" />

Create a datatemplate for each view. Implement a DataTemplateSelector class which given an item returns the correct datatemplate. If the collection of items is called Items your xaml would look something like this

<TabControl 
    ItemsSource="{Binding Path=Items}"
    ContentTemplateSelector="{StaticResource MyTemplateSelector}" />
花期渐远 2024-09-11 17:37:03

您尝试过使用 DataTemplateSelectors 吗?

基本上,您在主 ViewModel 中发布较小 ViewModel 的集合 - 然后在 DataTemplateSelector 中根据 ViewModel 的类型选择模板?

<UserControl.Resources>
    <DataTemplate x:Key="HeaderTemplate">
        <TextBlock Text="CMR"/>
    </DataTemplate>
    <DataTemplate x:Key="FirstTemplate">
        <local:FirstView/>
    </DataTemplate>
    <DataTemplate x:Key="SecondTemplate">
        <lcoal:SecondView/>
    </DataTemplate>
    <local:TemplateSelector x:Key="TemplateSelector" FirstTypeTemplate="{StaticResource FirstTemplate}" SecondTypeTemplate={StaticResource SecondTemplate}/>
</UserControl.Resources>
<TabControl ItemsSource="{Binding SmallerViewModels}" ContentTemplateSelector="{StaticResource TemplateSelector}" ItemTemplate="{StaticResource HeaderTemplate}">

在代码隐藏中:

public class TemplateSelector:DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if(item.GetType() == typeof(FirstViewModel)
            return FirstTypeTemplate
        return SecondTypeTemplate;
    }
    public DataTemplate FirstTypeTemplate { get; set; }
    public DataTemplate SecondTypeTemplate { get; set; }
}

编辑:
ViewModel:

public class SharedViewModel
{
    public SharedViewModel()
    {
        SmallerViewModels = new List<ISmallViewModel>();
        SmallerViewModels.Add(new FirstViewModel());
        SmallerViewModels.Add(new SecondViewModel());
    }
    public IList<ISmallViewModel> SmallerViewModels{get;private set;}
}
public interface ISmallViewModel{}
public class FirstViewModel:ISmallViewModel
{
    public string FirstDescription
    {
        get{return "My first ViewModel";}
    }
}
public class SecondViewModel:ISmallViewModel
{
    public string SecondDescription
    {
        get{return "My second ViewModel";}
    }
}

视图

<UserControl  .... x:Class="...FirstView">
    <TextBlock Text="{Binding FirstDescription}"
</UserControl>
<UserControl  .... x:Class="...SecondView">
    <TextBlock Text="{Binding SecondDescription}"
</UserControl>

Have you tried using DataTemplateSelectors?

Basically, you publish a collection of smaller ViewModels in your main ViewModel - then in the DataTemplateSelector choose your template based on the type of ViewModel?

<UserControl.Resources>
    <DataTemplate x:Key="HeaderTemplate">
        <TextBlock Text="CMR"/>
    </DataTemplate>
    <DataTemplate x:Key="FirstTemplate">
        <local:FirstView/>
    </DataTemplate>
    <DataTemplate x:Key="SecondTemplate">
        <lcoal:SecondView/>
    </DataTemplate>
    <local:TemplateSelector x:Key="TemplateSelector" FirstTypeTemplate="{StaticResource FirstTemplate}" SecondTypeTemplate={StaticResource SecondTemplate}/>
</UserControl.Resources>
<TabControl ItemsSource="{Binding SmallerViewModels}" ContentTemplateSelector="{StaticResource TemplateSelector}" ItemTemplate="{StaticResource HeaderTemplate}">

In Code-behind:

public class TemplateSelector:DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if(item.GetType() == typeof(FirstViewModel)
            return FirstTypeTemplate
        return SecondTypeTemplate;
    }
    public DataTemplate FirstTypeTemplate { get; set; }
    public DataTemplate SecondTypeTemplate { get; set; }
}

EDIT:
ViewModels:

public class SharedViewModel
{
    public SharedViewModel()
    {
        SmallerViewModels = new List<ISmallViewModel>();
        SmallerViewModels.Add(new FirstViewModel());
        SmallerViewModels.Add(new SecondViewModel());
    }
    public IList<ISmallViewModel> SmallerViewModels{get;private set;}
}
public interface ISmallViewModel{}
public class FirstViewModel:ISmallViewModel
{
    public string FirstDescription
    {
        get{return "My first ViewModel";}
    }
}
public class SecondViewModel:ISmallViewModel
{
    public string SecondDescription
    {
        get{return "My second ViewModel";}
    }
}

Views

<UserControl  .... x:Class="...FirstView">
    <TextBlock Text="{Binding FirstDescription}"
</UserControl>
<UserControl  .... x:Class="...SecondView">
    <TextBlock Text="{Binding SecondDescription}"
</UserControl>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文