Вы уверены, что вам нужно изменить стиль HeaderedContentControl, а не ContentTemplate в зависимости от динамического типа контента? Другими словами: вам нужно изменить стиль элемента управления или вам просто нужно изменить шаблон данных элемента?
Поскольку существует очень удобное свойство ContentTemplateSelector, и если вы напишите очень простой класс, вы сможете выбрать DataTemplate на основе динамического типа контента.
Если это не так, и вы уверены, что вам нужно изменить стиль, то не могли бы вы немного рассказать, какие части стиля вы хотите изменить - возможно, существует обходной путь для того же ContentTemplateSelector.
Если вы настаиваете на изменении стилей, подумайте немного об использовании триггера данных внутри вашего стиля - с помощью очень простого конвертера вы сможете изменять определенные свойства (или все, если хотите) вашего стиля.
Я буду рад оказать вам дальнейшую помощь, как только вы разработаете детали вашей проблемы.
UPD : ОК, автор настаивает на том, что ему нужно изменить стиль. Вот два возможных способа, как вы можете это сделать.
Первое и простое решение, но строго ограниченное: поскольку ваш контент Header
может быть указан с помощью контента Content
, вы можете сделать это:
<DataTemplate x:Key="DefaultTemplate">
<HeaderedContentControl Content="{Binding}"
Header="{Binding DisplayName}"
Style="{StaticResource DefaultStyle}" />
</DataTemplate>
<DataTemplate x:Key="CarTemplate"
DataType="dm:Car">
<HeaderedContentControl Content="{Binding}"
Header="{Binding DisplayName}"
Style="{StaticResource CarStyle}" />
</DataTemplate>
<DataTemplate x:Key="BoatTemplate"
DataType="dm:Boat">
<HeaderedContentControl Content="{Binding}"
Header="{Binding DisplayName}"
Style="{StaticResource BoatStyle}" />
</DataTemplate>
<u:TypeBasedDataTemplateSelector x:Key="MySelector"
DefaultTemplate="{StaticResource DefaultTemplate}"
NullTemplate="{StaticResource DefaultTemplate}">
<u:TypeMapping Type="dm:Car" Template="{StaticResource CarTemplate}" />
<u:TypeMapping Type="dm:Boat" Template="{StaticResource BoatTemplate}" />
</u:TypeBasedDataTemplateSelector>
<ContentPresenter Content="{Binding LeftChild}"
ContentTemplateSelector="{StaticResource MySelector}" />
Единственный код, который вам понадобится для поддержки этого чисто декларативного решения, - это очень простая реализация селектора шаблонов. Вот оно:
public class TypeMapping
{
public Type Type { get; set; }
public DataTemplate Template { get; set; }
}
public class TypeBasedDataTemplateSelector : DataTemplateSelector, IAddChild
{
public DataTemplate DefaultTemplate { get; set; }
public DataTemplate NullTemplate { get; set; }
private readonly Dictionary<Type, DataTemplate> Mapping = new Dictionary<Type, DataTemplate>();
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item == null)
return NullTemplate;
DataTemplate template;
if (!Mapping.TryGetValue(item.GetType(), out template))
template = DefaultTemplate;
return template;
}
#region IAddChild Members
public void AddChild(object value)
{
if (!(value is TypeMapping))
throw new Exception("...");
var tm = (TypeMapping)value;
Mapping.Add(tm.Type, tm.Template);
}
public void AddText(string text)
{
throw new NotImplementedException();
}
#endregion
}
Второе решение является более общим и может применяться к случаям, когда контент Header
не имеет ничего общего с контентом Content
. Он основан на возможностях конвертера Binding.
<Style x:Key="StandardHeaderedStyle">
<!--...-->
</Style>
<Style x:Key="CarHeaderedStyle"
BasedOn="{StaticResource StandardHeaderedStyle}">
<!--...-->
</Style>
<Style x:Key="BoatHeaderedStyle"
BasedOn="{StaticResource StandardHeaderedStyle}">
<!--...-->
</Style>
<Style x:Key="UnknownHeaderedStyle"
BasedOn="{StaticResource StandardHeaderedStyle}">
<!--...-->
</Style>
<u:StylesMap x:Key="MyStylesMap"
FallbackStyle="{StaticResource UnknownHeaderedStyle}">
<u:StyleMapping Type="Car" Style="{StaticResource CarHeaderedStyle}" />
<u:StyleMapping Type="Boat" Style="{StaticResource BoatHeaderedStyle}" />
</u:StylesMap>
<u:StyleSelectorConverter x:Key="StyleSelectorConverter" />
<HeaderedContentControl Content="{Binding LeftChild}"
Header="{Binding LeftChild.DisplayName}">
<HeaderedContentControl.Style>
<Binding Path="LeftChild"
Converter="{StaticResource StyleSelectorConverter}"
ConverterParameter="{StaticResource MyStylesMap}" />
</HeaderedContentControl.Style>
</HeaderedContentControl>
Также требуется код поддержки:
public class StyleMapping
{
public Type Type { get; set; }
public Style Style { get; set; }
}
public class StylesMap : Dictionary<Type, Style>, IAddChild
{
public Style FallbackStyle { get; set; }
#region IAddChild Members
public void AddChild(object value)
{
if (!(value is StyleMapping))
throw new InvalidOperationException("...");
var m = (StyleMapping)value;
this.Add(m.Type, m.Style);
}
public void AddText(string text)
{
throw new NotImplementedException();
}
#endregion
}
public class StyleSelectorConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var m = (StylesMap)parameter;
if (value == null)
return m.FallbackStyle;
Style style;
if (!m.TryGetValue(value.GetType(), out style))
style = m.FallbackStyle;
return style;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
НТН