可以在XAML(.NET 4之前的版本)中指定通用类型吗?


73

在XAML中,我可以声明一个DataTemplate以便在显示特定类型时使用该模板。例如,此DataTemplate将使用TextBlock显示客户名称:

<DataTemplate DataType="{x:Type my:Customer}">
    <TextBlock Text="{Binding Name}" />
</DataTemplate>

我想知道是否可以定义将在每次显示IList <Customer>时使用的DataTemplate。因此,例如,如果ContentControl的Content是ObservableCollection <Customer>,它将使用该模板。

是否可以使用{x:Type}标记扩展在XAML中声明类似IList的泛型类型?


您实际上在这里有2个问题,首先是DataTemplate不支持接口,其次是泛型
MikeT 2014年

Answers:


24

不是开箱即用,不是;但是那里有一些进取的开发人员。

例如,微软公司的Mike Hillberg在这篇文章中就玩过它。Google当然还有其他人。


31

不是直接在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; }
}

资源字典:

<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;
    }
}

可能是一个更好,更轻松的解决方案
书呆子培训

我发现这比其他“模板选择器”教程更容易理解。谢谢
杰克·弗罗斯特


7

aelij(WPF Contrib项目的项目协调员)有另一种方法

更酷的是(即使它将来会面世)……XAML 2009(当前版本为XAML 2006)将原生支持此功能。请查看此PDC 2008会话,以获取有关其更多信息。


5
仅在宽松的xaml文件中支持XAML 2009(从.NET 4.0,WPF 4.0开始)。也就是说,Blend,Cider(Visual Studio设计器)和已编译的BAML(嵌入式xaml会编译到其中)...不支持新语法。希望这会在WPF的未来版本中有所改变。请参阅以下链接和投票:dotnet.uservoice.com/forums/40583-wpf-feature-suggestions/...
cplotts

0

完全违背了泛型的目的,但是您可以像这样定义一个从泛型派生的类,其唯一目的是能够在XAML中使用该类型。

public class MyType : List<int> { }

并在xaml中使用它,例如

<DataTemplate DataType={x:Type myNamespace:MyType}>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.