1 - 我有TabControl。它的项目来源是Tabs的集合
不同种类。我需要为每种类型使用不同的XAML。如何形成TabItem标题和内容取决于ViewModel类型?
2 - 为每种类型的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);
}
}
答案 0 :(得分:1)
使用DataTemplates,您可以为您的类型定义不同的外观:
DataTemplate用于为逻辑实体(.cs)提供可视化表示,一旦您将逻辑对象(在您的案例中为invader / human vm&#39; s)作为内容分配,框架将遍历逻辑树为您的类型寻找DataTemplate。
如果找不到,它只会显示&#34; ToString()&#34;你的类型。
在您的情况下,您有2个内容TabItem.Content和Header,可以通过HeaderTemplate为其分配DataTemplate。
HumanView和InvaderView是UserControls。
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>