我有一个从DataGrid派生的类,当所有列都是DataGridTextColumns时,它可以很好地工作,并允许我提取每列中的不同字符串。但是,我不得不对其进行扩展以允许使用DataGridComboBox列,但是我找不到找到这些字符串的方法。
如果我有一个DataGridTextColumn,则可以使用下面的代码来获取包含字符串的不同值的排序列表。这段代码在我的子类DataGrid中,并且不需要在运行时知道数据源或数据源类型。
var type = this.Items[0].GetType();
var propertyInfo = type.GetProperty(columnName);
// Sorts the Items in the natural order for the property/column used
// then gets just that property as strings
// distinct etc.
List<string> query = this.Items.Cast<object>()
.OrderBy(i => propertyInfo.GetValue(i))
.Select(i => $"{propertyInfo.GetValue(i)}")
.Distinct()
.ToList();
return query;
DataGridComboBoxColumn链接到对象的SupplierId,我找不到将SupplierId转换为供应商名称的方法。这是列定义的XAML。
<DataGridComboBoxColumn
Header="Supplier"
SelectedValueBinding="{Binding SupplierId, Mode=TwoWay}"
DisplayMemberPath="Name"
SelectedValuePath="Id">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.SuppliersList, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.SuppliersList, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
public class MyObject
{
public int SupplierId { get; set; }
// other properties
}
public class Supplier
{
public int Id { get; set; }
public string Name { get; set; }
}
我已经到了无法实现的地步,我将不得不重新设计DataGrid类,但我真的不愿意。
答案 0 :(得分:1)
您的数据项,即this.Items
中的对象,没有要检索的名称。它仅具有SupplierId
属性。
因此,为了获得在ComboBox
中显示的名称,您需要从SuppliersList
未知的DataGrid
或视觉对象中获取名称。 ComboBox
元素,仅适用于已加载到可视化树中的行。
是的,您可能应该重新考虑您的设计。
如果您确实想获得视觉ComboBox
元素的引用,请参见以下示例:
foreach (object item in this.Items)
{
DataGridRow row = this.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
if (row != null)
{
ComboBox cmb = FindVisualChildren<ComboBox>(row)?.FirstOrDefault();
if (cmb != null)
{
string name = cmb.Text;
}
}
}