【问题标题】:Binding collection to ComboBox in DataGrid将集合绑定到 DataGrid 中的 ComboBox
【发布时间】:2014-03-21 10:22:41
【问题描述】:

当 ComboBox 在 DataGrid 中实现时,我有两个关于将 ComboBox 绑定到列表对象的问题。但它们是如此相互关联,以至于我认为两个线程没有建设性。

我有很多类,我想在 xceed DataGrid 中显示它们的数据。我的 DataContext 设置为 ViewModelClass。它有一个 X 类对象的列表:

public class ViewModelClass
{
    public IList<X> ListX { get; set; }
}

X 类看起来像这样。它有一个属性 ID 和一个 Y 类对象的列表。 该列表应该是我的 ComboBoxes 的 ItemsSource(在 DataGrid 中)。

public class X
{
     public int Id { get; set; }

     // this should be my ItemsSource for the ComboBoxes
     public IList<Y> ListY { get; set; }
}

类 Y 和 Z 看起来像这样。它们是一些非常简单的类:

public class Y
{
     public Z PropZ { get; set; }
}

public class Z
{
     public string Name { get; set; }
}

我的 XAML 代码看起来像这样。

<Grid.Resources>
<xcdg:DataGridCollectionViewSource x:Key="ListX" AutoCreateItemProperties="False"
                                   Source="{Binding Path=ListX,
                                                    UpdateSourceTrigger=PropertyChanged,
                                                    Mode=TwoWay}" />
</Grid.Resources>

<p:DataGrid AutoCreateColumns="False"
            ItemsSource="{Binding Source={StaticResource ListX},
                                  UpdateSourceTrigger=PropertyChanged}">

    <xcdg:Column Title="Id" FieldName="Id" />

    <xcdg:Column Title="Functions" **FieldName="ListY"**>
        <xcdg:Column.CellContentTemplate>
            <DataTemplate>
                <ComboBox DisplayMemberPath="PropZ.Name"
                          **ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type xcdg:DataGridControl}}, Path=ItemsSource.ListY**}"                                      SelectedValuePath="Funktion.FunktionId" />
            </DataTemplate>
        </xcdg:Column.CellContentTemplate>
    </xcdg:Column>
  1. 现在我不知道,如何绑定ComboBox的ItemsSource,以便在我的X类中读取ListY的列表值?

  2. 那么我不知道我的函数列的字段名实际上是什么? 我输入了 ListY,因为它代表了我的 X 类中的属性 (IList)。但我觉得可能不太对。

非常感谢您的帮助!

