如何为WPF DataGrid获取单元级别的ComboBox?

new*_*man 6 wpf datagrid combobox itemssource

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

new*_*man 1

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

有两列。第一列是状态。第二列是 StateCandidate。State 列绑定到 States 列表,StateCandidate 列绑定到 StateCandidates 列表。关键点是,当 State 更改时,会重新创建 StateCandidates 列表。因此,每行中可能有不同的 StateCandidates 列表(基于所选的 State)。

主窗口.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>
Run Code Online (Sandbox Code Playgroud)

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,当状态更改时,它不会更新 StateCandidates 列表,直到选择不同的行,这是我将要解决的一个单独问题。有人知道我如何强制提交吗?

再次感谢乔纳森的灵感。我会继续寻找更好的解决方案。

  • @乔纳森:非常感谢您的链接。但是,我无法使该示例适用于该示例,可能是因为我不使用 DataTable。在为此苦苦挣扎时,我在该博客中发现了一条评论,指向 http://codefluff.blogspot.com/2010/05/commiting-bound-cell-changes.html。这个解决方案效果很好。 (2认同)