6

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

4

2 回答 2

2

你可能无法可靠地做到这一点。网格可以重复使用组合框或随机创建/销毁它。

碰巧我碰巧在一个可以做到这一点的屏幕上工作。鉴于这些...

  • 网格中的每一行都绑定到 Trade 类型的对象。
  • 每个贸易都有一个国家财产
  • 每个 Trade 都有一个 TerritoryCanidates 属性
  • 更改 State 属性将导致 TerritoryCanidates 属性更改

这使我能够将 ItemsSource 绑定到 TerritoryCanidates 属性。反过来,DataGrid 在所有情况下都会遵守。


<Window x:Class="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">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="State">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding State}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox SelectedItem="{Binding State}" ItemsSource="{Binding StateCanidates}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Territory">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Territory}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox SelectedItem="{Binding Territory}" ItemsSource="{Binding TerritoryCanidates}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

        </DataGrid.Columns>

    </DataGrid>
</Grid>
</Window>


Imports System.ComponentModel

Class MainWindow
Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Dim x As New List(Of Model)
    x.Add(New Model)
    x.Add(New Model)
    x.Add(New Model)

    Zoom.ItemsSource = x
End Sub
End Class

Class Model
Implements INotifyPropertyChanged

Public ReadOnly Property StateCanidates As List(Of String)
    Get
        Return New List(Of String) From {"CA", "TX", "NY"}
    End Get
End Property

Public ReadOnly Property TerritoryCanidates As List(Of String)
    Get
        If State = "" Then Return Nothing
        Return New List(Of String) From {State & "1", State & "2"}
    End Get
End Property

Private m_State As String
Public Property State() As String
    Get
        Return m_State
    End Get
    Set(ByVal value As String)
        m_State = value
        OnPropertyChanged("State")
        OnPropertyChanged("TerritoryCanidates")
    End Set
End Property

Private m_Territory As String
Public Property Territory() As String
    Get
        Return m_Territory
    End Get
    Set(ByVal value As String)
        m_Territory = value
        OnPropertyChanged("Territory")
    End Set
End Property




Public Sub OnPropertyChanged(ByVal propertyName As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub

Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
于 2010-10-01T23:25:54.910 回答
1

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

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

主窗口.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>

主窗口.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));
        }
    }
}

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

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

于 2010-10-03T02:58:26.473 回答