web-dev-qa-db-ja.com

XAML(.NET 4 Framework以前)でジェネリック型を指定できますか?

XAMLでは、特定の型が表示されるたびにテンプレートが使用されるように、DataTemplateを宣言できます。たとえば、このDataTemplateはTextBlockを使用して顧客の名前を表示します。

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

IList <Customer>が表示されるときにいつでも使用されるDataTemplateを定義できるかどうか疑問に思っています。したがって、ContentControlのコンテンツが、たとえばObservableCollection <Customer>である場合、そのテンプレートを使用します。

{x:Type}マークアップ拡張機能を使用して、XAMLでIListのようなジェネリック型を宣言することは可能ですか?

72
Matt Hamilton

箱から出していない、いいえ。しかし、そうしている進取の気性のある開発者がいます。

たとえば、MicrosoftのMike Hillbergは この投稿 でそれを試しました。 Googleにはもちろん他にもあります。

24
ageektrapped

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;
    }
}
31
Ian Oakes

Tを指定する派生クラスでジェネリッククラスをラップすることもできます

public class StringList : List<String>{}

xAMLのStringListを使用します。

21
Claudiu Mihaila

aelij( WPF Contrib プロジェクトのプロジェクトコーディネーター)には、別の way があります。

さらにクールなのは(将来的にはいつかはオフになりますが)... XAML 2009(XAML 2006が現在のバージョンです)がこれをネイティブにサポートすることです。詳細については、こちらをご覧ください PDC 2008セッション .

7
cplotts

.netフレームワークの再送信バージョンでは、これを行うことができます。

XAMLドキュメントのジェネリック を確認してください。 x:TypeArguments ;を使用する必要があります。いくつかの制限があるため、最初にドキュメントをお読みください。

Stackoverflowの XAMLでジェネリック型引数を指定する方法 の質問も参照してください

0
Ian Ringrose

ジェネリックの目的はかなり打ち負かされますが、XAMLでそのタイプを使用できるという唯一の目的で、ジェネリックから派生したクラスを定義できます。

public class MyType : List<int> { }

そして、xamlで使用します。お気に入り

<DataTemplate DataType={x:Type myNamespace:MyType}>
0
Mike de Klerk