Можно ли указать универсальный тип в XAML (до .NET 4 Framework)? - PullRequest
72 голосов
/ 09 октября 2008

В XAML я могу объявить DataTemplate, чтобы шаблон использовался всякий раз, когда отображается определенный тип. Например, этот DataTemplate будет использовать TextBlock для отображения имени клиента:

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

Мне интересно, возможно ли определить DataTemplate, который будет использоваться всякий раз, когда отображается IList . Так что, если ContentControl Content, скажем, ObservableCollection , он будет использовать этот шаблон.

Можно ли объявить универсальный тип, такой как IList, в XAML, используя расширение разметки {x: Type}?

Ответы [ 6 ]

30 голосов
/ 09 октября 2008

Не напрямую в XAML, однако вы можете сослаться на DataTemplateSelector из XAML, чтобы выбрать правильный шаблон.

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;
    }
}
24 голосов
/ 09 октября 2008

Не из коробки, нет; но есть предприимчивые разработчики, которые сделали это.

Майк Хиллберг из Microsoft играл с ним в в этом посте , например. У Google, конечно, есть и другие.

21 голосов
/ 29 октября 2010

Вы также можете обернуть свой универсальный класс в производный класс, который определяет T

public class StringList : List<String>{}

и использовать StringList из XAML.

7 голосов
/ 04 ноября 2008

aelij (координатор проекта WPF Contrib ) имеет другой способ сделать это.

Что еще круче (хотя в будущем это будет выходной) ... так это то, что XAML 2009 (текущая версия XAML 2006) будет поддерживать это изначально. Проверьте эту сессию PDC 2008 для информации об этом и больше.

0 голосов
/ 11 ноября 2016

Совершенно отрицательно сказывается на назначении универсального, но вы можете определить класс, производный от универсального, примерно так, с единственной целью возможности использовать этот тип в XAML.

public class MyType : List<int> { }

И используйте его в xaml, например. как

<DataTemplate DataType={x:Type myNamespace:MyType}>
0 голосов
/ 09 февраля 2014

Я полагаю, что в последних версиях .net Framework это можно сделать.

Проверьте Generics в документации XAML . Вам нужно будет использовать x:TypeArguments; Существуют некоторые ограничения, поэтому сначала прочтите документацию.

Также см. Как указать аргумент универсального типа в XAML вопрос о Stackoverflow

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...