In XAML kann ich eine DataTemplate deklarieren, sodass die Vorlage immer dann verwendet wird, wenn ein bestimmter Typ angezeigt wird. In dieser DataTemplate wird beispielsweise ein TextBlock verwendet, um den Namen eines Kunden anzuzeigen:
<DataTemplate DataType="{x:Type my:Customer}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
Ich frage mich, ob es möglich ist, eine DataTemplate zu definieren, die jedes Mal verwendet wird, wenn eine IList <Kunde> angezeigt wird. Wenn der Inhalt eines ContentControls beispielsweise eine ObservableCollection <Kunde> ist, wird diese Vorlage verwendet.
Ist es möglich, einen generischen Typ wie IList in XAML mit der Markup-Erweiterung {x: Type} zu deklarieren?
Antworten:
Nicht sofort einsatzbereit, nein; Aber es gibt unternehmungslustige Entwickler, die dies getan haben.
Mike Hillberg von Microsoft hat zum Beispiel in diesem Beitrag damit gespielt. Google hat natürlich andere.
quelle
Nicht direkt in XAML, Sie können jedoch auf eine
DataTemplateSelector
von XAML verweisen , um die richtige Vorlage auszuwählen.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; } }
Das Ressourcenwörterbuch:
<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>
Das Fenster 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>
Der Fenstercode dahinter:
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; } }
quelle
Sie können Ihre generische Klasse auch in eine abgeleitete Klasse einschließen, die das T angibt
public class StringList : List<String>{}
und verwenden Sie StringList von XAML.
quelle
aelij (der Projektkoordinator für das WPF Contrib- Projekt) hat eine andere Möglichkeit , dies zu tun.
Was noch cooler ist (obwohl es irgendwann in der Zukunft nicht mehr möglich ist) ... ist, dass XAML 2009 (XAML 2006 ist die aktuelle Version) dies nativ unterstützen wird. In dieser PDC 2008-Sitzung finden Sie Informationen dazu und mehr.
quelle
Der Zweck eines Generikums ist ziemlich zunichte gemacht, aber Sie können eine Klasse definieren, die sich wie folgt vom Generikum ableitet, mit dem einzigen Zweck, diesen Typ in XAML verwenden zu können.
public class MyType : List<int> { }
Und benutze es in xaml zB wie
<DataTemplate DataType={x:Type myNamespace:MyType}>
quelle