我可以在 XAML(.NET 4 之前)中指定泛型类型吗?
Posted
技术标签:
【中文标题】我可以在 XAML(.NET 4 之前)中指定泛型类型吗?【英文标题】:Can I specify a generic type in XAML (pre .NET 4 Framework)? 【发布时间】:2010-09-16 04:01:28 【问题描述】:在 XAML 中,我可以声明一个 DataTemplate,以便在显示特定类型时使用该模板。例如,此 DataTemplate 将使用 TextBlock 来显示客户的姓名:
<DataTemplate DataType="x:Type my:Customer">
<TextBlock Text="Binding Name" />
</DataTemplate>
我想知道是否可以定义一个在显示 IList
是否可以使用 x:Type 标记扩展在 XAML 中声明像 IList 这样的泛型类型?
【问题讨论】:
这里实际上有两个问题,首先 DataTemplate 不支持接口,其次是泛型 有关框架的最新版本,请参阅***.com/questions/7573712/… 【参考方案1】:不是直接在 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;
【讨论】:
可能是一个更好更简单的解决方案 我发现这比其他模板选择器教程更容易理解。谢谢【参考方案2】:不是开箱即用的,不;但是有一些有进取心的开发人员已经这样做了。
例如,微软的 Mike Hillberg 在this post 中使用过它。 Google 当然还有其他的。
【讨论】:
【参考方案3】:您还可以将泛型类包装在指定 T 的派生类中
public class StringList : List<String>
并使用 XAML 中的 StringList。
【讨论】:
这对我有用。有一个完全空的类有点奇怪,但它完成了工作。 我在***.com/a/33827448/11635 中使用这种技术构建了一个通用包装器【参考方案4】:aelij(WPF Contrib 项目的项目协调员)有另一个 way 来做。
更酷的是(即使它在未来的某个时候关闭)...... XAML 2009(XAML 2006 是当前版本)将在本机上支持这一点。查看PDC 2008 session 了解更多信息。
【讨论】:
XAML 2009 仅在松散的 xaml 文件中受支持(从 .NET 4.0、WPF 4.0 开始)。也就是说,Blend、Cider(Visual Studio 设计器)和已编译的 BAML(这是您的嵌入式 xaml 编译成的内容)......不支持新语法。希望这将在 WPF 的未来版本中改变。查看以下链接并投票:dotnet.uservoice.com/forums/40583-wpf-feature-suggestions/…【参考方案5】:这完全违背了泛型的目的,但您可以像这样定义从泛型派生的类,其唯一目的是能够在 XAML 中使用该类型。
public class MyType : List<int>
并在 xaml 中使用它,例如喜欢
<DataTemplate DataType=x:Type myNamespace:MyType>
【讨论】:
以上是关于我可以在 XAML(.NET 4 之前)中指定泛型类型吗?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在 app.xaml 文件的样式中指定 OnPlatform ?