基于ViewModel类型的TabItem

本文关键字:TabItem 类型 ViewModel 基于 | 更新日期: 2023-09-27 17:50:28

1 -我有TabControl。它的项源是选项卡的集合不同的类型。我需要为每种类型使用不同的XAML。如何形成TabItem标题和内容取决于ViewModel类型?
为每种类型的ViewModel封装XAML的最佳解决方案是什么?我应该为每种类型都设置一个UserControl还是有更好的解决方案?

HumanTabViewModel和InvaderTabViewModel是BaseViewModel类的子类。

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

class PanelViewModel : BaseViewModel
{
    private readonly ObservableCollection<BaseViewModel> _tabs = new ObservableCollection<BaseViewModel>();
    public ObservableCollection<BaseViewModel> Tabs
    {
        get { return _tabs; }
    }
    private void InitTabs()
    {
        // Fill Tabs collection with some logic
        var tab1 = new HumanTabViewModel ();
        _tabs.Add(tab1);
        var tab2 = new InvaderTabViewModel ();
        _tabs.Add(tab2);
    }
}

基于ViewModel类型的TabItem

通过使用datatemplate,您可以为您的类型定义不同的外观:

DataTemplate是用来给逻辑实体(.cs)一个可视化的表示,一旦你把你的逻辑对象(在你的例子中是入侵者/虚拟机)指定为Content,框架将遍历逻辑树,为你的类型寻找一个DataTemplate。

如果没有找到,它将只显示您的类型的"ToString()"。

在您的例子中,您有2个内容TabItem。其中可以通过HeaderTemplate分配一个DataTemplate。

HumanView和InvaderView都是usercontrol。

CS:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        Items.Add(new HumanViewModel());
        Items.Add(new InvaderViewModel());
    }
    private ObservableCollection<BaseViewModel> items;
    public ObservableCollection<BaseViewModel> Items
    {
        get
        {
            if (items == null)
                items = new ObservableCollection<BaseViewModel>();
            return items;
        }
    }
}
public class BaseViewModel : INotifyPropertyChanged
{
    public virtual string Header
    {
        get { return "BaseViewModel"; }
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
public class HumanViewModel : BaseViewModel
{
    public override string Header
    {
        get
        {
            return "HumanViewModel";
        }
    }
}
public class InvaderViewModel : BaseViewModel
{
    public override string Header
    {
        get
        {
            return "InvaderViewModel";
        }
    }
}
XAML:

<Window>
   <Window.Resources>
      <DataTemplate DataType="{x:Type local:HumanViewModel}">
          <local:HumanView />
      </DataTemplate>
      <DataTemplate DataType="{x:Type local:InvaderViewModel}">
          <local:InvaderView />
      </DataTemplate>
       <Style TargetType="TabItem">
          <Setter Property="HeaderTemplate">
              <Setter.Value>
                  <DataTemplate>
                      <TextBlock Text="{Binding Header,Mode=OneWay}" FontSize="18" FontWeight="Bold" Foreground="DarkBlue" Width="Auto"/>
                  </DataTemplate>
              </Setter.Value>
          </Setter>
      </Style>
  </Window.Resources>

  <Grid>
      <TabControl ItemsSource="{Binding Items, Mode=OneWay}" />    
  </Grid>
</Window>