在我的 WPF 应用程序中,我重新设计了 ComboBox。问题是我似乎无法正确应用 BorderThickness。我认为我做得对,但我必须遗漏一些东西,因为结果不是我所期望的(它始终保持为 1 的厚度)。
UserControl 中使用的 ComboBox(注意厚度为 3):
<ComboBox DockPanel.Dock="Top" SelectedItem="{Binding CurrentAnalysisKey}"
ItemsSource="{Binding AnalysisKeys}" Height="25"
BorderBrush="{StaticResource ListBoxBorderBrush}"
BorderThickness="3"
DisplayMemberPath="ReaffectedName" Margin="0,5" />
资源文件中定义的 ComboBox 样式:
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Foreground"
Value="White" />
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="BorderBrush"
Value="{StaticResource BlackBorderBrush}" />
<Setter Property="BorderThickness"
Value="2" />
<Setter Property="Template"
Value="{DynamicResource ComboBoxTemplate}" />
</Style>
<Style d:IsControlPart="True"
TargetType="{x:Type ComboBoxItem}">
<Setter Property="Foreground"
Value="White" />
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<ControlTemplate.Resources>
<Storyboard x:Key="HoverOn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="HoverRectangle"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="HoverOff">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="HoverRectangle"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.4000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="SelectedOn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="SelectedRectangle"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="SelectedOff">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="SelectedRectangle"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.4000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid SnapsToDevicePixels="true"
Margin="1"
IsHitTestVisible="True">
<Rectangle x:Name="Background"
IsHitTestVisible="True"
Opacity="0.25"
Fill="{StaticResource NormalBrush}"
RadiusX="1"
RadiusY="1" />
<Rectangle x:Name="HoverRectangle"
IsHitTestVisible="True"
Opacity="0"
Fill="{StaticResource NormalBrush}"
RadiusX="1"
RadiusY="1" />
<Rectangle x:Name="SelectedRectangle"
IsHitTestVisible="False"
Opacity="0"
Fill="{StaticResource SelectedBackgroundBrush}"
RadiusX="1"
RadiusY="1" />
<ContentPresenter Margin="5,2,0,2"
x:Name="contentPresenter"
VerticalAlignment="Center" />
<Rectangle x:Name="FocusVisualElement"
Visibility="Collapsed"
Stroke="{StaticResource HoverShineBrush}"
StrokeThickness="1"
RadiusX="1"
RadiusY="1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted"
Value="true">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource SelectedOff}"
x:Name="SelectedOff_BeginStoryboard" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource SelectedOn}"
x:Name="SelectedOn_BeginStoryboard" />
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsMouseOver"
Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource HoverOff}"
x:Name="HoverOff_BeginStoryboard" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource HoverOn}" />
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="{DynamicResource DisabledForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Static ToolBar.ComboBoxStyleKey}"
TargetType="{x:Type ComboBox}">
<Setter Property="FontSize"
Value="10" />
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="Template"
Value="{DynamicResource ComboBoxTemplate}" />
<Setter Property="Foreground"
Value="White" />
</Style>
ComboBox 模板:(ThicknessConverter 用于将接收到的厚度吐出到调试窗口中)
<ControlTemplate x:Key="ComboBoxTemplate"
TargetType="{x:Type ComboBox}">
<Grid x:Name="grid">
<Grid.Resources>
<converters:ComboBoxThicknessConverter x:Key="thicknessConv" />
</Grid.Resources>
<ToggleButton Template="{DynamicResource ComboBoxToggleButton}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
x:Name="ToggleButton"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press" />
<ContentPresenter HorizontalAlignment="Left"
x:Name="ContentSite"
Margin="{TemplateBinding BorderThickness, Converter={StaticResource thicknessConv}}"
VerticalAlignment="Center"
Content="{TemplateBinding SelectedItem}"
ContentTemplate="{TemplateBinding ItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
IsHitTestVisible="False" />
<Popup IsOpen="{TemplateBinding IsDropDownOpen}"
Placement="Bottom"
x:Name="Popup"
Focusable="False"
AllowsTransparency="True"
PopupAnimation="Slide">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}"
MinWidth="{TemplateBinding ActualWidth}"
x:Name="DropDown"
SnapsToDevicePixels="True">
<Border x:Name="DropDownBorder"
Background="{DynamicResource ControlBackgroundBrush}"
CornerRadius="3" />
<ScrollViewer Margin="4,6"
Style="{DynamicResource NuclearScrollViewer}"
SnapsToDevicePixels="True"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
CanContentScroll="True"
Foreground="{DynamicResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems"
Value="false">
<Setter Property="MinHeight"
Value="95"
TargetName="DropDownBorder" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="{DynamicResource DisabledForegroundBrush}" />
<Setter Property="Opacity"
TargetName="grid"
Value="0.5" />
</Trigger>
<Trigger Property="IsGrouping"
Value="true">
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</Trigger>
<Trigger Property="AllowsTransparency"
SourceName="Popup"
Value="true">
<Setter Property="Margin"
Value="0,2,0,0"
TargetName="DropDownBorder" />
</Trigger>
<Trigger Property="local:Dragging.IsDragTarget"
Value="True">
<Setter Property="BorderBrush"
Value="{StaticResource DragTargetBorderBrush}"
TargetName="ToggleButton" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
组合框切换按钮:
<ControlTemplate x:Key="ComboBoxToggleButton"
TargetType="{x:Type ToggleButton}">
<Grid x:Name="grid">
<Grid.Resources>
<converters:SpecialThicknessConverter x:Key="cv2" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Rectangle Grid.ColumnSpan="2"
HorizontalAlignment="Stretch"
x:Name="Rectangle"
VerticalAlignment="Stretch"
RadiusX="3"
RadiusY="3"
StrokeThickness="{TemplateBinding BorderThickness, Converter={StaticResource cv2}}"
Fill="{DynamicResource LightBrush}"
Stroke="{TemplateBinding BorderBrush}" />
<Border Grid.Column="1"
Margin="2"
Background="{DynamicResource BorderBrush}"
CornerRadius="3"
x:Name="border" />
<Border Grid.Column="1"
Margin="2"
Background="{DynamicResource HoverBrush}"
CornerRadius="3"
x:Name="HoverBorder"
Opacity="0" />
<Border Grid.Column="1"
Margin="2"
Background="{DynamicResource HoverShineBrush}"
CornerRadius="3"
x:Name="HoverShineBorder"
Opacity="0" />
<Path Grid.Column="1"
HorizontalAlignment="Center"
x:Name="Arrow"
VerticalAlignment="Center"
Fill="{x:Null}"
Data="M0.5,0.5 L3,6.5 5.5,0.5"
Stroke="{DynamicResource GlyphBrush}"
Margin="5,0"
Height="7"
StrokeThickness="2"
Stretch="Fill" />
<Border Grid.Column="1"
Margin="2"
Background="{DynamicResource ShineBrush}"
CornerRadius="3"
x:Name="ShineBorder" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource HoverOff}"
x:Name="HoverOff_BeginStoryboard" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource HoverOn}" />
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsChecked"
Value="true" />
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource DisabledForegroundBrush}" />
<Setter Property="Stroke"
TargetName="Arrow"
Value="{DynamicResource DisabledForegroundBrush}" />
<Setter Property="Background"
TargetName="border"
Value="{DynamicResource DisabledBorderBrush}" />
<Setter Property="Opacity"
TargetName="grid"
Value="0.8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
其中一个厚度转换器用于为构成 ComboBox 右侧的按钮的边框和路径留出空间(20 像素)。两者都包括在下面:
public class ComboBoxThicknessConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var oldT = (Thickness)value;
//Debug.WriteLine("cbx templ thickness = {" + oldT.Left + ", " + oldT.Top + ", " + oldT.Right + ", " + oldT.Bottom + "}");
return new Thickness(oldT.Left, oldT.Top, oldT.Right + 20, oldT.Bottom);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
public class SpecialThicknessConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var oldT = (Thickness)value;
Debug.WriteLine("toggle btn thickness = {" + oldT.Left + ", " + oldT.Top + ", " + oldT.Right + ", " + oldT.Bottom + "}");
return oldT;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
除非我在 ComboBoxToggleButton 内手动将 StrokeThickness 更改为硬编码值,否则我总是得到相同的厚度:1。
有什么想法我哪里出错了吗?据我了解,我正在将 ComboBox 中的 BorderThickness 沿着层次结构的每一级正确传递到 ComboBoxToggleButton 中的 Rectangle 中。但是,当我查看调试窗口时,我看到了 ComboBox 样式中设置器中使用的值,而不是声明 ComboBox 时使用的值。
提前致谢!
肖恩