Combobox show and hide ComboBox items in WPF

試著忘記壹切 提交于 2019-12-13 09:08:28

问题


ComboBox might have a lot of items.

This is the scenario i would like to achieve:

I have to create a custom ComboBox which has a "More" button which located at the last of the ComboBox items. If the ComboBox contain of 20 items, initially, when the ComboBox is clicked and the drop down list is shown, there are only 10 items and a "More" button under the 10th items are displayed.

Whenever the "More" button items is clicked, the "More" button will turn into "Less" and the drop down list will display total of 20 items. So when "Less" button is clicked, the display items will be reversed back to 10 items and the another 10 items will be hidden.

The 10 initial display items is just an example. Actually, The total of the ComboBox's initial display item can be set through the property.

For example: <local:CustomComboBox x:Name="CustomComboBox" InitialDisplayItem="10" />

I am new to wpf...How can i achieve that?


回答1:


Create a custom control such as:

public class CrazyCombo : ComboBox
{
    static CrazyCombo()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CrazyCombo), new FrameworkPropertyMetadata(typeof(CrazyCombo)));
    }

    public int InitialDisplayItem
    {
        get { return (int)GetValue(InitialDisplayItemProperty); }
        set { SetValue(InitialDisplayItemProperty, value); }
    }

    // Using a DependencyProperty as the backing store for InitialDisplayItem.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty InitialDisplayItemProperty =
        DependencyProperty.Register("InitialDisplayItem", typeof(int), typeof(CrazyCombo), new UIPropertyMetadata(0));

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var moreLessButton = Template.FindName("moreLessButton", this) as Button;

        moreLessButton.Click += new RoutedEventHandler(moreLessButton_Click);
    }

    void moreLessButton_Click(object sender, RoutedEventArgs e)
    {
        var moreLessButton = Template.FindName("moreLessButton", this) as Button;

        if (moreLessButton.Content.ToString() == "More")
        {
            var icv = CollectionViewSource.GetDefaultView(Items);

            icv.Filter = null;
            moreLessButton.Content = "Less";
        }
        else
        {
            var icv = CollectionViewSource.GetDefaultView(Items);

            icv.Filter += o => Items.OfType<object>().Take(InitialDisplayItem).Contains(o);

            moreLessButton.Content = "More";
        }
    }

    protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
    {
        base.OnItemsSourceChanged(oldValue, newValue);

        var icv = CollectionViewSource.GetDefaultView(Items);

        icv.Filter += o => Items.OfType<object>().Take(InitialDisplayItem).Contains(o);
    }

}

In the generic.xaml you will need to put in the entire style for a standard combo box, you can use blend to get it. I won't post it because it is huuuuuggge. You will need to change the following sections:

Change the style to point at you custom control i.e.

 <Style TargetType="{x:Type local:CrazyCombo}">

In the combo box popup add the more/less button

<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
                        <Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
                            <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
                                <StackPanel>
                                    <ScrollViewer x:Name="DropDownScrollViewer">
                                        <Grid RenderOptions.ClearTypeHint="Enabled">
                                            <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                                <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
                                            </Canvas>
                                            <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                        </Grid>
                                    </ScrollViewer>
                                    <Button Name="moreLessButton" Content="More"/>
                                </StackPanel>
                            </Border>
                        </Microsoft_Windows_Themes:SystemDropShadowChrome>
                    </Popup>

The only addition to the standard combo box control template was the line

<Button Name="moreLessButton" Content="More"/>

You then use the custom control like

<Window x:Class="WpfApplication4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication4"
    Title="MainWindow" Height="350" Width="525" Foreground="red">

<StackPanel>

    <local:CrazyCombo x:Name="bah" ItemsSource="{Binding Foo}" InitialDisplayItem="1"/>

</StackPanel>

If you were to do this for real you would add some triggers to the button so it only displayed if there were more items then the "InitialDisplayItem". You would probably also make the button a toggle button instead of my silly switch code.



来源:https://stackoverflow.com/questions/11680660/combobox-show-and-hide-combobox-items-in-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!