您可以使用链接到的装饰器解决方案并进行一些更改,或者您可以使用样式和转换器来做到这一点。
装饰器解决方案
装饰器解决方案更复杂,但有更好的接口和封装。您需要进行的更改很简单,但如果您不是 WPF 专家,可能会很困难。它们是:
将 ComboBox 识别为另一种特殊情况(如 TextBox)。订阅其 SelectedItemChanged,并使用 SelectedItem==null 更新装饰器可见性。
不处理输入事件(HitTestVisible=False、Focusable=False 等)
在这种情况下,您的 ComboBox 样式将非常简单,只需设置附加属性即可。
样式和转换器
使用样式和转换器可能对您来说更简单。这是转换器的主体:
object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value==null ? Visibility.Visible : Visibility.Hidden;
}
您的样式将替换默认的 ComboBox 样式并包含来自主题的 ControlTemplate 的副本,并用类似这样的东西包裹(或使用装饰器):
<Style TargetType="{x:Class ComboBox}">
<Style.Setters>
<Setter Property="local:MyInputPromptClass.PromptText" Value="SELECT an item" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Class ComboBox}">
<Grid>
... existing XAML from theme ControlTemplate ...
<TextBlock
Text="{Binding local:MyInputPromptClass.PromptText, RelativeSource={RelativeSource TemplatedParent}}"
Visibility="{Binding SelectedItem, Converter={x:Static local:MyInputPromptClass.Converter}, RelativeSource={RelativeSource TemplatedParent}}"
HitTestVisible="False" Focusable="False"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
此解决方案不如其他解决方案令人满意,因为通过从主题复制默认 ComboBox 模板,您最终会得到一个不跟踪当前 Windows 主题的应用程序。可以使用多个 ControlTemplates 以及 StaticResource 和一些棘手的绑定来解决这个问题,但那时我建议只使用 adorner 和附加属性。