带标题的WPF Multicolumn combox

时间:2018-03-28 17:42:51

标签: c# wpf xaml mvvm datatemplate

我正在尝试使用标头实现多列组合框并包含搜索功能。 通过扩展组合框控件,我能够实现包含搜索过滤。 但我无法使用标题实现多列显示。 我已经浏览了大部分谷歌搜索文章,但没有任何帮助,

下面是我的扩展组合框控件的xaml,

<wpf:FilteredComboBox DisplayMemberPath="Description"
                                        IsEditable="True"
                                        IsTextSearchEnabled="False"
                                        ItemTemplate="{StaticResource SearchGridTemplate}"
                                        ItemsSource="{Binding DataContext.MaterialsList,
                                                              RelativeSource={RelativeSource Mode=FindAncestor,
                                                                                             AncestorType={x:Type UserControl}}}"
                                        StaysOpenOnEdit="True">

                                        <wpf:FilteredComboBox.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <VirtualizingStackPanel VirtualizationMode="Recycling" />
                                            </ItemsPanelTemplate>
                                        </wpf:FilteredComboBox.ItemsPanel>
                                    </wpf:FilteredComboBox>

下面是应用于FilteredComboboxControl的ItemTemplate属性的数据模板,我需要修改此模板,以便数据显示在带有标题的列中。

<DataTemplate x:Key="SearchGridTemplate">
            <Border
                Margin="2"
                BorderBrush="Gray"
                BorderThickness="1">
                <Grid MinWidth="200">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="300" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <TextBlock
                        Grid.Row="0"
                        Grid.Column="0"
                        Margin="5"
                        FontWeight="Bold"
                        Text="Part Number" />
                    <TextBlock
                        Grid.Row="0"
                        Grid.Column="1"
                        Margin="0,5,0,0"
                        FontWeight="Bold"
                        Text=":" />
                    <TextBlock
                        Grid.Row="0"
                        Grid.Column="2"
                        Margin="5"
                        Text="{Binding PartNumber}"
                        TextTrimming="WordEllipsis"
                        ToolTip="{Binding Text,
                                          RelativeSource={RelativeSource Self}}" />
                    <Border
                        Grid.Row="1"
                        Grid.Column="0"
                        Grid.ColumnSpan="3"
                        BorderBrush="Gray"
                        BorderThickness="0.5" />
                    <TextBlock
                        Grid.Row="2"
                        Grid.Column="0"
                        Margin="5"
                        FontWeight="Bold"
                        Text="Material Name" />
                    <TextBlock
                        Grid.Row="2"
                        Grid.Column="1"
                        Margin="0,5,0,0"
                        FontWeight="Bold"
                        Text=":" />
                    <TextBlock
                        Grid.Row="2"
                        Grid.Column="2"
                        Margin="5"
                        Text="{Binding Description}"
                        TextTrimming="WordEllipsis"
                        ToolTip="{Binding Text,
                                          RelativeSource={RelativeSource Self}}" />
                </Grid>
            </Border>
        </DataTemplate>

我需要实现这样的目标, enter image description here

使用弹出模板:我可以获取标题和相应的数据。但是如果值很大,则标题不能正确合并,

