看起来WFP DataGridComboBoxColumn正在为此列中的所有单元格使用单个ItemsSource。我有一个案例,其中ComboBox项依赖于同一行中的另一个单元格。我设法在PreparingCellForEdit事件中填充ItemsSource。但是,它不能按预期工作。最初,此列中的所有单元格都是空的。一旦我为这个列的ComboBox填充ItemsSource,所有相关的单元格(具有相同的项目源)都显示值。但是,如果我单击其他类型的单元格(填充了不同的项目源),则所有值都将消失,新类型单元格将显示值。您只能为列使用一组Items Source?我不敢相信这是真的。我错过了什么吗?任何解决方法?
答案 0 :(得分:2)
你可能无法可靠地做到这一点。网格可以重用组合框或随机创建/销毁它。
偶然的机会我碰巧正在制作一个能做到这一点的屏幕。鉴于这些......
这使我能够将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
答案 1 :(得分:1)
感谢Jonathan的例子,我解决了我的问题如下。我修改了Jonathan的代码以突出我的解决方案。我从他的例子中删除了Territory属性,因为我不需要它来解决我的问题。
有两列。第一栏是国家。第二列是StateCandidate。 State列绑定到States列表,StateCandidate列绑定到StateCandidates列表。关键是在State更改时重新创建StateCandidates列表。因此,每行中可能有一个不同的StateCandidate列表(基于所选的状态)。
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
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列表,直到选择了另一行,这是一个我将要解决的分离问题。有人知道我怎么强行提交吗?
再次感谢Jonathan的灵感。我会一直在寻找更好的解决方案。