<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}"> <Grid x:Name="grid"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="20" /> </Grid.ColumnDefinitions> <Rectangle Grid.ColumnSpan="2" HorizontalAlignment="Stretch" x:Name="Rectangle" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="3" RadiusY="3" Fill="LightBlue" /> <!--Combobox控件外殼--> <Rectangle Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="3" RadiusY="3" Fill="Gray" /> <!--除開下拉按鈕的其他部分--> <Border Margin="2,2,2,2" Grid.Column="1" Background="Red" Width="Auto" CornerRadius="3,3,3,3" x:Name="drop_border" /> <Path Grid.Column="1" HorizontalAlignment="Center" Width="Auto" x:Name="Arrow" VerticalAlignment="Center" Fill="{x:Null}" Data="M0.5,0.5 L3,6.5 5.5,0.5" Stroke="Black" Margin="5,0,5,0" Height="7" StrokeThickness="2" Stretch="Fill" /> <!--Border 和 Path為下拉按鈕--> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="drop_border" Property="Background" Value="White" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> <ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}"> <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" /> </ControlTemplate> <Style TargetType="{x:Type ComboBox}"> <Setter Property="SnapsToDevicePixels" Value="true" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBox}"> <Border BorderBrush="Orange" x:Name="border"> <Grid x:Name="grid"> <ToggleButton Template="{StaticResource ComboBoxToggleButton}" x:Name="ToggleButton" Focusable="false" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" /> <ContentPresenter HorizontalAlignment="Left" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False" /> <TextBox Visibility="Hidden" Margin="2,2,22,2" x:Name="PART_EditableTextBox" Style="{x:Null}" VerticalAlignment="Center" Focusable="True" IsReadOnly="{TemplateBinding IsReadOnly}" Foreground="Black" HorizontalAlignment="Stretch" Background="Azure" /> <!--文本輸入框,當IsEditable為true 才顯示--> <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="WhiteSmoke" CornerRadius="3,3,3,3" /> <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True" Foreground="{StaticResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}"> <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" /> </ScrollViewer> </Grid> </Popup> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="HasItems" Value="false"> <Setter Property="MinHeight" Value="95" TargetName="DropDownBorder" /> </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="IsEditable" Value="true"> <Setter Property="IsTabStop" Value="false" /> <Setter Property="Visibility" Value="Visible" TargetName="PART_EditableTextBox" /> <Setter Property="Visibility" Value="Hidden" TargetName="ContentSite" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
一直沒搞懂Combobox具體是怎么設計的,今天抽空研究了一下,終於看懂了,主要有3個控件組成,ToggleButton,TextBox 和Popup,
ToggleButton:整個控件是由ToggleButton鋪滿的HorizontalAlignment="Stretch",ToggleButton里面由一個Rectangle鋪滿,設置Combobox的圓角,邊框及背景顏色,然后寬度20px的Border,path 為下拉按鈕樣式, 點擊combobox下拉按鈕實際是點擊ToggleButton
TextBox :當IsEditable為True,會把Textbox 顯示出來,Textbox是覆蓋在ToggleButton之上的, 注意應設置HorizontalAlignment="Stretch",這樣才會把Textbox鋪滿,網上很多設置的是Left,很不好選中TextBox,其次還應設置Margin="2,2,22,2",距右邊22px,這樣才不能遮擋出下拉按鈕
Popup:用於顯示ComboboxItem
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}"> <Grid x:Name="grid"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="20" /> </Grid.ColumnDefinitions> <Rectangle Grid.ColumnSpan="2" HorizontalAlignment="Stretch" x:Name="Rectangle" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="3" RadiusY="3" Fill="LightBlue" /> <!--Combobox控件外殼--> <Rectangle Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="3" RadiusY="3" Fill="Gray" /> <!--除開下拉按鈕的其他部分--> <Border Margin="2,2,2,2" Grid.Column="1" Background="Red" Width="Auto" CornerRadius="3,3,3,3" x:Name="drop_border" /> <Path Grid.Column="1" HorizontalAlignment="Center" Width="Auto" x:Name="Arrow" VerticalAlignment="Center" Fill="{x:Null}" Data="M0.5,0.5 L3,6.5 5.5,0.5" Stroke="Black" Margin="5,0,5,0" Height="7" StrokeThickness="2" Stretch="Fill" /> <!--Border 和 Path為下拉按鈕--> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="drop_border" Property="Background" Value="White" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate>
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}"> <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" /> </ControlTemplate> <Style TargetType="{x:Type ComboBox}"> <Setter Property="SnapsToDevicePixels" Value="true" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBox}"> <Border BorderBrush="Orange" x:Name="border"> <Grid x:Name="grid"> <ToggleButton Template="{StaticResource ComboBoxToggleButton}" x:Name="ToggleButton" Focusable="false" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" /> <ContentPresenter HorizontalAlignment="Left" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False" /> <TextBox Visibility="Hidden" Margin="2,2,22,2" x:Name="PART_EditableTextBox" Style="{x:Null}" VerticalAlignment="Center" Focusable="True" IsReadOnly="{TemplateBinding IsReadOnly}" Foreground="Black" HorizontalAlignment="Stretch" Background="Azure" /> <!--文本輸入框,當IsEditable為true 才顯示--> <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="WhiteSmoke" CornerRadius="3,3,3,3" /> <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True" Foreground="{StaticResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}"> <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" /> </ScrollViewer> </Grid> </Popup> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="HasItems" Value="false"> <Setter Property="MinHeight" Value="95" TargetName="DropDownBorder" /> </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="IsEditable" Value="true"> <Setter Property="IsTabStop" Value="false" /> <Setter Property="Visibility" Value="Visible" TargetName="PART_EditableTextBox" /> <Setter Property="Visibility" Value="Hidden" TargetName="ContentSite" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>