Это работает для переопределения цветов фона ComboBoxItem в приложении Xamarin Forms WPF, но не очень элегантно, потому что мне приходится вручную применять шаблоны к ComboBoxItems в пользовательском средстве визуализации:
App.xaml в Application.Resources:
<ControlTemplate TargetType = "{x:Type ComboBoxItem}" x:Key = "CustomComboBoxItem">
<Border BorderThickness = "{TemplateBinding Border.BorderThickness}" Padding = "{TemplateBinding Control.Padding}" BorderBrush = "{TemplateBinding Border.BorderBrush}" Background = "{TemplateBinding Panel.Background}" Name = "Bd" SnapsToDevicePixels = "True">
<ContentPresenter Content = "{TemplateBinding ContentControl.Content}" ContentTemplate = "{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat = "{TemplateBinding ContentControl.ContentStringFormat}" HorizontalAlignment = "{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment = "{TemplateBinding Control.VerticalContentAlignment}" SnapsToDevicePixels = "{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
... All the regular triggers here override with new colors ...
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType = "{x:Type ComboBoxItem}">
<Setter Property='OverridesDefaultStyle' Value='True'/>
<Setter Property = "Template" Value = "{StaticResource CustomComboBoxItem}">
</Setter>
</Style>
В пользовательском PickerRenderer:
protected override void UpdateNativeWidget()
{
base.UpdateNativeWidget();
var c = Control;
if (p == null)
{
template = System.Windows.Application.Current.Resources["CustomComboBoxItem"] as System.Windows.Controls.ControlTemplate;
ItemsPresenter presenter = GetVisualChild<ItemsPresenter>(c);
Popup p = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(c, 0), 0) as Popup;
var a = (((((p.Child) as Decorator).Child as Border).Child as ScrollViewer).Content as System.Windows.Controls.Grid).Children;
presenter = a[1] as ItemsPresenter;
this.p = presenter;
this.p.Loaded += Presenter_Loaded;
}
}
ItemsPresenter p;
ComboBoxItem[] items;
System.Windows.Controls.ControlTemplate template;
private void Presenter_Loaded(object sender, RoutedEventArgs e)
{
items = new ComboBoxItem[Control.ItemContainerGenerator.Items.Count];
for(int i=0;i<items.Length;i++)
{
items[i] = Control.ItemContainerGenerator.ContainerFromIndex(i) as ComboBoxItem;
if (template != null)
{
items[i].Template = template;
}
}
}
Я не могу сделать следующее, иначе я получу следующее исключение:
ArgumentException: элемент уже добавлен. Ключ в словаре: «System.Windows.Controls.ComboBoxItem». Добавляемый ключ: «System.Windows.Controls.ComboBoxItem».
<ControlTemplate TargetType = "{x:Type ComboBoxItem}" x:Key = "{x:Type ComboBoxItem}">
</ControlTemplate>
или это, значения по умолчанию не будут переопределены:
<ControlTemplate TargetType = "{x:Type ComboBoxItem}" x:Key = "CustomComboBoxItem">
</ControlTemplate>
<Style TargetType = "{x:Type ComboBoxItem}" x:Key = "{x:Type ComboBoxItem}">
<Setter Property='OverridesDefaultStyle' Value='True'/>
<Setter Property = "Template" Value = "{StaticResource CustomComboBoxItem}">
</Setter>
</Style>
Есть ли более простой и элегантный способ сделать то, что я хочу сделать здесь?
Если вы хотите установить шаблон comBoxItem по умолчанию во всем приложении как customComboxItem. Вы просто помещаете ресурс стиля в app.xaml.
<Application.Resources>
<Style TargetType = "{x:Type ComboBoxItem}" x:Key = "{x:Type ComboBoxItem}">
<Setter Property='OverridesDefaultStyle' Value='True'/>
<Setter Property = "Template" Value = "{StaticResource CustomComboBoxItem}">
</Setter>
</Style>
</Application.Resources>
Принимая это как ответ. У меня было место в моем коде в PickerRenderer OnElementChanged, где использовался Contrtol.ItemContainerStyle, из-за которого стили Application.Resources не применялись.