我可以在XAML(.NET 4 Framework之前)中指定genericstypes吗?
在XAML中,我可以声明一个DataTemplate,以便在显示特定types时使用该模板。 例如,这个DataTemplate将使用一个TextBlock来显示一个客户的名字:
<DataTemplate DataType="{x:Type my:Customer}"> <TextBlock Text="{Binding Name}" /> </DataTemplate>
我想知道是否有可能定义一个DataTemplate,在任何时候显示IList <Customer>时都会使用它。 所以如果一个ContentControl的内容是一个ObservableCollection <Customer>,它会使用该模板。
是否有可能使用{x:Type}标记扩展在XAML中声明像IList这样的genericstypes?
不是开箱即可 但是那里有进取的开发者。
例如,微软公司的迈克·希尔伯格(Mike Hillberg)在这篇文章中对此进行了讨论 Google有其他的。
不是直接在XAML中,但是可以引用XAML中的DataTemplateSelector
来select正确的模板。
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; } }
您也可以将您的generics类包装在指定T的派生类中
public class StringList : List<String>{}
并使用XAML中的StringList。
aelij( WPF Contrib项目的项目协调员)有另一种方法来做到这一点。
更酷的是(即使将来有一段时间了)…… XAML 2009(XAML 2006是最新版本)将会在本地支持这一点。 看看这个PDC 2008会议的信息和更多。
我发现在.net框架的resent版本中可以这样做。
检查XAML文档中的generics 。 你需要使用x:TypeArguments
; 有一些限制,所以先阅读文档。
另请参阅如何在Stackoverflow的XAML问题中指定genericstypes参数
相当于打破了generics的目的,但是您可以定义一个从generics派生出来的类,就像在XAML中使用这种types的唯一目的一样。
public class MyType : List<int> { }
并在像xaml中使用它
<DataTemplate DataType={x:Type myNamespace:MyType}>