Ответ 1
Не из коробки, нет; но есть предприимчивые разработчики, которые это сделали.
Майк Хиллберг в Microsoft играл с ним в этот пост, например. Разумеется, у Google есть другие.
В XAML я могу объявить DataTemplate, чтобы шаблон использовался всякий раз, когда отображается определенный тип. Например, этот DataTemplate будет использовать TextBlock для отображения имени клиента:
<DataTemplate DataType="{x:Type my:Customer}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
Мне интересно, можно ли определить DataTemplate, который будет использоваться в любое время, когда IList <Customer> отображается. Поэтому, если ContentControl Content является, скажем, ObservableCollection <Customer> он будет использовать этот шаблон.
Можно ли объявить общий тип типа IList в XAML с помощью расширения {x: Type} Markup Extension?
Не из коробки, нет; но есть предприимчивые разработчики, которые это сделали.
Майк Хиллберг в Microsoft играл с ним в этот пост, например. Разумеется, у Google есть другие.
Не в 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;
}
}
Вы также можете обернуть свой общий класс в производном классе, который указывает T
public class StringList : List<String>{}
и используйте StringList из XAML.
aelij (координатор проекта для проекта WPF Contrib) имеет еще один путь, чтобы сделать это.
Что еще круче (хотя в какой-то момент это когда-то)... что XAML 2009 (XAML 2006 - это текущая версия) будет поддерживать это изначально. Ознакомьтесь с этим сеансом PDC 2008 для получения информации об этом и многом другом.
Я могу сказать, что в resent версиях .NET Framework это можно сделать.
Проверьте Общие сведения в документации XAML. Вам нужно будет использовать x:TypeArguments
; есть некоторые ограничения, поэтому сначала прочтите документацию.
Также см. Как задать аргумент типового типа в XAML на Stackoverflow
Совершенно поражает цель общего, но вы можете определить класс, который происходит из общего типа, таким образом, с единственной целью - использовать этот тип в XAML.
public class MyType : List<int> { }
И используйте его в xaml, например. как
<DataTemplate DataType={x:Type myNamespace:MyType}>