DataTemplateSelector и Windows 8
У меня очень странная проблема. Я написал приложение, используя wpf, telerik(тема office2007). Я использую DataTemplateSelector для динамического создания представления для разных типов моделей. В Windows 7 все хорошо и хорошо работает, но в Windows 8 DataTemplateSelector не работает! WTF? Можете ли вы помочь мне с моей проблемой?
public class TabDataTemplateSelector:DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if(item==null || container == null)
return null;
FrameworkElement element = Application.Current.MainWindow as FrameworkElement;
if (element == null)
return null;
if (item is PetrochemicalCatalogViewModel)
{
return element.FindResource("PetrochemicalCatalogDataTemplate") as DataTemplate;
}
if (item is FuelPriceViewModel)
{
return element.FindResource("FuelPriceDataTemplate") as DataTemplate;
}
if (item is RoleViewModel)
{
return element.FindResource("RoleDataTemplate") as DataTemplate;
}
if (item is IEquipmentViewModel)
{
return element.FindResource("EquipmentDataTemplate") as DataTemplate;
}
if (item is IZondsViewModel)
{
return element.FindResource("ZondDataTemplate") as DataTemplate;
}
if (item is ITankCatalogViewModel)
{
return element.FindResource("TanksDataTemplate") as DataTemplate;
}
if (item is IDispensersWorkplaceViewModel)
{
return element.FindResource("DispensingDataTemplate") as DataTemplate;
}
if (item is IDispenserSetsWorkplaceViewModel)
{
return element.FindResource("DispenserSetsWorkplaceTemplate") as DataTemplate;
}
if (item is IPaymentTypeCatalogViewModel)
{
return element.FindResource("PaymentTypeWorkplaceTemplate") as DataTemplate;
}
if (item is ICashManagementViewModel)
{
return element.FindResource("CashManagementTemplate") as DataTemplate;
}
if (item is ITerminalWorkplaceViewModel)
{
return element.FindResource("TerminalDataTemplate") as DataTemplate;
}
if (item is IPriceingWorkplaceViewModel)
{
return element.FindResource("PriceingDataTemplate") as DataTemplate;
}
return null;
}
}
<local:TabDataTemplateSelector x:Key="tabDataTemplateSelector"/>
<DataTemplate x:Key="TabContentTemplate">
<telerik:RadBusyIndicator x:Name="rbiBusy" VerticalAlignment="Stretch" IsBusy="{Binding IsBusy}" HorizontalContentAlignment="Stretch" telerik:StyleManager.Theme="Windows8Touch" VerticalContentAlignment="Stretch">
<ContentPresenter ContentTemplateSelector="{StaticResource tabDataTemplateSelector}" Content="{Binding TabContentViewModel}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</telerik:RadBusyIndicator>
</DataTemplate>
2 ответа
Вещи немного отличаются от Windows 7 и Windows 8. У меня была та же проблема, и я обнаружил, что свойство DataType не поддерживает DataTemplate в Windows 8, поэтому мне пришлось выбрать его на основе их имени и использовать пользовательский DataTemplateSelector, Вот и извлечение моего кода, где список заполнен разными типами:
XAML:
<UserControl.Resources>
<s:CustomDataTemplateSelector
x:Key="CustomDataTemplateSelector" />
<DataTemplate
x:Key="Activity1">
<c:ActivityControl1 />
</DataTemplate>
<DataTemplate
x:Key="Activity2">
<c:ActivityControl2 />
</DataTemplate>
</UserControl.Resources>
<Grid>
<ListView
FontSize="20"
BorderThickness="0"
Foreground="Black"
ItemsSource="{Binding Activities}"
HorizontalContentAlignment="Stretch"
ItemTemplateSelector="{StaticResource CustomDataTemplateSelector}" />
</Grid>
CS:
public class CustomDataTemplateSelector : DataTemplateSelector
{
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
string key = item.GetType().Name;
FrameworkElement element = container as FrameworkElement;
while (element != null)
{
if (element.Resources.ContainsKey(key))
return element.Resources[key] as DataTemplate;
element = VisualTreeHelper.GetParent(element) as FrameworkElement;
}
return Application.Current.Resources[key] as DataTemplate;
}
}
Надеюсь это поможет.
Стандартный способ сделать то, что вы хотите, это поставить каждый из ваших DataTemplate
с в UserControl
(без DataTemplate
объект, например просто добавьте содержимое), назовите их ...View
(где '...' происходит из соответствующего класса модели представления) и соедините их с вашими моделями представления, используя DataTemplate
определены в App.xaml
:
<DataTemplate DataType="{x:Type ViewModels:PetrochemicalCatalogViewModel}">
<Views:PetrochemicalCatalogView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:FuelPriceViewModel}">
<Views:FuelPriceView />
</DataTemplate>
...
<DataTemplate DataType="{x:Type ViewModels:IPriceingWorkplaceViewModel}">
<Views:IPriceingWorkplaceView />
</DataTemplate>