数据网格与自动完成组合框-再次



我知道这已经被问过几次了,但是我无法找到一个允许在WPF DataGrid中使用组合框的工具包。允许过滤和自动完成,没有一个问题提供任何解决方案,我能够工作。我需要的组合框列的行为是:

  • 按下单元格的下拉按钮将显示ItemSource中的所有对象。
  • 只要你按下"文本框"的一部分,它会过滤下拉框,当你输入/删除文本,并取决于在组合框中的文本。
  • 输入无效的内容将显示"未找到";在下拉菜单中。按下或失去焦点只会保留组合框中最后一个有效的项目。

我已经尝试了几个选项,我既不能得到工作与数据网格或者他们根本不具备上述要求。例子:

  1. DotNetProjects。WpfToolkit
  2. Syncfusion。ComboBoxAdv

我创建了一个简单的测试应用程序来测试几个选项。我的模型是一个水果和蔬菜对象,只有一个属性(名称)。我有一个Customer对象,它有名称和项目(水果或蔬菜)。

public class Vegetable : IsFruitOrVegetable, INotifyPropertyChanged
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
RaisePropertyChanged("Name");
}
}
public Vegetable()
{
}
public Vegetable(string _Name)
{
this.Name = _Name;
}

public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string PropertyName)
{
var property = PropertyChanged;
if (property != null)
property(this, new PropertyChangedEventArgs(PropertyName));
}
}
public class Fruit: IsFruitOrVegetable, INotifyPropertyChanged
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
RaisePropertyChanged("Name");
}
}
public Fruit()
{
}
public Fruit(string _Name)
{
this.Name = _Name;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string PropertyName)
{
var property = PropertyChanged;
if (property != null)
property(this, new PropertyChangedEventArgs(PropertyName));
}
}
public class Customer : INotifyPropertyChanged
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
RaisePropertyChanged("Name");
}
}
private IsFruitOrVegetable item;
public IsFruitOrVegetable Item
{
get
{
return item;
}
set
{
item = value;
RaisePropertyChanged("Item");
}
}
private int totalQuantity;
public int TotalQuantity
{
get
{
return totalQuantity;
}
set
{
totalQuantity = value;
RaisePropertyChanged("TotalQuantity");
}
}
public Customer()
{
}
public Customer(string _Name)
{
this.Name = _Name;
Item = null;
TotalQuantity = 1;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string PropertyName)
{
var property = PropertyChanged;
if (property != null)
property(this, new PropertyChangedEventArgs(PropertyName));
}
}

我的视图模型由我的客户列表(CustomersList)和itemsList(水果和蔬菜的项目列表)组成。

public class MainViewModel : INotifyPropertyChanged
{
private ObservableCollection<Customer> customersList;
public ObservableCollection<Customer> CustomersList
{
get
{
return customersList;
}
set
{
customersList1 = value;
}
}
private ObservableCollection<IsFruitOrVegetable> itemsList;
public ObservableCollection<IsFruitOrVegetable> ItemsList
{
get
{
return itemsList;
}
set
{
itemsList = value;
}
}
private IsFruitOrVegetable itemOption;
public IsFruitOrVegetable ItemOption
{
get
{
return itemOption;
}
set
{
itemOption = value;
}
}
public MainViewModel()
{
ItemsList = new ObservableCollection<IsFruitOrVegetable>();
ItemsList.Add(new Fruit("Apple"));
ItemsList.Add(new Fruit("Banana"));
ItemsList.Add(new Fruit("Avocado"));
ItemsList.Add(new Fruit("Blueberries"));
ItemsList.Add(new Vegetable("Broccoli"));
ItemsList.Add(new Vegetable("Cabbage"));
ItemsList.Add(new Vegetable("Carrot"));
ItemsList.Add(new Vegetable("Cauliflower"));
CustomersList = new ObservableCollection<Customer>();
CustomersList.Add(new Customer("Bob"));
CustomersList.Add(new Customer("Tony"));
CustomersList.Add(new Customer("John"));
CustomersList[0].Item = ItemsList[0];
CustomersList[1].Item = ItemsList[1];
CustomersList[2].Item = ItemsList[2];
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string PropertyName)
{
var property = PropertyChanged;
if (property != null)
property(this, new PropertyChangedEventArgs(PropertyName));
}
}

My view for:

<Label Content="DEFAULT COMBOBOX" HorizontalAlignment="Left" Height="32" Margin="22,10,0,0" VerticalAlignment="Top" Width="207"/>
<ComboBox HorizontalAlignment="Left" Margin="22,47,0,0" VerticalAlignment="Top" Width="120" DisplayMemberPath="Name"
SelectedValue="{Binding ItemOption, Source={StaticResource viewModel}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding ItemsList,Source={StaticResource viewModel}}"/>
<DataGrid HorizontalAlignment="Left" Height="291" Margin="22,90,0,0" VerticalAlignment="Top" Width="207"
ItemsSource="{Binding CustomersList,Source={StaticResource viewModel}}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Customer" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="*"/>
<DataGridComboBoxColumn Header="Item" ItemsSource="{Binding ItemsList,Source={StaticResource viewModel}}" Width="*"
DisplayMemberPath="Name"
SelectedItemBinding="{Binding Item, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataGrid.Columns>
</DataGrid>

我知道很多解决方案实现模板列,但我找不到一个组合框,我想实现这一意图的工作。有人可以提供一个超级简单的例子,允许或指出我在正确的方向?

我也做过类似的事情,试试https://github.com/DamnjanMarkovic/WPFMedicalData.

行为是非常具体的。如果你没有找到任何的组合框,行为正确的方式,你总是可以自己创建它。

一种方式可以是一个ToggleButton与一个弹出。对于可重用性,你也可以把它放入UserControl

这里有一个非常简单的例子,你如何开始自己创建控件(没有功能和测试)。

<ToggleButton x:name="MyButton" />
<Popup
PlacementTarget="{Binding ElementName=MyButton}"
Width="{Binding ActualWidth, ElementName=MyButton}">
<Border
BorderBrush="Black"
BorderThickness="2"
Background="White">
<StackPanel>
<!-- Some Other Controlls like an TextBox for searching the contents -->
<!-- List View for displaying the ItemSource -->
</StackPanel>
</Border>
</Popup>

要在Datagrid中实现它,我建议使用templatecolluml。

<DataGridTemplateColumn Header="Header">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<uc:CustomUserControl />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>

请注意,如果ItemSource不是您的项目模型的一部分,则需要一个相对源。

ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}, Mode=FindAncestor}, Path=DataContext.YourItemSource}"

最新更新