WPF 多列组合框
WPF Multi-Column Combobox
我知道有人问过这个问题,我查看了很多结果,但我发现的结果似乎并不完全有效,或者它们给我带来了问题。
我想要的是一个我可以输入的组合框,它会开始自动完成并根据单个列缩小范围。例如,如果我有名字和姓氏,我会输入姓氏,姓氏会缩小范围。
在下面的示例中,当我 select 组合框中的一个值时,我得到“System.Data.DataRowView”。
我已经使用 selection changed 事件进行了测试,只是为了检查,我什至无法为组合设置文本,但如果我可以 return 来自数据 table 的正确值。
如果有任何好的综合资源可以查找,如网站、教程、视频、在线课程、书籍,我将不胜感激。
- 搜索组合框和自动更新项目
- 显示带有项目的特定字段 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.RowFilter
的 filter 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>
我知道有人问过这个问题,我查看了很多结果,但我发现的结果似乎并不完全有效,或者它们给我带来了问题。
我想要的是一个我可以输入的组合框,它会开始自动完成并根据单个列缩小范围。例如,如果我有名字和姓氏,我会输入姓氏,姓氏会缩小范围。
在下面的示例中,当我 select 组合框中的一个值时,我得到“System.Data.DataRowView”。 我已经使用 selection changed 事件进行了测试,只是为了检查,我什至无法为组合设置文本,但如果我可以 return 来自数据 table 的正确值。
如果有任何好的综合资源可以查找,如网站、教程、视频、在线课程、书籍,我将不胜感激。
- 搜索组合框和自动更新项目
- 显示带有项目的特定字段 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.RowFilter
的 filter 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>