[英]Creating a re-usable DataTemplate resource for an ItemsControl
我目前有什么
我目前有一個ItemsControl,可用於顯示控件列表。 由於每個“項目”都包含多個控件,因此我通過指定DataTemplate進行設置。 這樣的事情(為了使代碼更容易理解,我刪除了一些元素屬性):
<ItemsControl x:Name="Items" ItemsSource="{Binding Path=MyItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Path Grid.Column="0"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<c:MyControl />
<c:MyButton />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我要做什么
上面的代碼提供了我想要的功能,但是我在幾個地方都有,我希望將重復的代碼減到最少。 關於上述xaml,重用DataTemplate時唯一需要不同的是“ MyButton”和“ MyControl”的控件。 考慮到這一點,我定義上述XAML的理想方法是這樣的:
<ItemsControl x:Name="Items" ItemsSource="{Binding Path=MyItems}">
<c:MyControl />
<c:MyButton />
</ItemsControl>
我對課程的某些變化感到很高興,但希望可以清楚地看到我要消除的重復項。
我嘗試過的
到目前為止,我已經嘗試在資源文件中創建模板,但是效果不佳,我甚至不確定自己走的路是否正確。 這就是我所擁有的:
<DataTemplate x:Key="MyTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Path Grid.Column="0" Fill="..." Data="..." />
<StackPanel Grid.Column="1" Orientation="Horizontal">
<ItemsPresenter />
</StackPanel>
</Grid>
</DataTemplate>
我嘗試像這樣將其應用於我的XAML:
<ItemsControl x:Name="Items" ItemsSource="{Binding Path=MyItems}" ItemTemplate="{StaticResource MyTemplate}">
<c:MyControl />
<c:MyButton />
</ItemsControl>
一切正常,但是在運行時出現錯誤: "Items collection must be empty before using ItemsSource."
這顯然是我不正確方法的副作用。
我究竟做錯了什么? 如何設置我的模板使其以我想要的方式工作?
您可以創建一個派生的ItemsControl類,該類使用ContentControl
(而不是ContentPresenter
)作為項目容器類型:
public class MyItemsControl : ItemsControl
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ContentControl();
}
}
現在,您可以將當前的DataTemplate分為位於ContentControl Template
的“外部”可重用部分和由其余DataTemplate定義的“內部”部分:
<!-- somewhere in Resources -->
<Style x:Key="ReusableItemContainerStyle" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Path Grid.Column="0" ... />
<ContentPresenter Grid.Column="1"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<local:MyItemsControl
ItemsSource="{Binding MyItems}"
ItemContainerStyle="{StaticResource ReusableItemContainerStyle}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<c:MyControl />
<c:MyButton />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</local:MyItemsControl>
更新 :您還可以在Generic.xaml中為派生的ItemsControl設置默認樣式的可重用ItemContainerStyle,如下所示:
<Style TargetType="local:MyItemsControl"
BasedOn="{StaticResource {x:Type ItemsControl}}">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Path Grid.Column="0" ... />
<ContentPresenter Grid.Column="1"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
然后,您還必須為ItemsControl設置默認樣式鍵:
public class MyItemsControl : ItemsControl
{
static MyItemsControl()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(MyItemsControl),
new FrameworkPropertyMetadata(typeof(MyItemsControl)));
}
protected override DependencyObject GetContainerForItemOverride()
{
return new ContentControl();
}
}
將模板聲明為新控件,如下所示:
<UserControl x:Class="UI.Views.NewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Name="myNewControl">
<Grid>
<ItemsControl x:Name="Items" ItemsSource="{Binding Path=MyItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Path Grid.Column="0"/>
<ContentControl Grid.Row="1" Content="{Binding MyCustomControl, ElementName=myNewControl}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
MyCustomControl應該是控件的依賴項屬性。
您將如何使用它:
<MyNewControl>
<MyNewControl.MyCustomControl>
<StackPanel>
<MyControl/>
<MyButton/>
</StackPanel>
</MyNewControl.MyCustomControl>
</MyNewControl>
希望這可以幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.