Cha*_*esB 5 wpf xaml datatemplate
我有一个带有单个特定选项卡的 TabControl 和一个绑定到一组 VM 的集合,使用不同的用户控件。为此,我使用在控件资源中定义的 CompositeCollection 和 DataTemplates,根据 VM 类型(充当 ContentTemplate)选择正确的用户控件。
我还设置了一个 ItemTemplate 来定义带有绑定的选项卡项的名称,但它没有在资源中定义,因为我猜它会与“ContentTemplate”冲突。
它工作正常,但我看到跟踪到以下错误:
System.Windows.Data 错误:26:ItemTemplate 和 ItemTemplateSelector 对于已经属于 ItemsControl 的容器类型的项目被忽略;类型='标签项'
看起来 ContentTemplate 和 ItemTemplate 之间存在一些冲突,但我不知道如何解决?
代码如下:
<TabControl HorizontalAlignment="Left" Height="300" Width="500">
<TabControl.Resources>
<CollectionViewSource x:Key="personCollection" Source="{Binding Persons}" />
<DataTemplate DataType="{x:Type viewModel:Main}">
<local:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:Person}">
<local:PersonView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemsSource>
<CompositeCollection>
<TabItem Header="General" Content="{Binding }"/>
<CollectionContainer Collection="{Binding Source={StaticResource personCollection}}" />
</CompositeCollection>
</TabControl.ItemsSource>
<TabControl.ItemTemplate>
<DataTemplate DataType="viewModel:Person">
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
Run Code Online (Sandbox Code Playgroud)
您观察到的错误非常明显。
您可以定义ItemsSource您的TabControl作为一个CompositeCollection包含不同类型的元素:
TabItem“将军”;Person视图模型。所以你只是将一个视图和一些视图模型混合在一个集合中 - 这并不整洁。WPF 通过错误消息通知您。引擎尝试为项目创建视图(使用DataTemplates),突然遇到一个已经指定的视图 (a TabItem),它与项目容器的类型完全相同(因为对于TabControl,每个视图模型的视图将插入到TabItem容器中)。因此,WPF 只是将 插入TabItem到 中TabControl并通知它尚未使用任何ItemTemplate或ItemTemplateSelector用于创建它。
你可以简单地忽略这个错误,因为最终控件应该看起来像你想要的(我想)。
另一种(可能更简洁)的方法不是在一个集合中混合视图和视图模型,而是为“常规”选项卡指定一个“常规”视图模型:
<TabControl.ItemsSource>
<CompositeCollection>
<viewModel:GeneralViewModel/>
<CollectionContainer Collection="{Binding Source={StaticResource personCollection}}" />
</CompositeCollection>
</TabControl.ItemsSource>
Run Code Online (Sandbox Code Playgroud)
当然,您还需要告诉 WPF 如何将其可视化:
<TabControl.Resources>
<DataTemplate DataType="{x:Type viewModel:GeneralViewModel}">
<local:GeneralView />
</DataTemplate>
<!-- ... -->
</TabControl.Resources>
Run Code Online (Sandbox Code Playgroud)
解决您评论中的问题。
1.
如何将 GeneralViewModel 绑定到存在于我的 DataContext 中的那个?
这是可能的,但需要一些开销。您必须为此创建一个绑定代理。(看看这里。)
您需要的第二件事是标记扩展:
class BindingProxyValue : MarkupExtension
{
public BindingProxy Proxy { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Proxy.DataContext;
}
}
Run Code Online (Sandbox Code Playgroud)
将此标记扩展与集合中的绑定代理一起使用:
<TabControl.Resources>
<local:BindingProxy x:Key="Proxy" DataContext="{Binding GeneralViewModel}"/>
</TabControl.Resources>
<!--...-->
<CompositeCollection>
<local:BindingProxyValue Proxy="{StaticResource Proxy}"/>
<CollectionContainer Collection="{Binding Source={StaticResource personCollection}}" />
</CompositeCollection>
Run Code Online (Sandbox Code Playgroud)
您可以根据需要扩展标记扩展,例如,它可以观察对象更新并替换目标中的项目CompositeCollection。
2.
如何指定常规选项卡的标题名称?
您可以使用ItemTemplates,但它会变得有点复杂。你必须DataTemplateSelector为你的TabControl:
class YourTabItemDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
FrameworkElement element = container as FrameworkElement;
if (element != null && item != null)
{
if (item is GeneralViewmodel)
{
return (DataTemplate)element.FindResource("GeneralTabItemTemplate");
}
else
{
return (DataTemplate)element.FindResource("PersonTabItemTemplate");
}
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以ItemTemplate为不同的TabItems定义不同的s:
<TabControl.Resources>
<!-- ... -->
<DataTemplate x:Key="GeneralTabItemTemplate">
<TextBlock Text="General" />
</DataTemplate>
<DataTemplate x:Key="PersonTabItemTemplate">
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</TabControl.Resources>
Run Code Online (Sandbox Code Playgroud)
问题是:这项努力是否值得,或者您对错误消息 26 是否满意?你决定。
| 归档时间: |
|
| 查看次数: |
2217 次 |
| 最近记录: |