【问题标题】:DataGridComboBoxColumn with a dropdown arrow带有下拉箭头的 DataGridComboBoxColumn
【发布时间】:2018-08-26 05:06:30
【问题描述】:

我希望在 DatagridComboboxColumn 中显示一个小向下箭头,表示这是一个下拉列表,如下图所示。

为了实现上述目的,我修改了 ComboBoxToggleButton,将 Path 更改为:

<Path x:Name="Arrow" Grid.Column="1" VerticalAlignment="Center" Data="M 0 0 L 6 6 L 12 0 Z">
    <Path.Fill>
        <SolidColorBrush Color="Gray" />
    </Path.Fill>
  </Path>

在 ComboBox 样式的弹出窗口中,我将其保留为默认设置,即:

<Popup x:Name="Popup" AllowsTransparency="True" Focusable="False" IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" PopupAnimation="Slide">
   .....                                               
    <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
         <StackPanel HorizontalAlignment="Left" IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
    </ScrollViewer>
   .....
</Popup>

我已将样式命名为 "ExpenseDescription"

最后将样式作为 ElementStyle 附加到 DatagridComboBoxColumn 上,如下所示:

<DataGridComboBoxColum  ElementStyle="{StaticResource ExpenseDescription}
.......

这很好用。

但是我试图通过将默认 StackPanel 替换为 Datagrid 来修改 ComboBox Popup(下拉列表),以便下拉列表具有如下多列(尽管在此示例中我只显示了 1 列):

 <Popup x:Name="Popup" AllowsTransparency="True" Focusable="False" IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" PopupAnimation="Slide">
 .....                                               
    <DataGrid AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{TemplateBinding ItemsSource}"  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
       <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Description}" Header="Account Description"/>
        </DataGrid.Columns>
    </DataGrid>
   .....
</Popup>

这仅在我将样式附加到 EditingElementStyle(而不是 ElementStyle)并且如上所述的箭头效果消失时才有效。

当我附加到 ElementStyle 时,我得到了箭头效果,但所有行现在都绑定到同一个下拉选定项,如下所示:

我尝试通过插入来修改样式

<Setter Property="IsSynchronizedWithCurrentItem" Value="False" />

效果是 SelectionChanged 事件不会触发。

在有人将我引导到另一个可能有效的示例之前,请帮助我修改它。