<UserControl
x:Class="MultiColumnSearchComboBox.MultiColumnSearchView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MultiColumnSearchComboBox"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="ucAdvCombo"
d:DesignHeight="80"
d:DesignWidth="600"
mc:Ignorable="d">
<UserControl.Resources>
    <!--  Toggle Button Template  -->
    <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
        <Grid x:Name="gd">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>
            <Border
                x:Name="Border"
                Grid.ColumnSpan="2"
                Background="White"
                BorderBrush="LightGray"
                BorderThickness="1"
                SnapsToDevicePixels="True" />
            <Border
                x:Name="Boredr1"
                Grid.Column="0"
                Margin="1"
                Background="White"
                BorderBrush="LightGray"
                BorderThickness="0,0,1,0"
                SnapsToDevicePixels="True" />
            <Path
                x:Name="Arrow"
                Grid.Column="1"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Data="M 0 0 L 6 6 L 12 0 Z"
                Fill="Black"
                SnapsToDevicePixels="True" />
            <ContentPresenter Grid.Column="0" TextElement.Foreground="Orange" />
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="ToggleButton.IsMouseOver" Value="True">
                <Setter TargetName="Border" Property="BorderBrush" Value="Black" />
                <Setter TargetName="Boredr1" Property="BorderBrush" Value="Black" />
            </Trigger>
            <Trigger Property="ToggleButton.IsChecked" Value="True">
                <Setter TargetName="Arrow" Property="Data" Value="M 0 0 L 5 5 L 10 0" />
                <Setter TargetName="Arrow" Property="Fill" Value="White" />
                <Setter TargetName="Arrow" Property="Stroke" Value="Black" />
                <Setter TargetName="Arrow" Property="StrokeThickness" Value="1.5" />
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter TargetName="gd" Property="Visibility" Value="Visible" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    <!--  TextBox Template  -->
    <ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
        <ScrollViewer x:Name="PART_ContentHost" Focusable="False" />
    </ControlTemplate>

    <!--  Style with Scroll Bar  -->
    <Style x:Key="EditableComboBoxStyle" TargetType="ComboBox">
        <Setter Property="SnapsToDevicePixels" Value="true" />
        <Setter Property="OverridesDefaultStyle" Value="true" />
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
        <Setter Property="ScrollViewer.CanContentScroll" Value="true" />
        <Setter Property="Height" Value="40" />
        <Setter Property="MinWidth" Value="120" />
        <Setter Property="MinHeight" Value="20" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ComboBox">
                    <Grid>
                        <ToggleButton
                            Name="ToggleButton"
                            ClickMode="Press"
                            Focusable="false"
                            Foreground="Black"
                            IsChecked="{Binding Path=IsDropDownOpen,
                                                Mode=TwoWay,
                                                RelativeSource={RelativeSource TemplatedParent}}"
                            Template="{StaticResource ComboBoxToggleButton}" />
                        <ContentPresenter
                            Name="ContentSite"
                            Margin="3,3,23,3"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Center"
                            Content="{TemplateBinding SelectionBoxItem}"
                            ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                            ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                            IsHitTestVisible="False" />
                        <TextBox
                            x:Name="PART_EditableTextBox"
                            Margin="0,0,30,0"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Center"
                            CaretBrush="Black"
                            Focusable="True"
                            FontFamily="B Koodak"
                            FontSize="15"
                            Foreground="Black"
                            IsReadOnly="{TemplateBinding IsReadOnly}"
                            OverridesDefaultStyle="True"
                            SelectionBrush="Gray"
                            Style="{x:Null}"
                            Template="{StaticResource ComboBoxTextBox}"
                            TextWrapping="NoWrap"
                            Visibility="Hidden" />
                        <Popup
                            Name="Popup"
                            Grid.ColumnSpan="2"
                            AllowsTransparency="True"
                            Focusable="False"
                            IsOpen="{TemplateBinding IsDropDownOpen}"
                            Placement="Bottom"
                            PopupAnimation="Fade">
                            <Grid
                                MinWidth="{TemplateBinding ActualWidth}"
                                MaxWidth="{TemplateBinding ActualWidth}"
                                MaxHeight="{TemplateBinding MaxDropDownHeight}"
                                SnapsToDevicePixels="True">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition SharedSizeGroup="A" />
                                    <ColumnDefinition Width="5" />
                                    <ColumnDefinition SharedSizeGroup="B" />
                                </Grid.ColumnDefinitions>
                                <Grid
                                    Grid.Row="0"
                                    Grid.Column="0"
                                    Background="#C8E6E6">
                                    <TextBlock
                                        Height="30"
                                        Padding="5"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Top"
                                        FontFamily="Arial"
                                        FontSize="14"
                                        FontWeight="Bold"
                                        Foreground="Black"
                                        Text="{Binding DataContext.ColumnNames[0],
                                                       RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
                                </Grid>
                                <Border
                                    x:Name="DropDownBorder"
                                    Grid.RowSpan="2"
                                    Grid.ColumnSpan="4"
                                    MaxWidth="{TemplateBinding ActualWidth}"
                                    Background="Transparent"
                                    BorderBrush="LightGray"
                                    BorderThickness="1"
                                    SnapsToDevicePixels="True" />
                                <Grid
                                    Grid.Row="0"
                                    Grid.Column="2"
                                    Background="#C8E6E6">
                                    <TextBlock
                                        Padding="5"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Top"
                                        FontFamily="Arial"
                                        FontSize="14"
                                        FontWeight="Bold"
                                        Foreground="Black"
                                        Text="{Binding DataContext.ColumnNames[1],
                                                       RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
                                </Grid>
                                <ScrollViewer
                                    Grid.ColumnSpan="3"
                                    Margin="0,30,0,0"
                                    ScrollViewer.CanContentScroll="False"
                                    SnapsToDevicePixels="True">
                                    <StackPanel Background="Transparent" IsItemsHost="True" />
                                </ScrollViewer>
                            </Grid>
                        </Popup>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEditable" Value="true">
                            <Setter Property="IsTabStop" Value="false" />
                            <Setter TargetName="PART_EditableTextBox" Property="Background" Value="White" />
                            <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
                            <Setter TargetName="PART_EditableTextBox" Property="Foreground" Value="Black" />
                            <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden" />
                        </Trigger>
                        <Trigger Property="HasItems" Value="false">
                            <!--<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95" />-->
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="IsTabStop" Value="false" />
                            <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
                            <Setter TargetName="PART_EditableTextBox" Property="Foreground" Value="Black" />
                            <Setter TargetName="PART_EditableTextBox" Property="IsEnabled" Value="False" />
                            <Setter TargetName="PART_EditableTextBox" Property="Background" Value="White" />
                            <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden" />
                        </Trigger>
                        <Trigger Property="IsGrouping" Value="true">
                            <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
                        </Trigger>
                        <Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
                            <!--<Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0" />-->
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--  combobox item style  -->
    <Style x:Key="Column_CmbItem" TargetType="ComboBoxItem">
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="OverridesDefaultStyle" Value="True" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ComboBoxItem">
                    <Grid
                        x:Name="Border"
                        Margin="1,0,1,1"
                        Background="White">
                        <ContentPresenter />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="ComboBoxItem.IsSelected" Value="True">
                            <Setter TargetName="Border" Property="Background" Value="Gray" />
                        </Trigger>
                        <Trigger Property="ComboBoxItem.IsMouseOver" Value="True">
                            <Setter TargetName="Border" Property="Background" Value="LightBlue" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<Grid>
    <ComboBox
        x:Name="Combobox"
        Width="550"
        Height="25"
        HorizontalAlignment="Left"
        local:ComboBoxItemsSourceDecorator.ItemsSource="{Binding Path=ItemsCollectionView,
                                                                 ValidatesOnDataErrors=True,
                                                                 UpdateSourceTrigger=PropertyChanged,
                                                                 Mode=OneWay}"
        IsEditable="True"
        IsTextSearchCaseSensitive="False"
        IsTextSearchEnabled="True"
        ItemContainerStyle="{StaticResource Column_CmbItem}"
        SelectedValue="{Binding SelectedItem}"
        StaysOpenOnEdit="True"
        Style="{StaticResource EditableComboBoxStyle}"
        Text="{Binding FilterCriteria}"
        TextSearch.TextPath="FirstColumn">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <Grid
                    x:Name="multiColumnComboBox"
                    Background="Transparent"
                    SnapsToDevicePixels="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="A" />
                        <ColumnDefinition Width="20" />
                        <ColumnDefinition SharedSizeGroup="B" />
                    </Grid.ColumnDefinitions>
                    <TextBlock
                        Grid.Column="0"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Center"
                        FontSize="14"
                        Foreground="Black"
                        Text="{Binding FirstColumn}"
                        TextTrimming="CharacterEllipsis" />
                    <TextBlock
                        Grid.Column="2"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Center"
                        FontSize="14"
                        Foreground="Black"
                        Text="{Binding SecondColumn}" />
                </Grid>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</Grid>

