0
votes

I have a DataGrid with 3 column inside: Name -DataGridTextColumn, Value-DataGridTextColumn, ParamJson - DataGridTemplateColumn with combobox and has a ICollectionView of ParameterGrid as a source.

There is a ViewModel that provides ICollectionView of ParameterGrid. ParameterGrid contains 4 parameters: Name, Value, ParamJson, SelectedParamJson.

I need to handle all rows of DataGrid, so i use the command that get all dataGrid as a Command Parameter and than iterate over DataGrid.Items (I could use directly ICollectionView?).

The question is How to bind properly SelectedItem in Combobox in DataGrid to 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 >`

ViewModel

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; }
}
3

3 Answers

1
votes

If you want to bind to the SelectedParamJson property that is defined in the same class as the ParamsJson property, you should not set the RelativeSource property to anything at all:

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

You should also move the ComboBox to the CellEditingTemplate of the DataGridTemplateColumn.

1
votes

The thing is you have to define <DataGridTemplateColumn.CellEditingTemplate>, where you should do all bindings and <DataGridTemplateColumn.CellTemplate>, that present value when the cell is not active.

That seems to be strange that you could not bind everything inside <DataGridTemplateColumn.CellTemplate>, because you have to do an additional klick to activate combobox.

Xaml that works for me:

    <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>
0
votes

your ancestor is not the datagrid its the datarow you want to get the datacontext from.

so you made a collection view of some source collection like list, this means every row in your Datagrid repesents a IJsonObject Object and there you should have your Collection for the ComboBox Column defined. Like a List that you can bind to the Column and in Turn you can have a IJsonProperty field that you can bind to the selected Item.

So then you should get a Combobox filled with yout List Items and if you select one of them the IJsonProerty Field will be set to the selected Item.

I hope its understandable since I dont really got a code snippet right now.