【问题讨论】:

    标签: c# wpf datagrid combobox


    【解决方案1】:

    要回答您的第一个问题 - 试试这个

    <ComboBox ItemsSource="{Binding Path=DataContext.ListY, 
     RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
    

    对于您的第二个问题,我不太确定(取决于您),但字段名称可能是 SelectedFunction 或类似的东西

    【讨论】:

    • 不,抱歉,它不起作用。在我的 DataContext 中是已知的 ListX 属性,但没有 ListY 属性。如果有的话,我将不得不编写 DataContext.ListX.ListY。但它也不起作用。不管怎样,谢谢你的回答!
    【解决方案2】:

    让我们将您的问题分解成小块。您有一个 ListX 集合,它的数据绑定到 DataGrid.ItemsSource 属性:

    <DataGrid ItemsSource="{Binding ListX}" ... />
    

    在此阶段要注意您的代码的一点是,在 ItemsSource 属性上将 Binding.UpdateSourceTrigger property 设置为 PropertyChanged 是没有意义的。从链接页面:

    TwoWay 或 OneWayToSource 的绑定侦听目标属性中的更改并将它们传播回源。这称为更新源。通常,只要目标属性更改,就会发生这些更新。这适用于复选框和其他简单控件,但通常不适用于文本字段。每次击键后更新可能会降低性能,并且它会剥夺用户在提交新值之前退格和修复打字错误的通常机会。因此,Text 属性的默认 UpdateSourceTrigger 值为 LostFocus 而不是 PropertyChanged。

    真的应该知道代码在使用之前做了什么。

    所以无论如何,回到你的问题...我们有一个数据绑定DataGrid,其中一列有一个ComboBox。我不太确定您为什么不使用DataGridComboBoxColumn Class 或同等产品,但没关系。现在,您需要了解所有集合控件:

    如果A 类型的集合是绑定到集合控件的ItemsSource 属性的数据,则集合控件的每个项都将是A 类型的实例。这意味着每个项目的DataContext 将被设置为A 类型的实例。这意味着我们可以从定义每个项目应该是什么样子的任何DataTemplate 中访问类A 中定义的所有属性。

    这意味着您可以从定义您的项目外观的DataTemplate 中直接访问X 类的ListY 属性。因此,您应该能够做到这一点:

    <DataTemplate>
        <ComboBox DisplayMemberPath="PropZ.Name" ItemsSource="{Binding ListY}" 
            SelectedValuePath="Funktion.FunktionId" />
    </DataTemplate>
    

    我无法确认您设置的 SelectedValuePath 是否有效,因为您没有在任何地方提及它,但如果您的班级 Y 没有名为 Funktion 的属性,那么它不会工作。您还必须更好地解释您的第二个问题,因为我并没有真正理解它。

    【讨论】:

    • 在我的 DataContext 中是 ListX 属性。我可以将它用作 DataGrid 的数据源,我也这样做了。因此,DataGrid 的每一行都包含 ListX 类型的数据。 ListY 属性在我的 DataContext 中是未知的。至少不是直接的。因为我需要访问每一行,因此可以将相应 ComboBox 的 ItemsSource 属性设置为 ((ListX)datarow).ListY。我直接给
    • "Function" 是我工作的实际名称。为简单起见,因为零件有德语术语,所以我使用了替代名称。以“功能”的名义,我已经忘记了。感谢您的回答 !字段名称的问题现在是次要的。如果第一个问题得到解决,解决方案会很有趣。但是没有解决我第二个问题的解决方案并不需要太多。
    【解决方案3】:

    我找到了一个解决方案,但即使这样也没有被证明是有效的。因为将 cell.Content 分配给 comboBox.ItemsSource 在我的视图中没有显示效果:-(

    在 XAML 中,我有以下代码

    <xcdg:Column.CellContentTemplate>
        <DataTemplate>
            <p:XDataGridComboBox 
                DataRow="{Binding RelativeSource={RelativeSource AncestorType={x:Type xcdg:DataRow}}}" 
                ItemsFieldName="Functions" />
        </DataTemplate>
    </xcdg:Column.CellContentTemplate>
    

    我编写了一个自定义控件,在其中明确设置了每个 ComboBox 的数据源:

    static XDataGridComboBox()
    {
        DataRowProperty = DependencyProperty.RegisterAttached(
            "DataRow",
            typeof(DataRow),
            typeof(XDataGridComboBox),
            new FrameworkPropertyMetadata(OnChangeDataRow));
    
            ItemsFieldNameProperty = DependencyProperty.RegisterAttached(
                "ItemsFieldName",
                typeof(string),
                typeof(XDataGridComboBox),
                new FrameworkPropertyMetadata(OnChangeItemsFieldName));
    }
    
    private static void OnChangeDataRow(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var comboBox = d as XDataGridComboBox;
        if (comboBox == null)
        {
            return;
        }
    
        var cell =
            (from DataCell c in comboBox.DataRow.Cells where c.FieldName == comboBox.ItemsFieldName select c)
                .FirstOrDefault();
    
        if (cell == null)
        {
            return;
        }
    
        comboBox.ItemsSource = cell.Content as IEnumerable;
    }
    

    我需要的数据可用,但视图没有显示。我不知道我没有考虑到什么。

    【讨论】:

    • 我找到了一个非常简单的解决方案:
    猜你喜欢
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    相关资源
    最近更新 更多