C# 我可以在 XAML(.NET 4 Framework 之前)中指定泛型类型吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/185349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I specify a generic type in XAML (pre .NET 4 Framework)?
提问by Matt Hamilton
In XAML I can declare a DataTemplate so that the template is used whenever a specific type is displayed. For example, this DataTemplate will use a TextBlock to display the name of a customer:
在 XAML 中,我可以声明一个 DataTemplate,以便在显示特定类型时使用该模板。例如,此 DataTemplate 将使用 TextBlock 来显示客户的姓名:
<DataTemplate DataType="{x:Type my:Customer}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
I'm wondering if it's possible to define a DataTemplate that will be used any time an IList<Customer> is displayed. So if a ContentControl's Content is, say, an ObservableCollection<Customer> it would use that template.
我想知道是否可以定义一个在显示 IList<Customer> 时将使用的 DataTemplate。因此,如果 ContentControl 的 Content 是 ObservableCollection<Customer>,它将使用该模板。
Is it possible to declare a generic type like IList in XAML using the {x:Type} Markup Extension?
是否可以使用 {x:Type} 标记扩展在 XAML 中声明像 IList 这样的泛型类型?
采纳答案by ageektrapped
回答by Ian Oakes
Not directly in XAML, however you could reference a DataTemplateSelector
from XAML to choose the correct template.
不是直接在 XAML 中,但是您可以DataTemplateSelector
从 XAML 中引用 a来选择正确的模板。
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; }
}
The resource dictionary:
资源字典:
<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>
The window XAML:
窗口 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>
The window code behind:
后面的窗口代码:
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;
}
}
回答by cplotts
aelij (the project coordinator for the WPF Contribproject) has another wayto do it.
aelij(WPF Contrib项目的项目协调员)有另一种方法来做到这一点。
What's even cooler (even though it is sometime off in the future) ... is that XAML 2009 (XAML 2006 is the current version) is going to support this natively. Check out this PDC 2008 sessionfor info on it and more.
更酷的是(即使它在未来的某个时候关闭)...是 XAML 2009(XAML 2006 是当前版本)将在本机支持此功能。查看此PDC 2008 会议以获取有关它的信息及更多信息。
回答by Claudiu Mihaila
You also can wrap your generic class in a derived class that specifies the T
您还可以将泛型类包装在指定 T 的派生类中
public class StringList : List<String>{}
and use StringList from XAML.
并使用 XAML 中的 StringList。
回答by Mike de Klerk
Quite defeats the purpose of a generic, but you could define a class that derives from the generic like so, with the sole purpose of being able to use that type in XAML.
完全违背了泛型的目的,但您可以像这样定义一个从泛型派生的类,其唯一目的是能够在 XAML 中使用该类型。
public class MyType : List<int> { }
And use it in xaml e.g. like
并在 xaml 中使用它,例如
<DataTemplate DataType={x:Type myNamespace:MyType}>