WPF开发中重写Combox样式遇到的一些问题


在实际的WPF开发过程中,你可能需要自定义ComBox的样式,重写的样式可能不出效果,背景色无法正常显示,或者是显示的内容出现白色遮罩,如以下的效果:

1.ComBox样式如下:

 <Style TargetType="TextBlock" x:Key="BaseTextBlockStyle">
	 <Setter Property="FontSize" Value="14"/>
	 <Setter Property="FontFamily" Value="Arial"/>
	 <Setter Property="FontWeight" Value="Normal"/>
	 <Setter Property="Opacity" Value="1"/>
	 <Setter Property="Background" Value="{x:Null}"/>
	 <Setter Property="Foreground" Value="White"/>
	 <Setter Property="VerticalAlignment" Value="Center"/>
	 <Setter Property="HorizontalAlignment" Value="Center"/>
	 <Setter Property="Padding" Value="0"/>
	 <!--<Style.Triggers>
		 <Trigger Property="IsMouseOver" Value="True">
			 <Setter Property="Foreground" Value="White"/>
			 <Setter Property="Cursor" Value="Hand"/>
		 </Trigger>
	 </Style.Triggers>-->
 </Style>

<Style x:Key="BaseComboBoxStyle" TargetType="ComboBox">
	<Setter Property="FontSize" Value="14"/>
	<Setter Property="FontFamily" Value="Arial"/>
	<Setter Property="Margin" Value="5,0,5,0"/>
	<Setter Property="VerticalAlignment" Value="Center"/>
	<Setter Property="HorizontalAlignment" Value="Right"/>
	<Setter Property="Width" Value="160"/>
	<Setter Property="Height" Value="32"/>
	<Setter Property="Background" Value="#0D0D19"/>
	<Setter Property="BorderThickness" Value="0"/>
	<Setter Property="IsEditable" Value="False"/>
	<Setter Property="ItemTemplate">
		<Setter.Value>
			<DataTemplate>
				<StackPanel Orientation="Horizontal">
					<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="5,0,0,0" Style="{StaticResource ResourceKey=BaseTextBlockStyle}"/>
				</StackPanel>
			</DataTemplate>
		</Setter.Value>
	</Setter>
</Style>

页面展示如下:

 <ComboBox     Tag="SelectTestPositonList"
			   ItemsSource="{Binding SelectTestPositonList, Mode=OneWay}" 
			   SelectedItem="{Binding SelectTestPositionItem}"
			   SelectionChanged="ComboBox_SelectionChanged">
	 <ComboBox.ItemTemplate>
		 <DataTemplate>
			 <StackPanel Orientation="Horizontal">
				 <TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="5,0,0,0" Style="{StaticResource ResourceKey=BaseTextBlockStyle}"/>
			 </StackPanel>
		 </DataTemplate>
	 </ComboBox.ItemTemplate>
 </ComboBox>

运行效果如下:

2.原因

这是因为 WPF 默认的 ComboBox 模板中,其子元素(如 ToggleButton、ContentPresenter、Popup 等)有独立的样式,你仅仅设置 Background 并不会影响内部结构,尤其是:

  • 下拉按钮(ToggleButton)
  • 选中项显示区域
  • 下拉列表(Popup)

解决方案:重写 ComboBox 的控件模板(ControlTemplate)

3.重写样式:

<Style TargetType="TextBlock" x:Key="BaseTextBlockStyle">
	<Setter Property="FontSize" Value="14"/>
	<Setter Property="FontFamily" Value="Arial"/>
	<Setter Property="FontWeight" Value="Normal"/>
	<Setter Property="Opacity" Value="1"/>
	<Setter Property="Background" Value="{x:Null}"/>
	<Setter Property="Foreground" Value="White"/>
	<Setter Property="VerticalAlignment" Value="Center"/>
	<Setter Property="HorizontalAlignment" Value="Center"/>
	<Setter Property="Padding" Value="0"/>
	<!--<Style.Triggers>
		<Trigger Property="IsMouseOver" Value="True">
			<Setter Property="Foreground" Value="White"/>
			<Setter Property="Cursor" Value="Hand"/>
		</Trigger>
	</Style.Triggers>-->
</Style>

<Style x:Key="BaseComboBoxStyle" TargetType="ComboBox">
	<Setter Property="Foreground" Value="White"/>
	<Setter Property="Background" Value="#0D0D19"/>
	<Setter Property="BorderThickness" Value="0"/>
	<Setter Property="FontSize" Value="14"/>
	<Setter Property="FontFamily" Value="Arial"/>
	<Setter Property="Width" Value="160"/>
	<Setter Property="Height" Value="32"/>
	<Setter Property="HorizontalAlignment" Value="Right"/>
	<Setter Property="VerticalAlignment" Value="Center"/>
	<Setter Property="Margin" Value="5,0,5,0"/>
	<Setter Property="IsEditable" Value="False"/>
	<Setter Property="ItemTemplate">
		<Setter.Value>
			<DataTemplate>
				<StackPanel Orientation="Horizontal">
					<TextBlock Text="{Binding Name}" Margin="5,0,0,0" Style="{StaticResource BaseTextBlockStyle}" />
				</StackPanel>
			</DataTemplate>
		</Setter.Value>
	</Setter>
	<Setter Property="Template">
		<Setter.Value>
			<ControlTemplate TargetType="ComboBox">
				<Grid>
					<ToggleButton
						Name="ToggleButton"
						IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
						ClickMode="Press"
						Background="{TemplateBinding Background}"
						BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}">
						<Grid>
							<ContentPresenter
								Name="ContentSite"
								IsHitTestVisible="False"
								Content="{TemplateBinding SelectionBoxItem}"
								ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
								VerticalAlignment="Center"
								HorizontalAlignment="Left" Width="160"
								Margin="6,0,0,0"
								RecognizesAccessKey="True"/>
							<Path
								HorizontalAlignment="Right"
								Margin="0,0,6,0"
								VerticalAlignment="Center"
								Data="M 0 0 L 4 4 L 8 0 Z"
								Fill="White"/>
						</Grid>
					</ToggleButton>
					<Popup
						Name="Popup"
						Placement="Bottom"
						IsOpen="{TemplateBinding IsDropDownOpen}"
						AllowsTransparency="True"
						Focusable="False"
						PopupAnimation="Slide">
						<Grid
							Name="DropDown"
							SnapsToDevicePixels="True"
							MinWidth="{TemplateBinding ActualWidth}"
							MaxHeight="200"
							Background="#0D0D19">
							<Border x:Name="DropDownBorder" BorderThickness="0" Background="#0D0D19"/>
							<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
								<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
							</ScrollViewer>
						</Grid>
					</Popup>
				</Grid>
				<ControlTemplate.Triggers>
					<Trigger Property="HasItems" Value="false">
						<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
					</Trigger>
					<Trigger Property="IsEnabled" Value="false">
						<Setter Property="Foreground" Value="Gray"/>
					</Trigger>
					<Trigger Property="IsMouseOver" Value="True">
						<Setter Property="Background" Value="#1A1A2A"/>
					</Trigger>
				</ControlTemplate.Triggers>
			</ControlTemplate>
		</Setter.Value>
	</Setter>
</Style>

使用方式如下:

效果图1:

效果图2:

如果本文介绍对你有帮助,可以一键四连:点赞+评论+收藏+推荐,谢谢!