【问题标题】:Binding Combobox inside DataGrid在 DataGrid 中绑定 Combobox
【发布时间】:2020-07-20 19:30:44
【问题描述】:

我有一个包含 3 列的 DataGrid:名称 -DataGridTextColumn、Value-DataGridTextColumn、ParamJson - 带有组合框的 DataGridTemplateColumn,并且有一个 ParameterGrid 的 ICollectionView 作为源。

有一个ViewModel提供了ParameterGrid的ICollectionView。 ParameterGrid包含4个参数:Name、Value、ParamJson、SelectedParamJson。

我需要处理 DataGrid 的所有行,所以我使用获取所有 dataGrid 作为命令参数的命令,而不是遍历 DataGrid.Items(我可以直接使用 ICollectionView?)。

问题是如何将DataGrid中Combobox中的SelectedItem正确绑定到SelectedParamJson?

Xaml:

<DataGrid Grid.Row="0"
                x:Name="parametersGridView"
                AutoGenerateColumns="False"
                VerticalScrollBarVisibility="Visible"
                CanUserAddRows="False"
                ItemsSource="{Binding PropertiesGrid}"
                Margin="5"
                AlternatingRowBackground="LightGoldenrodYellow">

         <DataGrid.Columns>
            <DataGridTextColumn Header="Name"
                                Binding="{Binding Path=Name}"
                                IsReadOnly="True" />

            <DataGridTextColumn Header="Value"
                                Binding="{Binding Path=Value}" />

            <DataGridTemplateColumn Header="Parameter" >
               <DataGridTemplateColumn.CellTemplate>
                  <DataTemplate>
                     <ComboBox MinWidth="100"
                               MaxWidth="150"
                               ItemsSource="{Binding Path=ParamsJson}"
                               SelectedItem="{Binding Path=SelectedParamJson, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                               StaysOpenOnEdit="True"
                               IsEditable="True">
                        <ComboBox.ItemTemplate>
                           <DataTemplate>
                              <TextBlock Text="{Binding}" />
                           </DataTemplate>
                        </ComboBox.ItemTemplate>
                     </ComboBox>
                  </DataTemplate>
               </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

         </DataGrid.Columns>
      </DataGrid >     <DataGrid Grid.Row="0"
                x:Name="parametersGridView"
                AutoGenerateColumns="False"
                VerticalScrollBarVisibility="Visible"
                CanUserAddRows="False"
                ItemsSource="{Binding PropertiesGrid}"
                Margin="5"
                AlternatingRowBackground="LightGoldenrodYellow">

         <DataGrid.Columns>
            <DataGridTextColumn Header="Name"
                                Binding="{Binding Path=Name}"
                                IsReadOnly="True" />

            <DataGridTextColumn Header="Value"
                                Binding="{Binding Path=Value}" />

            <DataGridTemplateColumn Header="Parameter" >
               <DataGridTemplateColumn.CellTemplate>
                  <DataTemplate>
                     <ComboBox ItemsSource="{Binding Path=ParamsJson}"
                               SelectedItem="{Binding Path=SelectedParamJson, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                               StaysOpenOnEdit="True"
                               IsEditable="True">
                        <ComboBox.ItemTemplate>
                           <DataTemplate>
                              <TextBlock Text="{Binding}" />
                           </DataTemplate>
                        </ComboBox.ItemTemplate>
                     </ComboBox>
                  </DataTemplate>
               </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

         </DataGrid.Columns>
      </DataGrid >`

视图模型

class DataGridViewModel : DependencyObject
{
    public DataGridViewModel()
    {
        var data = new DataEmulator();
        PropertiesGrid = CollectionViewSource.GetDefaultView(data.GetCommonParameters());
    }

    public ICollectionView PropertiesGrid
    {
        get { return (ICollectionView)GetValue(PropertiesGridProperty); }
        set { SetValue(PropertiesGridProperty, value); }
    }
    public static readonly DependencyProperty PropertiesGridProperty =
        DependencyProperty.Register("PropertiesGrid", typeof(ICollectionView), typeof(DataGridViewModel), new PropertyMetadata(null));

    public ICommand TestCommand
    {
        get
        {
            return new RelayCommand
            {
                ExecuteAction = a =>
                {

                    // here SelectedParamJson should be as Selected in combobox,
                    // but it is always null because of the wrong binding
                },
                CanExecutePredicate = p =>
                {
                    return true;
                }
            };
        }
    }
}
public class ParameterGrid
{
    public string Name { get; set; }
    public string Value { get; set; }
    public List<SamResult> ParamsJson { get; set; }
    public SamResult SelectedParamJson { get; set; }
}

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    如果要绑定到与ParamsJson 属性在同一类中定义的SelectedParamJson 属性,则根本不应将RelativeSource 属性设置为任何值:

    ItemsSource="{Binding Path=ParamsJson}"
    SelectedItem="{Binding Path=SelectedParamJson}"
    

    您还应该将ComboBox 移动到DataGridTemplateColumn 的CellEditingTemplate。

    【讨论】:

      【解决方案2】:

      问题是您必须定义&lt;DataGridTemplateColumn.CellEditingTemplate&gt;,您应该在其中进行所有绑定和&lt;DataGridTemplateColumn.CellTemplate&gt;,即当单元格不活动时的当前值。

      您无法绑定&lt;DataGridTemplateColumn.CellTemplate&gt; 中的所有内容,这似乎很奇怪,因为您必须额外单击才能激活组合框。

      适合我的 Xaml:

          <DataGridTemplateColumn Header="Parameter" >
      
             <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                   <TextBlock Text="{Binding Path=SelectedParamJson}" />
                </DataTemplate>
             </DataGridTemplateColumn.CellTemplate>
      
             <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                   <ComboBox MinWidth="100"
                             MaxWidth="150"
                             ItemsSource="{Binding Path=ParamsJson}"
                             SelectedItem="{Binding Path=SelectedParamJson}"
                             StaysOpenOnEdit="True"
                             IsEditable="True">
                      <ComboBox.ItemTemplate>
                         <DataTemplate>
                            <TextBlock Text="{Binding}" />
                         </DataTemplate>
                      </ComboBox.ItemTemplate>
                   </ComboBox>
                </DataTemplate>
             </DataGridTemplateColumn.CellEditingTemplate>
      
          </DataGridTemplateColumn>
      

      【讨论】:

      • 我将不胜感激另一个解决方案,其中 ComboBox 无需额外单击单元格即可激活它
      • 亲爱的@mm8,如果我理解正确,你的答案是ItemsSource="{Binding Path=ParamsJson}" SelectedItem="{Binding Path=SelectedParamJson}",但如果你看一下我的答案,问题就出在另一件事上。在我的问题中,我在&lt;DataGridTemplateColumn.CellTemplate&gt; 部分定义了Combobox,而不是&lt;DataGridTemplateColumn.CellEditingTemplate&gt;。并且由于某种原因,当Combobox 在&lt;DataGridTemplateColumn.CellTemplate&gt; 中定义时,绑定不起作用。在我的变体中,您在单击单元格之前看不到Combobox。如果可行,请使用完整代码发布您的答案。
      • 您在原始代码中使用了RelativeSource。这就是 binding 不起作用的原因。无论如何,我更新了我的答案,包括关于将元素放入 CellEditingColumn 的注释。
      • 好的,让我们在您的帖子中合并我们的答案。并将我的回答标记为有用。
      【解决方案3】:

      您的祖先不是数据网格,而是您要从中获取数据上下文的数据行。

      所以您创建了一些源集合(如列表)的集合视图,这意味着您的 Datagrid 中的每一行都代表一个 IJsonObject 对象,并且您应该在那里定义 ComboBox 列的集合。就像可以绑定到 Column 的 List 一样,在 Turn 中,您可以拥有一个 IJsonProperty 字段,您可以将其绑定到选定的 Item。

      那么你应该得到一个包含你的列表项的组合框,如果你选择其中一个,IJsonProerty 字段将设置为选定的项。

      我希望它可以理解,因为我现在还没有真正的代码 sn-p。

      【讨论】:

      • 不幸的是 SelectedItem="{Binding Path=SelectedParamJson, RelativeSource={RelativeSource AncestorType=DataGridRow}}" 对我不起作用
      • 好吧,如果绑定到数据网格行的对象上没有名为 SelectedParamJson 的属性,则它无法工作。所以你需要绑定到对象公开的东西,或者如果你有一个更全局的属性,那么你可能需要找到一个祖先,比如用户控件或窗口。再次,相对源正在查找 acestors 数据上下文中的公共属性,因此您需要弄清楚 SelectedParamJson 的定义位置以及哪个控件具有定义它的 vm。
      • DataGrid 有ItemsSource="{Binding PropertiesGrid}"。我相信 DataGridTemplateColumn 里面的 Comboxx 应该直接看到 SelectedParamJson,没有任何 AncestorType ...
      • 如果您的数据是 ParameterGrid 对象的集合,那么每个都是 ParameterGrid 反过来可以公开作为 Datagrid 单元格绑定(您的列定义)的公共属性,因此如果您绑定到作为 DataGridRow 的祖先应该有一个名为 SelectedParamJson 的公共属性,可以绑定到 Combobox 的 SelectedItem 属性。所以你的 ComboBox Itemsource 是 ParamsJson 并且你选择的 Item 是 SelectedParamJson
      • 是的,如果您已经在上下文中,则不需要查找祖先,因为 SelectedParamJson 应该在同一范围内
      猜你喜欢
      • 2014-09-12
      • 2021-03-29
      • 2011-02-28
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-10
      • 2011-05-06
      相关资源
      最近更新 更多