UWP 中 ComboBox 的 CompositeCollection 的替代方案?
Alternative of CompositeCollection for ComboBox in UWP?
我想为我的 ComboBox
设置默认文本,例如 "Please Select"。对于 WPF,可以使用 CompositeCollection
来完成,如下所示,但是 CompositeCollection
在 UWP 中不可用,那么有什么替代方法吗?
<ComboBox SelectedIndex="0">
<ComboBox.ItemsSource>
<CompositeCollection>
<ListBoxItem>Please Select</ListBoxItem>
<CollectionContainer Collection="{Binding Source={StaticResource YOURDATASOURCE}}" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
I want to set a default text to my ComboBox, something like this "Please Select".
ComboBox 有 PlaceholderText
属性 用于显示在控件中,直到值被用户操作或其他一些操作更改。
<ComboBox PlaceholderText="Please Select" Width="200">
<x:String>Blue<x:String>
<x:String>Green<x:String>
<x:String>Red<x:String>
<x:String>Yellow<x:String>
</ComboBox>
更新
如果你需要一个项目成为默认选项,你可以使用SelectedItem or SelectIndex来实现。
在花了几个小时搜索解决方案后,我遇到了 this post,它通过在 ComboBox
在所选项目旁边。提供的解决方案是在 WPF 中,所以如果有人想要这个用于他们的 UWP 项目,请参考下面的代码:
自定义组合框样式:
<Style TargetType="ComboBox" x:Key="ComboBoxWithClearButtonStyle">
<Setter Property="Padding" Value="12,5,0,7" />
<Setter Property="MinWidth" Value="{ThemeResource ComboBoxThemeMinWidth}" />
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundAltMediumLowBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumLowBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ComboBoxBorderThemeThickness}" />
<Setter Property="TabNavigation" Value="Once" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<CarouselPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlPageBackgroundAltMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundListMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextBlock"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DropDownGlyph"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextBlock"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DropDownGlyph"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FocusedPressed" >
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextBlock"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DropDownGlyph"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
<VisualState x:Name="FocusedDropDown">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="PopupBorder"
Storyboard.TargetProperty="Visibility"
Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DropDownStates">
<VisualState x:Name="Opened">
<Storyboard>
<SplitOpenThemeAnimation
OpenedTargetName="PopupBorder"
ClosedTargetName="ContentPresenter"
OffsetFromCenter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOffset}"
OpenedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOpenedHeight}"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Closed">
<Storyboard>
<SplitCloseThemeAnimation
OpenedTargetName="PopupBorder"
ClosedTargetName="ContentPresenter"
OffsetFromCenter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOffset}"
OpenedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOpenedHeight}"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
x:DeferLoadStrategy="Lazy"
Margin="{ThemeResource ComboBoxHeaderThemeMargin}"
FlowDirection="{TemplateBinding FlowDirection}"
FontWeight="{ThemeResource ComboBoxHeaderThemeFontWeight}"
Visibility="Collapsed"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}" />
<Border x:Name="Background"
Grid.Row="1"
Grid.ColumnSpan="2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<Border x:Name="HighlightBackground"
Grid.Row="1"
Grid.ColumnSpan="2"
Background="{ThemeResource SystemControlHighlightListAccentLowBrush}"
BorderBrush="{ThemeResource SystemControlHighlightBaseMediumLowBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Opacity="0" />
<ContentPresenter x:Name="ContentPresenter"
Grid.Row="1"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextBlock x:Name="PlaceholderTextBlock"
Text="{TemplateBinding PlaceholderText}"
Foreground="{ThemeResource SystemControlPageTextBaseHighBrush}"/>
</ContentPresenter>
<Grid Grid.Row="1"
Grid.Column="1"
Margin="0,10,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button x:Name="ClearButton"
Foreground="Black"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="12"
Content=""
VerticalAlignment="Center"
BorderThickness="0"
Background="Transparent"
Height="20"
Width="30"
Padding="5,0"
Style="{StaticResource NoHoverButtonStyle}"
AutomationProperties.AccessibilityView="Raw" />
<FontIcon x:Name="DropDownGlyph"
Grid.Column="1"
IsHitTestVisible="False"
Foreground="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="12"
Glyph=""
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
<Popup x:Name="Popup">
<Border
x:Name="PopupBorder"
Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="{ThemeResource ComboBoxDropdownBorderThickness}"
Margin="0,-1,0,-1"
HorizontalAlignment="Stretch">
<ScrollViewer x:Name="ScrollViewer"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
MinWidth="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownContentMinWidth}"
VerticalSnapPointsType="OptionalSingle"
VerticalSnapPointsAlignment="Near"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
ZoomMode="Disabled"
AutomationProperties.AccessibilityView="Raw">
<ItemsPresenter Margin="{ThemeResource ComboBoxDropdownContentMargin}" />
</ScrollViewer>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML ComboBox 的行为:
public sealed class ComboBoxBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; set; }
public bool IsNullable
{
get => (bool)this.GetValue(IsNullableProperty);
set => this.SetValue(IsNullableProperty, value);
}
public static readonly DependencyProperty IsNullableProperty = DependencyProperty.Register(
"IsNullable",
typeof(bool),
typeof(ComboBoxBehavior),
new PropertyMetadata(false, null));
public void Attach(DependencyObject associatedObject)
{
if (!(associatedObject is ComboBox cb))
{
throw new ArgumentException("ComboBoxBehavior can only be used with a ComboBox.");
}
this.AssociatedObject = associatedObject;
if (IsNullable)
{
cb.Loaded += OnComboBoxLoaded;
cb.SelectionChanged += OnSelectionChanged;
}
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
ApplyIsNullable(sender as ComboBox);
}
private void OnComboBoxLoaded(object sender, RoutedEventArgs e)
{
ApplyIsNullable(sender as ComboBox);
}
private void ApplyIsNullable(ComboBox comboBox)
{
comboBox.ApplyTemplate();
var clearButton = GetClearButton(comboBox);
if (clearButton != null)
{
clearButton.Click -= OnClearButtonClicked;
clearButton.Click += OnClearButtonClicked;
if (IsNullable && comboBox.SelectedIndex != -1)
{
clearButton.Visibility = Visibility.Visible;
}
else
{
clearButton.Visibility = Visibility.Collapsed;
}
}
}
private void OnClearButtonClicked(object sender, RoutedEventArgs e)
{
(this.AssociatedObject as ComboBox).SelectedIndex = -1;
}
private Button GetClearButton(DependencyObject reference)
{
for (int childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(reference); childIndex++)
{
var child = VisualTreeHelper.GetChild(reference, childIndex);
if (child is Button && ((Button)child).Name == "ClearButton")
{
return (Button)child;
}
var clearButton = GetClearButton(child);
if (clearButton is Button)
{
return clearButton;
}
}
return null;
}
public void Detach()
{
ComboBox comboBox = null;
if (this.AssociatedObject is ComboBox)
{
comboBox = this.AssociatedObject as ComboBox;
comboBox.Loaded -= OnComboBoxLoaded;
comboBox.SelectionChanged -= OnSelectionChanged;
}
this.AssociatedObject = null;
}
}
ComobBox的使用方法:
<ComboBox ItemsSource="{Binding Source={StaticResource ViewModel}, Path=Actors}"
Height="25" Width="300"
HorizontalAlignment="Left" VerticalAlignment="Top"
Style="{StaticResource ComboBoxWithClearButtonStyle}">
<interactivity:Interaction.Behaviors>
<behaviors:ComboBoxBehavior IsNullable="True"/>
</interactivity:Interaction.Behaviors>
</ComboBox>
我想为我的 ComboBox
设置默认文本,例如 "Please Select"。对于 WPF,可以使用 CompositeCollection
来完成,如下所示,但是 CompositeCollection
在 UWP 中不可用,那么有什么替代方法吗?
<ComboBox SelectedIndex="0">
<ComboBox.ItemsSource>
<CompositeCollection>
<ListBoxItem>Please Select</ListBoxItem>
<CollectionContainer Collection="{Binding Source={StaticResource YOURDATASOURCE}}" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
I want to set a default text to my ComboBox, something like this "Please Select".
ComboBox 有 PlaceholderText
属性 用于显示在控件中,直到值被用户操作或其他一些操作更改。
<ComboBox PlaceholderText="Please Select" Width="200">
<x:String>Blue<x:String>
<x:String>Green<x:String>
<x:String>Red<x:String>
<x:String>Yellow<x:String>
</ComboBox>
更新
如果你需要一个项目成为默认选项,你可以使用SelectedItem or SelectIndex来实现。
在花了几个小时搜索解决方案后,我遇到了 this post,它通过在 ComboBox
在所选项目旁边。提供的解决方案是在 WPF 中,所以如果有人想要这个用于他们的 UWP 项目,请参考下面的代码:
自定义组合框样式:
<Style TargetType="ComboBox" x:Key="ComboBoxWithClearButtonStyle">
<Setter Property="Padding" Value="12,5,0,7" />
<Setter Property="MinWidth" Value="{ThemeResource ComboBoxThemeMinWidth}" />
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundAltMediumLowBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumLowBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ComboBoxBorderThemeThickness}" />
<Setter Property="TabNavigation" Value="Once" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<CarouselPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlPageBackgroundAltMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundListMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextBlock"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DropDownGlyph"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextBlock"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DropDownGlyph"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FocusedPressed" >
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextBlock"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DropDownGlyph"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseMediumHighBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
<VisualState x:Name="FocusedDropDown">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="PopupBorder"
Storyboard.TargetProperty="Visibility"
Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DropDownStates">
<VisualState x:Name="Opened">
<Storyboard>
<SplitOpenThemeAnimation
OpenedTargetName="PopupBorder"
ClosedTargetName="ContentPresenter"
OffsetFromCenter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOffset}"
OpenedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOpenedHeight}"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Closed">
<Storyboard>
<SplitCloseThemeAnimation
OpenedTargetName="PopupBorder"
ClosedTargetName="ContentPresenter"
OffsetFromCenter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOffset}"
OpenedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOpenedHeight}"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
x:DeferLoadStrategy="Lazy"
Margin="{ThemeResource ComboBoxHeaderThemeMargin}"
FlowDirection="{TemplateBinding FlowDirection}"
FontWeight="{ThemeResource ComboBoxHeaderThemeFontWeight}"
Visibility="Collapsed"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}" />
<Border x:Name="Background"
Grid.Row="1"
Grid.ColumnSpan="2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<Border x:Name="HighlightBackground"
Grid.Row="1"
Grid.ColumnSpan="2"
Background="{ThemeResource SystemControlHighlightListAccentLowBrush}"
BorderBrush="{ThemeResource SystemControlHighlightBaseMediumLowBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Opacity="0" />
<ContentPresenter x:Name="ContentPresenter"
Grid.Row="1"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextBlock x:Name="PlaceholderTextBlock"
Text="{TemplateBinding PlaceholderText}"
Foreground="{ThemeResource SystemControlPageTextBaseHighBrush}"/>
</ContentPresenter>
<Grid Grid.Row="1"
Grid.Column="1"
Margin="0,10,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button x:Name="ClearButton"
Foreground="Black"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="12"
Content=""
VerticalAlignment="Center"
BorderThickness="0"
Background="Transparent"
Height="20"
Width="30"
Padding="5,0"
Style="{StaticResource NoHoverButtonStyle}"
AutomationProperties.AccessibilityView="Raw" />
<FontIcon x:Name="DropDownGlyph"
Grid.Column="1"
IsHitTestVisible="False"
Foreground="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="12"
Glyph=""
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
<Popup x:Name="Popup">
<Border
x:Name="PopupBorder"
Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}"
BorderBrush="{ThemeResource SystemControlForegroundChromeHighBrush}"
BorderThickness="{ThemeResource ComboBoxDropdownBorderThickness}"
Margin="0,-1,0,-1"
HorizontalAlignment="Stretch">
<ScrollViewer x:Name="ScrollViewer"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
MinWidth="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownContentMinWidth}"
VerticalSnapPointsType="OptionalSingle"
VerticalSnapPointsAlignment="Near"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
ZoomMode="Disabled"
AutomationProperties.AccessibilityView="Raw">
<ItemsPresenter Margin="{ThemeResource ComboBoxDropdownContentMargin}" />
</ScrollViewer>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML ComboBox 的行为:
public sealed class ComboBoxBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; set; }
public bool IsNullable
{
get => (bool)this.GetValue(IsNullableProperty);
set => this.SetValue(IsNullableProperty, value);
}
public static readonly DependencyProperty IsNullableProperty = DependencyProperty.Register(
"IsNullable",
typeof(bool),
typeof(ComboBoxBehavior),
new PropertyMetadata(false, null));
public void Attach(DependencyObject associatedObject)
{
if (!(associatedObject is ComboBox cb))
{
throw new ArgumentException("ComboBoxBehavior can only be used with a ComboBox.");
}
this.AssociatedObject = associatedObject;
if (IsNullable)
{
cb.Loaded += OnComboBoxLoaded;
cb.SelectionChanged += OnSelectionChanged;
}
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
ApplyIsNullable(sender as ComboBox);
}
private void OnComboBoxLoaded(object sender, RoutedEventArgs e)
{
ApplyIsNullable(sender as ComboBox);
}
private void ApplyIsNullable(ComboBox comboBox)
{
comboBox.ApplyTemplate();
var clearButton = GetClearButton(comboBox);
if (clearButton != null)
{
clearButton.Click -= OnClearButtonClicked;
clearButton.Click += OnClearButtonClicked;
if (IsNullable && comboBox.SelectedIndex != -1)
{
clearButton.Visibility = Visibility.Visible;
}
else
{
clearButton.Visibility = Visibility.Collapsed;
}
}
}
private void OnClearButtonClicked(object sender, RoutedEventArgs e)
{
(this.AssociatedObject as ComboBox).SelectedIndex = -1;
}
private Button GetClearButton(DependencyObject reference)
{
for (int childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(reference); childIndex++)
{
var child = VisualTreeHelper.GetChild(reference, childIndex);
if (child is Button && ((Button)child).Name == "ClearButton")
{
return (Button)child;
}
var clearButton = GetClearButton(child);
if (clearButton is Button)
{
return clearButton;
}
}
return null;
}
public void Detach()
{
ComboBox comboBox = null;
if (this.AssociatedObject is ComboBox)
{
comboBox = this.AssociatedObject as ComboBox;
comboBox.Loaded -= OnComboBoxLoaded;
comboBox.SelectionChanged -= OnSelectionChanged;
}
this.AssociatedObject = null;
}
}
ComobBox的使用方法:
<ComboBox ItemsSource="{Binding Source={StaticResource ViewModel}, Path=Actors}"
Height="25" Width="300"
HorizontalAlignment="Left" VerticalAlignment="Top"
Style="{StaticResource ComboBoxWithClearButtonStyle}">
<interactivity:Interaction.Behaviors>
<behaviors:ComboBoxBehavior IsNullable="True"/>
</interactivity:Interaction.Behaviors>
</ComboBox>