这里是 XAML

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow"
        Width="300"
        Height="400">
    <Window.Resources>
        <local:DataSet1 x:Key="DataSet1" />
        <CollectionViewSource x:Key="ExpenseDetailsViewSource" Source="{Binding ExpenseDetails, Source={StaticResource DataSet1}}" />
        <CollectionViewSource x:Key="ExpenseDescriptionsViewSource" Source="{Binding ExpenseDescriptions, Source={StaticResource DataSet1}}" />
        <Style x:Key="Description" TargetType="{x:Type 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="Foreground" Value="Black" />
            <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ComboBox}">
                        <Grid>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="MouseOver" />
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetName="PART_EditableTextBox" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
                                                <EasingColorKeyFrame KeyTime="0" Value="{DynamicResource DisabledForegroundColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                                <VisualStateGroup x:Name="EditStates">
                                    <VisualState x:Name="Editable">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_EditableTextBox" Storyboard.TargetProperty="(UIElement.Visibility)">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentSite" Storyboard.TargetProperty="(UIElement.Visibility)">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}" />
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Uneditable" />
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ToggleButton x:Name="ToggleButton"
                                          Grid.Column="2"
                                          ClickMode="Press"
                                          Focusable="false"
                                          IsChecked="{Binding IsDropDownOpen,
                                                              Mode=TwoWay,
                                                              RelativeSource={RelativeSource TemplatedParent}}"
                                          Template="{DynamicResource ComboBoxToggleButton}" />
                            <ContentPresenter x: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="3,3,23,3"
                                     HorizontalAlignment="Left"
                                     VerticalAlignment="Bottom"
                                     Background="Transparent"
                                     Focusable="True"
                                     IsReadOnly="{TemplateBinding IsReadOnly}"
                                     Style="{x:Null}"
                                     TextAlignment="Left"
                                     Visibility="Hidden" />
                            <Popup x:Name="Popup"
                                   AllowsTransparency="True"
                                   Focusable="False"
                                   IsOpen="{TemplateBinding IsDropDownOpen}"
                                   Placement="Bottom"
                                   PopupAnimation="Slide">
                                <Grid x:Name="DropDown"
                                      MaxHeight="{TemplateBinding MaxDropDownHeight}"
                                      SnapsToDevicePixels="True">
                                    <Border x:Name="DropDownBorder" BorderThickness="0">

                                        <Border.BorderBrush>
                                            <SolidColorBrush Color="{DynamicResource ControlBackgroundColor}" />
                                        </Border.BorderBrush>
                                    </Border>
                                    <DataGrid AutoGenerateColumns="False"
                                              Background="Beige"
                                              CanUserAddRows="False"
                                              CanUserDeleteRows="False"
                                              ItemsSource="{TemplateBinding ItemsSource}"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
                                        <DataGrid.Columns>
                                            <DataGridTextColumn MinWidth="150"
                                                                Binding="{Binding Description}"
                                                                Header="Account Description" />
                                        </DataGrid.Columns>
                                    </DataGrid>
                                </Grid>
                            </Popup>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="HasItems" Value="false">
                                <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95" />
                            </Trigger>
                            <Trigger Property="IsGrouping" Value="true">
                                <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
                            </Trigger>
                            <Trigger SourceName="Popup" Property="AllowsTransparency" Value="true">
                                <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="0" />
                                <Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0" />
                                <!--  <Setter TargetName="DropDownBorder" Property="CornerRadius"  Value="4" />  -->
                            </Trigger>
                            <Trigger SourceName="ToggleButton" Property="IsMouseOver" Value="true">
                                <Setter TargetName="ContentSite" Property="TextElement.Foreground" Value="Yellow" />
                                <Setter Property="Background" Value="{DynamicResource TabItemHotBackground}" />
                                <Setter Property="FontWeight" Value="Bold" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <EventSetter Event="SelectionChanged" Handler="SomeSelectionChanged" />
        </Style>
    </Window.Resources>
    <Grid x:Name="MainGrid" DataContext="{StaticResource ExpenseDetailsViewSource}">

        <DataGrid x:Name="ExpenseDetailsDataGrid"
                  AutoGenerateColumns="False"
                  EnableRowVirtualization="True"
                  ItemsSource="{Binding}"
                  RowDetailsVisibilityMode="VisibleWhenSelected">
            <DataGrid.Columns>
                <DataGridComboBoxColumn x:Name="MyDataGridComboBoxColumn"
                                        Width="*"
                                        DisplayMemberPath="Description"
                                        ElementStyle="{StaticResource Description}"
                                        Header="Expense Description"
                                        ItemsSource="{Binding Source={StaticResource ExpenseDescriptionsViewSource}}"
                                        SelectedValueBinding="{Binding Path=ExpenseDescription,
                                                                       FallbackValue=1,
                                                                       UpdateSourceTrigger=PropertyChanged}"
                                        SelectedValuePath="ControlNumber" />
            </DataGrid.Columns>

        </DataGrid>

    </Grid>
</Window>

这是后面的 VB 代码。 SomeSelectionChanged Sub 只是强制关闭下拉列表。

Imports System.Data
Imports System.IO
Imports System.IO.Packaging
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.Win32
Imports System.Data.OleDb
Imports System
Imports System.Windows
Imports System.Reflection
Imports System.Management
Imports System.ComponentModel
Imports System.Data.SqlClient
Imports System.Windows.Controls.Primitives


Imports System.Text

Imports System.Collections.Generic
Imports System.Linq



