WPF 多列组合框

WPF Multi-Column Combobox

我知道有人问过这个问题,我查看了很多结果,但我发现的结果似乎并不完全有效,或者它们给我带来了问题。

我想要的是一个我可以输入的组合框,它会开始自动完成并根据单个列缩小范围。例如,如果我有名字和姓氏,我会输​​入姓氏,姓氏会缩小范围。

在下面的示例中,当我 select 组合框中的一个值时,我得到“System.Data.DataRowView”。 我已经使用 selection changed 事件进行了测试,只是为了检查,我什至无法为组合设置文本,但如果我可以 return 来自数据 table 的正确值。

如果有任何好的综合资源可以查找,如网站、教程、视频、在线课程、书籍,我将不胜感激。

  1. 搜索组合框和自动更新项目
  2. 显示带有项目的特定字段 selected

资源XAML:

 <Style x:Key="txtStyle" TargetType="{x:Type TextBlock}">
            <Setter Property="TextAlignment" Value="Left"></Setter>
            <Setter Property="FontSize" Value="14"></Setter>
            <Setter Property="HorizontalAlignment" Value="Left"></Setter>
        </Style>

 <DataTemplate x:Key="comboKEY">
            <Grid Height="25" Width="300" ShowGridLines="false">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="0"></ColumnDefinition>
                    <ColumnDefinition Width="200"></ColumnDefinition>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Column="0"  Text="{Binding Path='id'}"
                    Style="{StaticResource txtStyle}"></TextBlock>
                <TextBlock Grid.Column="1"  Text="{Binding Path='site_name'}"
                    Style="{StaticResource txtStyle}"
                           TextWrapping="Wrap"></TextBlock>
            </Grid>
        </DataTemplate>

XAML组合框

<WrapPanel Orientation="Horizontal" Canvas.Left="10" Canvas.Top="90">
                <ComboBox IsEditable="True"
                  Width="200"
                  Height="25"
                  IsTextSearchEnabled="False"
                  x:Name="cboName"
                  ItemTemplate="{StaticResource comboKEY
                  ItemsSource="{Binding}" SelectionChanged="cboName_SelectionChanged">
                </ComboBox>
            </WrapPanel>

代码隐藏

 private void cboName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            cboName.Text = dt.Rows[cboName.SelectedIndex]["dt_field"].ToString();
           
            test1.Content = dt[cboName.SelectedIndex]["dt_field"].ToString();
        }

当您想要过滤或排序 DataTable 时,您应该创建一个 DataView 并绑定到它。然后使用分配给 DataView.RowFilterfilter expression 来动态过滤 table.

以下示例显示如何通过处理由 ComboBox.
的 editable TextBox 引发的 TextBox.TextChanged 基于文本输入进行过滤 要过滤的列也是动态的。

由于 ComboBox.IsEditable 设置为 True,选择框的 ContenPresenter 被替换为 TextBox。这意味着您只能显示文本。默认情况下 ComboBox 将调用 object.ToString()。如果 DataRowView 之类的项目没有提供可用的覆盖,您只能设置 ComboBox.DisplayMemberPath。设置这个 属性 不允许设置 ComboBox.ItemTemplate。如果您仍想对下拉项进行布局,则必须覆盖 ComboBox.ItemContainerStyle.

MainWindow.xaml.cs

partial class MainWindow : Window
{
  // This property should be a DependencyProperty
  public DataView DataTableView { get; set; }

  // This property should be a DependencyProperty and have a property changed callback to update the DataTableView filter registered
  public string FilteredColumnName { get; set; }

  public MainWindow()
  { 
    InitializeComponent();
    this.DataContext = this;

    var dataTable = new DataTable();
   
    // TODO::Populate DataTable.
    // Assume table has a column 'LastName'

    this.DataTableView = dataTable.DefaultView;

    // Filter based on column 'LastName'
    this.FilteredColumnName = "LastName";
  }

  private void FilterDataTable_OnTextInput(object sender, TextChangedEventArgs textChangedEventArgs)
  {
    var comboBox = sender as ComboBox;
    var dataview = comboBox.ItemsSource as DataView;

    // Filter based on column 'LastName', 
    // where the value starts with the entered text: '<columnName> LIKE '<textInput>*'
    dataview.RowFilter = $"{this.FilteredColumnName} LIKE '{(textChangedEventArgs.OriginalSource as TextBox).Text}*'";
  }
}

MainWindow.xaml

<Window>
  <ComboBox ItemsSource="{Binding DataTableView}"
            DisplayMemberPath="LastName"
            SelectedValuePath="LastName"
            IsEditable="True" 
            StaysOpenOnEdit="True"
            TextBox.TextChanged="FilterDataTable_OnTextInput">
    <ComboBox.ItemContainerStyle>
      <Style TargetType="{x:Type ComboBoxItem}">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
              <Border BorderBrush="{TemplateBinding BorderBrush}"
                      BorderThickness="{TemplateBinding BorderThickness}"
                      Background="{TemplateBinding Background}">
                <StackPanel Orientation="Horizontal">
                  <TextBlock Text="{Binding Name}" />
                  <TextBlock Text="{Binding LastName}" />
                </StackPanel>
              </Border>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </ComboBox.ItemContainerStyle>
  </ComboBox>
</Window>