在XAML中,我可以声明一个DataTemplate,以便在显示特定类型时使用该模板。例如,此DataTemplate将使用TextBlock显示客户名称:
<DataTemplate DataType="{x:Type my:Customer}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
我想知道是否可以定义一个将在IList&lt; Customer&gt;的任何时候使用的DataTemplate。被展示。因此,如果ContentControl的内容是ObservableCollection&lt; Customer&gt;它会使用该模板。
是否可以使用{x:Type}标记扩展在XAML中声明类似IList的泛型类型?
答案 0 :(得分:30)
不是直接在XAML中,但您可以从XAML引用DataTemplateSelector
来选择正确的模板。
public class CustomerTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item,
DependencyObject container)
{
DataTemplate template = null;
if (item != null)
{
FrameworkElement element = container as FrameworkElement;
if (element != null)
{
string templateName = item is ObservableCollection<MyCustomer> ?
"MyCustomerTemplate" : "YourCustomerTemplate";
template = element.FindResource(templateName) as DataTemplate;
}
}
return template;
}
}
public class MyCustomer
{
public string CustomerName { get; set; }
}
public class YourCustomer
{
public string CustomerName { get; set; }
}
资源字典:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
>
<DataTemplate x:Key="MyCustomerTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="150"/>
</Grid.RowDefinitions>
<TextBlock Text="My Customer Template"/>
<ListBox ItemsSource="{Binding}"
DisplayMemberPath="CustomerName"
Grid.Row="1"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="YourCustomerTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="150"/>
</Grid.RowDefinitions>
<TextBlock Text="Your Customer Template"/>
<ListBox ItemsSource="{Binding}"
DisplayMemberPath="CustomerName"
Grid.Row="1"/>
</Grid>
</DataTemplate>
</ResourceDictionary>
窗口XAML:
<Window
x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
Height="300"
Width="300"
xmlns:local="clr-namespace:WpfApplication1"
>
<Grid>
<Grid.Resources>
<local:CustomerTemplateSelector x:Key="templateSelector"/>
</Grid.Resources>
<ContentControl
Content="{Binding}"
ContentTemplateSelector="{StaticResource templateSelector}"
/>
</Grid>
</Window>
背后的窗口代码:
public partial class Window1
{
public Window1()
{
InitializeComponent();
ObservableCollection<MyCustomer> myCustomers
= new ObservableCollection<MyCustomer>()
{
new MyCustomer(){CustomerName="Paul"},
new MyCustomer(){CustomerName="John"},
new MyCustomer(){CustomerName="Mary"}
};
ObservableCollection<YourCustomer> yourCustomers
= new ObservableCollection<YourCustomer>()
{
new YourCustomer(){CustomerName="Peter"},
new YourCustomer(){CustomerName="Chris"},
new YourCustomer(){CustomerName="Jan"}
};
//DataContext = myCustomers;
DataContext = yourCustomers;
}
}
答案 1 :(得分:24)
没有开箱即用,没有;但是那些有进取心的开发者已经这样做了。
例如,微软的Mike Hillberg在this post中使用了它。谷歌当然还有其他人。答案 2 :(得分:21)
您还可以将通用类包装在指定T
的派生类中public class StringList : List<String>{}
并使用XAML中的StringList。
答案 3 :(得分:7)
aelij(WPF Contrib项目的项目协调员)还有另外way来做这件事。
什么更酷(即使将来某个时候关闭)......是XAML 2009(XAML 2006是当前版本)本来会支持这个。查看此PDC 2008 session了解相关信息及其他信息。
答案 4 :(得分:0)
我认为,在.net框架的重新发布的版本中,这可以完成。
检查Generics in XAML documentation。你需要使用x:TypeArguments
;有一些限制,所以首先阅读文件。
另请参阅Stackoverflow上的How to specify generic type argument in XAML问题
答案 5 :(得分:0)
完全违背了泛型的目的,但您可以定义一个类似于泛型的类,其唯一目的是能够在XAML中使用该类型。
public class MyType : List<int> { }
并在xaml中使用它,例如像
<DataTemplate DataType={x:Type myNamespace:MyType}>