Я создал UserControl, который расширяет функциональность ComboBox интересными и полезными способами. Когда это выпало, это выглядит так:
Я встроил целую кучу функций в элемент управления, и все они работают гладко. Это заставляет меня поверить, что я что-то понимаю в том, что я делаю. Вы могли бы подумать, что было бы тривиально, чтобы стиль UserControl устанавливал кисть фона редактируемого TextBox. На самом деле, это кажется невероятным. И я сбит с толку.
XAML UserControl, чрезвычайно сокращенно (вы мне за это поблагодарите), выглядит следующим образом:
<UserControl x:Class="MyApp.CodeLookupBox" x:Name="MainControl">
<UserControl.Resources>
<!-- tons of DataTemplates and Styles, most notably the style that
contains the control template for the ComboBox -->
<UserControl.Resources>
<ComboBox x:Name="ComboBox"
Margin="0"
Style="{DynamicResource ComboBoxStyle1}"
VerticalAlignment="Top"
ItemTemplate="{StaticResource GridViewStyleTemplate}"/>
</UserControl>
В этом элементе управления много кода, в основном это свойства зависимостей, которые я использую для таких вещей, как выбор шаблона, который используется в раскрывающемся списке.
Что сводит меня с ума, так это редактируемое текстовое поле. Я хочу иметь возможность установить его кисть фона из стиля пользовательского элемента управления - например, когда я объявляю один из этих пользовательских элементов управления в моем XAML, он использует такой стиль:
<Style TargetType="{x:Type local:CodeLookupBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsRequired}" Value="True">
<Setter Property="EditableTextBoxBackground" Value="{StaticResource RequiredFieldBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
Я начал свою жизнь просто с установки фона UserControl, но это установило фон позади редактируемого TextBox. Сам TextBox остался белым.
Внутри шаблона для ComboBox есть стиль, который управляет этим TextBox:
<Style x:Key="ComboBoxEditableTextBox" TargetType="{x:Type TextBox}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer
x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
И есть TextBox (внутри шаблона элемента управления ComboBox), его плохое «я»:
<TextBox
x:Name="PART_EditableTextBox"
Margin="{TemplateBinding Padding}"
Style="{StaticResource ComboBoxEditableTextBox}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}"/>
Теперь есть определенный элемент вещей, которые человеку не нужно было знать о том стиле ComboBoxEditableTextBox. Что этот ScrollViewer делает там? Я понятия не имею. Я могу сказать вам, что если я закомментирую часть стиля, который устанавливает ControlTemplate TextBox, произойдут очень плохие вещи.
И я также знаю это: если я явно установлю фоновую кисть TextBox в качестве одного из установщиков стиля, ничего не произойдет. Если я явно установлю фон для PART_EditableTextBox, ничего не произойдет. (Я могу установить его передний план или его FontFamily, и они отлично работают.)
Если я явно установлю для фона этого ScrollViewer значение Green, хотя, вуаля, TextBox станет зеленым.
Хорошо, тогда TextBox игнорирует свой собственный фон и использует его из своего шаблона управления. На самом деле, строго говоря, он не использует тот же шаблон управления. Когда я устанавливаю фон ScrollViewer, вокруг краев цвета появляется определенное поле, а не цвет, полностью заполняющий TextBox. Но это поле белого цвета, а не фона.
Если я не могу понять, почему TextBox игнорирует свой Фон, мне придется смириться с настройкой ScrollViewer. Так как же получить его, чтобы получить кисть из свойства EditableTextBoxBackground пользовательского элемента управления? Я сделал это свойство зависимости, которое правильно вызывает событие PropertyChanged при его изменении. Я связываюсь с этим в таинственном XAML ScrollViewer, как это:
Background="{Binding ElementName=MainControl,
Path=EditableTextBoxBackground,
Converter={StaticResource DebuggingConverter}}"
Я установил точку останова в моем отладочном конвертере. Когда элемент управления впервые рисуется, он получает удар дважды. В первый раз значение кисти равно нулю. Во второй раз это правильное значение. И если я установлю свойство в конструкторе моего UserControl , оно будет работать.
Итак, вот что я знаю: свойство My UserControl устанавливается правильно. Привязка к стилю TextBox правильно связана со свойством UserControl. Привязка к ScrollViewer в шаблоне элемента управления TextBox привязана к правому свойству. Свойство вызывает PropertyChanged с правильным именем свойства при его изменении, и привязка передает значение в свойство фона ScrollViewer.
И ничего не происходит.
Итак, я думаю, у меня есть вопрос из трех частей: 1) Почему? 2) Какого черта ScrollViewer делает там в первую очередь? У меня есть подозрения, но сейчас час ночи, и мне становится трудно их сформулировать. 3) Почему Blend дал мне другой шаблон управления для работы, чем гораздо более понятный здесь ?
Действительно, любая помощь будет принята.