Class MainWindow

    Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Handles MyBase.Loaded

        Dim DataSet1 As WpfApplication1.DataSet1 = CType(Me.FindResource("DataSet1"), WpfApplication1.DataSet1)

        Dim dsNewRow As DataRow

        dsNewRow = DataSet1.Tables("ExpenseDescriptions").NewRow
        dsNewRow.Item("ControlNumber") = 1
        dsNewRow.Item("Description") = "Accounting Fees"
        DataSet1.Tables("ExpenseDescriptions").Rows.Add(dsNewRow)


        dsNewRow = DataSet1.Tables("ExpenseDescriptions").NewRow
        dsNewRow.Item("ControlNumber") = 2
        dsNewRow.Item("Description") = "Telephone"
        DataSet1.Tables("ExpenseDescriptions").Rows.Add(dsNewRow)

        dsNewRow = DataSet1.Tables("ExpenseDescriptions").NewRow
        dsNewRow.Item("ControlNumber") = 3
        dsNewRow.Item("Description") = "Insurance"
        DataSet1.Tables("ExpenseDescriptions").Rows.Add(dsNewRow)

        dsNewRow = DataSet1.Tables("ExpenseDescriptions").NewRow
        dsNewRow.Item("ControlNumber") = 4
        dsNewRow.Item("Description") = "Travel and Entertainment"
        DataSet1.Tables("ExpenseDescriptions").Rows.Add(dsNewRow)

        dsNewRow = DataSet1.Tables("ExpenseDescriptions").NewRow
        dsNewRow.Item("ControlNumber") = 5
        dsNewRow.Item("Description") = "Water and Lights"
        DataSet1.Tables("ExpenseDescriptions").Rows.Add(dsNewRow)


        dsNewRow = DataSet1.Tables("ExpenseDetails").NewRow
        dsNewRow.Item("ExpenseDescription") = 1
        DataSet1.Tables("ExpenseDetails").Rows.Add(dsNewRow)


        dsNewRow = DataSet1.Tables("ExpenseDetails").NewRow
        dsNewRow.Item("ExpenseDescription") = 2
        DataSet1.Tables("ExpenseDetails").Rows.Add(dsNewRow)

        dsNewRow = DataSet1.Tables("ExpenseDetails").NewRow
        dsNewRow.Item("ExpenseDescription") = 2
        DataSet1.Tables("ExpenseDetails").Rows.Add(dsNewRow)

        dsNewRow = DataSet1.Tables("ExpenseDetails").NewRow
        dsNewRow.Item("ExpenseDescription") = 3
        DataSet1.Tables("ExpenseDetails").Rows.Add(dsNewRow)

        dsNewRow = DataSet1.Tables("ExpenseDetails").NewRow
        dsNewRow.Item("ExpenseDescription") = 5
        DataSet1.Tables("ExpenseDetails").Rows.Add(dsNewRow)



    End Sub

    Private Sub SomeSelectionChanged(ByVal sender As Object, ByVal e As SelectionChangedEventArgs)

        Dim mycomboBox = CType(sender, ComboBox)
        mycomboBox.IsDropDownOpen = False

    End Sub


End Class

我明白你做了什么。我想使用 DataGrid/ListView 的原因是因为我想对数据进行排序和过滤。使用 TextBlocks/TextBoxes 我将无法对下拉列表进行排序和调整。 这是后面的 C# 代码,以备不时之需。问题是当我将样式放在 EditElementStyle 上时,它工作得很好。问题是当我尝试将样式设置为 ElementStyle 时。试试看,你就会明白我的意思

using System;
using System.Data;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;


using System.Reflection;
using System.Management;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Windows.Controls.Primitives;



namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

            WpfApplication1.DataSet1 dataSet1 = ((WpfApplication1.DataSet1)(this.FindResource("dataSet1")));

            DataRow dsNewRow = dataSet1.Tables["ExpenseDescriptions"].NewRow();
            dsNewRow["ControlNumber"] = 1;
            dsNewRow["Description"] = "Accounting Fees";
            dataSet1.Tables["ExpenseDescriptions"].Rows.Add(dsNewRow);

            dsNewRow = dataSet1.Tables["ExpenseDescriptions"].NewRow();
            dsNewRow["ControlNumber"] = 2;
            dsNewRow["Description"] = "Telephone";
            dataSet1.Tables["ExpenseDescriptions"].Rows.Add(dsNewRow);

            dsNewRow = dataSet1.Tables["ExpenseDescriptions"].NewRow();
            dsNewRow["ControlNumber"] = 3;
            dsNewRow["Description"] = "Insurance";
            dataSet1.Tables["ExpenseDescriptions"].Rows.Add(dsNewRow);

            dsNewRow = dataSet1.Tables["ExpenseDescriptions"].NewRow();
            dsNewRow["ControlNumber"] = 4;
            dsNewRow["Description"] = "Travel and Entertainment";
            dataSet1.Tables["ExpenseDescriptions"].Rows.Add(dsNewRow);

            dsNewRow = dataSet1.Tables["ExpenseDescriptions"].NewRow();
            dsNewRow["ControlNumber"] = 5;
            dsNewRow["Description"] = "Water and Lights";
            dataSet1.Tables["ExpenseDescriptions"].Rows.Add(dsNewRow);

            //================================

            dsNewRow = dataSet1.Tables["ExpenseDetails"].NewRow();
            dsNewRow["ExpenseDescription"] = 1;
            dataSet1.Tables["ExpenseDetails"].Rows.Add(dsNewRow);

            dsNewRow = dataSet1.Tables["ExpenseDetails"].NewRow();
            dsNewRow["ExpenseDescription"] = 2;
            dataSet1.Tables["ExpenseDetails"].Rows.Add(dsNewRow);

            dsNewRow = dataSet1.Tables["ExpenseDetails"].NewRow();
            dsNewRow["ExpenseDescription"] = 3;
            dataSet1.Tables["ExpenseDetails"].Rows.Add(dsNewRow);

            dsNewRow = dataSet1.Tables["ExpenseDetails"].NewRow();
            dsNewRow["ExpenseDescription"] = 4;
            dataSet1.Tables["ExpenseDetails"].Rows.Add(dsNewRow);

            dsNewRow = dataSet1.Tables["ExpenseDetails"].NewRow();
            dsNewRow["ExpenseDescription"] = 5;
            dataSet1.Tables["ExpenseDetails"].Rows.Add(dsNewRow);



        }

        private void SomeSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox mycomboBox = (ComboBox)sender;
            mycomboBox.IsDropDownOpen = false;

        }
    }
}

【问题讨论】:

  • 你的虚拟机是什么,值来自哪里?我在您的代码中看不到任何地方SelectionChanged。如果我在 ControlTemplate 中使用 ElementStyle + ComboBox 对我来说一切正常,也可以调用 SelectionChanged
  • Rekshino,我刚刚在原始问题中添加了 XAML 和代码。我有一个硬编码的 DataSet1。
  • Hmm.. 我用 c# 做的 ;) 实际上我不明白你为什么尝试在 Style 的 PopUp 中使用 DataGrid?您可以调整 ComboBoxItem 的默认样式以使 DropDown 多列
  • Hie Rekshino,我在原始帖子中提供了 C# 代码。按照您的方式进行操作将起作用,但我将无法对 DataGrid 或 ListView 进行排序和过滤。我希望用户能够过滤 DropDown 列表以避免向下滚动长 DropDown 列表。使用提供的 XAML 和 C# 代码自己尝试一下,您就会明白我的意思。
  • 复制粘贴 - 不起作用:(

标签: wpf


【解决方案1】:

你写:

这很好用。

那么,请不要碰任何东西,接受将ExpenseDescription 设置为ItemTemplate 的二传手。因此,您将在 ComboBox 中获得多行视图。

<Setter Property="ItemTemplate" >
    <Setter.Value>
        <DataTemplate>
            <Grid >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70"/>
                    <ColumnDefinition Width="70"/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding ControlNumber}" Grid.Column="0"/>
                <TextBlock Text="{Binding Description}" Grid.Column="1"/>
            </Grid>
        </DataTemplate>
    </Setter.Value>
</Setter>

【讨论】:

  • 这对我不起作用,因为我希望能够进行排序和过滤。这就是我需要使用 DataGrid 或 ListView 的原因。
猜你喜欢
  • 2015-07-11
  • 2015-02-10
  • 2021-06-19
  • 2013-07-18
  • 2012-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多