如何获取单元格级别的ComboBox for WPF DataGrid? [英] How to get cell level ComboBox for WPF DataGrid?

查看:169
本文介绍了如何获取单元格级别的ComboBox for WPF DataGrid?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看起来WFP DataGridComboBoxColumn正在为此列中的所有单元格使用单个ItemsSource。我有一个case ComboBox项目依赖于同一行中的其他单元格。我设法填充PrepiseCellForEdit事件中的ItemsSource。但是,它不能按预期工作。最初,此列中的所有单元格都为空。一旦我为这个列的ComboBox填充ItemsSource,所有相关的单元格(具有相同的项目源)显示值。但是,如果我单击另一种类型的单元格(填充不同的项目源),所有值都消失,新类型单元格显示值。您只能为列使用一组项目源?我不能相信这是真的。我错过了什么吗?任何解决方法?

It looks WFP DataGridComboBoxColumn is using a single ItemsSource for all cells in this column. I have a case where the ComboBox items are dependent on the other cell in the same row. I managed to populate the ItemsSource in PreparingCellForEdit event. However, it doesn't work as desired. Initially, all cells in this column is empty. Once I populate the ItemsSource for this column's ComboBox, all related cells (with the same items source) are showing values. However, if I click another type of cell (a different items source is populated), all values disappear and the new type cells show values. You can only use one set of Items Source for a column? I can't believe it is true. Did I miss anything? Any workaround?

推荐答案

感谢Jonathan的例子,我解决了我的问题如下。我修改了Jonathan的代码以突出我的解决方案。我从他的示例中删除了Territory属性,因为我不需要它为我的问题。

Thanks to Jonathan's example, I resolved my problem as follows. I modifiedy Jonathan's code to highlight my solution. I removed the Territory property from his example because I don't need it for my problem.

有两列。第一列是状态。第二列是StateCandidate。状态列绑定到一个状态列表,StateCandidate列绑定到一个StateCandidates列表。关键点是StateCandidates列表在状态更改时重新创建。因此,每行(根据所选州)可能有不同的StateCandidates列表。

There are two columns. First column is State. Second column is StateCandidate. State column is bind to a States list, and StateCandidate column is bind to a StateCandidates list. The key point is that the StateCandidates list is recreated when State is changed. So, there could be a different list of StateCandidates in each row (based on the selected State).

MainWindow.xaml

MainWindow.xaml

<Window x:Class="WpfTest1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid Name="Zoom" AutoGenerateColumns="False" Background="DarkGray" RowHeaderWidth="50" HeadersVisibility="All">
            <DataGrid.Columns>
                <DataGridTemplateColumn x:Name="colState" Header="State" Width="120">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding State}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox SelectedItem="{Binding State}" ItemsSource="{Binding States}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn x:Name="colStateCandiate" Header="State Candidate" Width="200">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding StateCandidate}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox SelectedItem="{Binding StateCandidate}" ItemsSource="{Binding StateCandidates}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

MainWindow.xaml.cs

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace WpfTest1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            List<Model> list = new List<Model>();
            list.Add(new Model() { State = "TX", StateCandidate = "TX2" });
            list.Add(new Model() { State = "CA" });
            list.Add(new Model() { State = "NY", StateCandidate = "NY1" });
            list.Add(new Model() { State = "TX" });
            list.Add(new Model() { State = "AK" });
            list.Add(new Model() { State = "MN" });

            Zoom.ItemsSource = list;
            Zoom.PreparingCellForEdit += new EventHandler<DataGridPreparingCellForEditEventArgs>(Zoom_PreparingCellForEdit);
        }

        void Zoom_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
        {
            if (e.Column == colStateCandiate)
            {                
                DataGridCell cell = e.Column.GetCellContent(e.Row).Parent as DataGridCell;
                cell.IsEnabled = (e.Row.Item as Model).StateCandidates != null;
            }
        }
    }
    public class Model : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _state;
        private List<string> _states = new List<string>() { "CA", "TX", "NY", "IL", "MN", "AK" };
        private string _stateCandidate;
        private List<string> _stateCandidates;

        public string State
        {
            get { return _state; }
            set
            {
                if (_state != value)
                {
                    _state = value;
                    _stateCandidate = null;
                    if (_state == "CA" || _state == "TX" || _state == "NY")
                        _stateCandidates = new List<string> { _state + "1", _state + "2" };
                    else
                        _stateCandidates = null;
                    OnPropertyChanged("State");
                }
            }
        }
        public List<string> States
        {
            get { return _states; }
        }
        public string StateCandidate
        {
            get { return _stateCandidate; }
            set 
            {
                if (_stateCandidate != value)
                {
                    _stateCandidate = value;
                    OnPropertyChanged("StateCandidate");
                }
            }
        }
        public List<string> StateCandidates
        {
            get { return _stateCandidates; }
        }
        public void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
}

请注意,更改,它不会更新StateCandidates列表,直到选择不同的行,这是一个单独的问题,我会战斗。有人知道我如何强制执行吗?

Note that, when State is changed, it won't update StateCandidates list until a different row is selected, which is a separated issue I'll be fighting. Do anybody know how I can force commit?

感谢Jonathan再次感谢他的灵感。我会继续寻找一个更好的解决方案。

Thanks to Jonathan again for his inspiration. I'll keep looking for a better solution.

这篇关于如何获取单元格级别的ComboBox for WPF DataGrid?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