UWP 中 ComboBox 的 CompositeCollection 替代方案? [英] Alternative of CompositeCollection for ComboBox in UWP?

查看:22
本文介绍了UWP 中 ComboBox 的 CompositeCollection 替代方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为我的 ComboBox 设置一个默认文本,类似于请选择".对于 WPF,它可以使用 CompositeCollection 完成,如下所示,但是 CompositeCollection 在 UWP 中不可用,那么有什么替代方法吗?

I want to set a default text to my ComboBox, something like this "Please Select". For WPF it can be done using CompositeCollection as below but CompositeCollection is not available in UWP, so is there any alternative for it?

<ComboBox SelectedIndex="0">
    <ComboBox.ItemsSource>
        <CompositeCollection>
            <ListBoxItem>Please Select</ListBoxItem>
            <CollectionContainer Collection="{Binding Source={StaticResource YOURDATASOURCE}}" />
        </CompositeCollection>
    </ComboBox.ItemsSource>
</ComboBox>

推荐答案

在花了几个小时寻找解决方案后,我遇到了 this 文章通过在所选项目旁边的 ComboBox 中附加 Clear(X) 按钮,以一种很好的方式解决了这个问题.提供的解决方案是在 WPF 中,所以如果有人想要这个用于他们的 UWP 项目,请参考以下代码:

After spending a couple of hours to search for the solution, I came across this post which tackle this problem in a nice way by appending the Clear(X) button inside the ComboBox beside the selected item. The solution provided is in WPF, so if anybody want's this for their UWP project please refer to below code:

自定义组合框样式:

<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="&#xE894;"
                                    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="&#xE0E5;"
            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 行为:

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>

这篇关于UWP 中 ComboBox 的 CompositeCollection 替代方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