WPF DataGrid - 从 DataGrid ItemsSource 对象的集合值中设置唯一的每行(对象)组合框值

Posted

技术标签:

【中文标题】WPF DataGrid - 从 DataGrid ItemsSource 对象的集合值中设置唯一的每行(对象)组合框值【英文标题】:WPF DataGrid - Set unique per row (object) combobox values from the DataGrid ItemsSource object's collection value 【发布时间】:2021-05-01 22:15:52 【问题描述】:

我正在尝试根据行(对象)的单个集合值设置列组合框值,以便每一行具有基于另一个值的不同选项列表。

例如。

第 1 列:国家/地区组合框 - 例如英国选自 "UK", "USA", "France"

第 2 列:城市组合框 - 例如LA selected "New York", "LA", "Texas" (基于 USA 之前的选择)

下面是我的示例数据对象

public class ExampleData

    public List<string> countries  get; set; 
    public List<string> cities  get; set; 

    public string country  get; set; 
    public string city  get; set; 

    public ExampleData(string country)
    
        this.country = country;
        countries = new List<string>()  "UK", "USA", "France" ;
    

    // Example update method to change dependant options
    public void UpdateOptions()
    
        if (country == "UK")
        
            cities = new List<string>()  "London", "Bristol", "Birmingham" ;
        
        else if (country == "USA")
        
            cities = new List<string>()  "New York", "LA", "Texas" ;
        
        else if (country == "France")
        
            cities = new List<string>()  "Paris", "Lyon", "Nice" ;
        
        else
        
            cities = new List<string>();
        
    

然后我会创建一个数据的示例集合,以显示在数据网格中

 public void TestScenario()
 
     ExampleDataCollection = new List<ExampleData>();

     exampleDataList.Add(new ExampleData("UK"));
     exampleDataList.Add(new ExampleData("USA"));
     exampleDataList.Add(new ExampleData("France"));

     DataGrid.ItemsSource = ExampleDataCollection ;
  

然后在 xaml 中,我会将对象集合作为 ItemsSource 绑定到数据网格,而每个列组合框将绑定到对象自己的集合,该集合将是每行(对象)独立的。这类似于 ExampleData.countries,其中 ExampleData.Country 是选定的值。

<DataGrid
    Name="ExampleDataGrid"
    AutoGenerateColumns="False"
    ItemsSource="Binding ExampleDataCollection"
    >
    <DataGrid.Columns>
        <DataGridComboBoxColumn 
            Header="country" 
            ItemsSource="Binding ExampleData.countries"
            SelectedValueBinding="Binding ExampleData.country" 
            />
        <DataGridComboBoxColumn 
            Header="city" 
            ItemsSource="Binding ExampleData.cities"
            SelectedValueBinding="Binding ExampleData.city" 
            />
    </DataGrid.Columns>
</DataGrid>

这实际上是否可行,或者是否应该将替代方法应用于这种情况?从逻辑上讲,这并不是一个复杂的过程,但是我一直无法实施解决方案。

【问题讨论】:

【参考方案1】:

以经典形式,我几乎放弃后不久就解决了这个问题!

解决方案是将对象集合绑定到主窗口类中的数据网格,然后绑定国家、国家、城市和城市的各个属性。这还包括为相关下拉列表添加更新触发器,以便可以调用类中的更新方法。

<DataGrid
    Name="ExampleDataGrid"
    AutoGenerateColumns="False"
    >
    <DataGrid.Columns>

        <DataGridTemplateColumn Header="Country">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ComboBox ItemsSource="Binding countries" SelectedItem="Binding Country, UpdateSourceTrigger=PropertyChanged"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <DataGridTemplateColumn Header="city">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ComboBox ItemsSource="Binding cities" SelectedItem="Binding City, UpdateSourceTrigger=PropertyChanged"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        
    </DataGrid.Columns>
</DataGrid>

国家和城市的字符串列表已更新为可观察的集合,以便新的组合框在更改时更新它们。添加 INotifyPropertyChanged 意味着当国家或城市从绑定到它的下拉选择中更改时,它会调用 OnPropertyChanged 方法。

这让我可以调用另一个方法来更新新的城市列表。必须注意的是,您不能简单地通过 equals 将现有集合替换为新集合。它必须具有与之相关的更改,例如添加或删除(不清楚)才能实际更新。见下文。

public class ExampleData : INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<string> countries  get; set; 
    public ObservableCollection<string> cities  get; set; 
    public ObservableCollection<string> towns  get; set; 

    private string country;
    private string city;
    private string town;
    
    public string Country
    
        get
        
            return country;
        
        set
        
            country = value;
            // Call OnPropertyChanged whenever the property is updated
            OnPropertyChanged("Country");
        
    
    public string City
    
        get
        
            return city;
        
        set
        
            city = value;
        
    
    public string Town  get; set; 

    public ExampleData(string country)
    
        this.country = country;
        countries = new ObservableCollection<string>()  "UK", "USA", "France" ;
        cities = new ObservableCollection<string>()  "London", "Bristol", "Plymouth" ;
    

    // Create the OnPropertyChanged method to raise the event 
    protected void OnPropertyChanged(string name)
    
        UpdateOptions();

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        
            handler(this, new PropertyChangedEventArgs(name));
            
        
    

    public void UpdateOptions()
    
        List<string> oldCities = cities.ToList<string>();

        List<string> newCities;

        foreach (string city in oldCities)
        
            cities.Remove(city);
        

        if (country == "UK")
        
            newCities = new List<string>()  "London", "Bristol", "Birmingham" ;
        
        else if (country == "USA")
        
            newCities = new List<string>()  "New York", "LA", "Texas" ;
        
        else if (country == "France")
        
            newCities = new List<string>()  "Paris", "Lyon", "Nice" ;
        
        else
        
            newCities = new List<string>();
        

        foreach (string city in newCities)
        
            cities.Add(city);
        
    

主窗口代码未做任何更改,如下所示。

public partial class MainWindow : Window

    public List<ExampleData> exampleDataList;

    public MainWindow()
    
        InitializeComponent();
        TestScenario();
    

    public void TestScenario()
    
        exampleDataList = new List<ExampleData>();

        exampleDataList.Add(new ExampleData("UK"));
        exampleDataList.Add(new ExampleData("USA"));
        exampleDataList.Add(new ExampleData("France"));
        ExampleDataGrid.ItemsSource = exampleDataList;
    

【讨论】:

太棒了。祝你好运

以上是关于WPF DataGrid - 从 DataGrid ItemsSource 对象的集合值中设置唯一的每行(对象)组合框值的主要内容,如果未能解决你的问题,请参考以下文章

从 WPF DataGrid 中的按钮触发 RelayCommand

WPF DataGrid常用属性记录

使用 MVVM 从 WPF 中的 TextBox 进行正确的 DataGrid 搜索

从MVVM WPF项目中的DataGrid中选择多个项目

WPF DataGrid - 从 DataGrid ItemsSource 对象的集合值中设置唯一的每行(对象)组合框值

WPF入门教程系列二十一——DataGrid示例