上面的用户控制结果如下所示,这里我们可以看到第一行第二列数据正在向第1列移动。 enter image description here

下面是我在Combobox中有DataGrid示例项目的链接,但是我无法在视图中显示组合框, Extended Datagrid Inside Combobox

1 个答案:

答案 0 :(得分:0)

如果我关注你的问题。 当您下拉您的combox时,您希望看到类似listview的内容。

如果您查看组合框模板,您感兴趣的位如下:

      <Popup 
        Name="Popup"
        Placement="Bottom"
        IsOpen="{TemplateBinding IsDropDownOpen}"
        AllowsTransparency="True" 
        Focusable="False"
        PopupAnimation="Slide">
        <Grid 
          Name="DropDown"
          SnapsToDevicePixels="True"                
          MinWidth="{TemplateBinding ActualWidth}"
          MaxHeight="{TemplateBinding MaxDropDownHeight}">
          <Border 
            x:Name="DropDownBorder"
            Background="{StaticResource WindowBackgroundBrush}"
            BorderThickness="1"
            BorderBrush="{StaticResource SolidBorderBrush}"/>
          <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
            <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
          </ScrollViewer>
        </Grid>
      </Popup>

当您单击组合键将其删除时,会出现弹出窗口。 请注意,具有IsItemsHost = true的stackpanel。 这将托管您的项目,您可以使用该数据模板进行模板化。 你还需要它们之上的标题。 使用网格并将其放在该滚动查看器上方的模板中。您还需要在现有网格上使用rowdefinitions,以便获得一些空间。 在这些列中定义列并将标题或边框标记在其中。 您将遇到的下一个问题是让列排成一行。 您可以使用共享大小范围来实现。如下所述: https://wpf.2000things.com/tag/sharedsizegroup/

弹出窗口不在与组合相同的datacontext中,因此您还需要一些方法来设置标题。假设你真的想绑定它们。最简单的方法是使用placementtarget设置其网格的datacontext。 大致

DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=PopUp}"

(那一位是航空代码。)

这是一个快速而又脏的实现,仍需要一些工作: https://1drv.ms/u/s!AmPvL3r385QhgpgPutGprfx5CBUFBw

项目是缩进的,所以仍然需要做一些工作才能将它们向左移动而你可能希望列之间有一点间隙。