【问题标题】:WPF DataGrid - Set unique per row (object) combobox values from the DataGrid ItemsSource object's collection valueWPF DataGrid - 从 DataGrid ItemsSource 对象的集合值中设置唯一的每行(对象)组合框值
【发布时间】: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>

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

【问题讨论】:

    标签: c# wpf xaml combobox


    【解决方案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;
        }
    }
    

    【讨论】:

    • 太棒了。祝你好运
    猜你喜欢
    • 2012-11-30
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多