3
votes

I have agrid which has three columns :

  1. Friendly Name
  2. Continent Name
  3. Country Name

The 1st column is a textbox column Editable. The second column is a Combobox that displays the list of continents. The 3rd column is a combobox which displays list of countries based on the continent selected in the 2nd column. I want to implement single click for these column. I tried the solution given in this link Single click edit in WPF DataGrid

But that only works on the first column and not the other two (DataGridTemplateColumn) columns.

How is this possible. Please suggest. The sample XAML and data description is given below.

<DataGrid Grid.Row="1" VerticalAlignment="Top"
                                   ItemsSource="{Binding Path=GeographyData,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                  Style="{StaticResource DataGridStyleNormal}">
                            <DataGrid.Columns>
                                <DataGridTextColumn Width="*" Header="Friendly name" Binding="{Binding Path=FriendlyName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                                <!--FilterDef -->
                                <DataGridTemplateColumn Width="*"
                                                        Header="Continents">
                                    <DataGridTemplateColumn.CellEditingTemplate>
                                        <DataTemplate>
                                            <ComboBox SelectedValue="{Binding ContinentId, Mode=TwoWay}"
                                                      SelectedValuePath="ID"
                                                      DisplayMemberPath="Name"
                                                      ItemsSource="{Binding Path=DataContext.ContinentsAndCountries,Mode=OneWay,UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"/>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellEditingTemplate>
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <TextBlock>
                                               <TextBlock.Text>
                                                    <MultiBinding Converter="{StaticResource ContinentCaptionConverter}">
                                                          <Binding Path="ContinentId"/>
                                                          <Binding Path="DataContext.ContinentsAndCountries" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}"/>
                                                        </MultiBinding>
                                                </TextBlock.Text>
                                            </TextBlock>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                                <!--Level-->
                                <DataGridTemplateColumn Width="*"
                                                        Header="Countries">
                                    <DataGridTemplateColumn.CellEditingTemplate>
                                        <DataTemplate>
                                            <ComboBox SelectedValue="{Binding CountryId, Mode=TwoWay}"
                                                      SelectedValuePath="ID"
                                                      DisplayMemberPath="Name">
                                                <ComboBox.ItemsSource>
                                                    <MultiBinding Converter="{StaticResource CountryValuesConverter}">
                                                        <Binding Path="DataContext.ContinentsAndCountries" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}"/>
                                                        <Binding Path="ContinentId"/>
                                                    </MultiBinding>
                                                </ComboBox.ItemsSource>
                                            </ComboBox>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellEditingTemplate>
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <TextBlock>
                                               <TextBlock.Text>
                                                    <MultiBinding Converter="{StaticResource CountryCaptionConverter}">
                                                            <Binding Path="DataContext.ContinentsAndCountries" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}"/>
                                                            <Binding Path="ContinentId"/>
                                                            <Binding Path="CountryId"/>
                                                        </MultiBinding>
                                                </TextBlock.Text>
                                            </TextBlock>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                            </DataGrid.Columns>
                        </DataGrid>

Note : The data "ContinentsAndCountries" is an observable collection of master detail data.

  • Girija
2
Maybe this answer helps you.LPL
Doesnot work. I guess it does the same thing as in this link stackoverflow.com/questions/3426765/…Shankar
I Did this by setting the combobox Loaded Event private void Combobox_Loaded(object sender, RoutedEventArgs e) { if (sender != null) { ComboBox cmb = sender as ComboBox; cmb.IsDropDownOpen = true; } }Shankar
Fine. Then post it as an answer and accept it.LPL

2 Answers

5
votes

I Did this by setting the combobox Loaded Event

private void DataGridComboboxTemplate_Loaded(object sender, RoutedEventArgs e)
    {
        if (sender != null)
        {
            ComboBox cmb = sender as ComboBox;
            cmb.IsDropDownOpen = true;
        }
    }
1
votes

Sorry for he necro; I've finally figured out how to make a truly single-click UX. You have to intercept the DataGridCell's OnGotFocus event, set the cell's mode to IsEditing, then intercept the Loaded event for the actor control in your CellEditingTemplate:

<Window.Resources>
    <Style
        x:Key="AutoEditModeOnClick"
        TargetType="{x:Type DataGridCell}">

        <EventSetter Event="GotFocus" Handler="DataGridCell_OnGotFocus" />
    </Style>
</Window.Resources>

<DataGrid.Columns>
    <DataGridTemplateColumn
        CellStyle="{StaticResource AutoEditModeOnClick}"
        Header="Score">

        <!-- Example with ComboBox -->

        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <!-- Some more XAML -->
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>

        <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
                <!-- Some more XAML -->
                <ComboBox
                    DisplayMemberPath="Description"
                    SelectedValuePath="RecordID"
                    SelectedValue="{Binding Score,
                        TargetNullValue=0,
                        UpdateSourceTrigger=PropertyChanged}"
                    ItemsSource="{Binding DataContext.ScoreOptions,
                        RelativeSource={RelativeSource
                            AncestorType={x:Type DataGrid}}}"
                    Loaded="Combobox_Loaded"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>

    <DataGridTemplateColumn
        CellStyle="{StaticResource AutoEditModeOnClick}"
        Header="Comment">

        <!-- Example with TextBox -->

        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <!-- Some more XAML -->
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>

        <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
                <!-- Some more XAML -->
                <TextBox
                    Loaded="TextBox_Loaded"
                    Text="{Binding Comment,
                        UpdateSourceTrigger=LostFocus}"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

In your code-behind, you need three handlers; one for the cell, and one for each type of control (ComboBox, TextBox):

    /// <summary>
    /// Skips the 'DataGridCell.Focus' step and goes straight into IsEditing
    /// </summary>
    private void DataGridCell_OnGotFocus(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        cell.IsEditing = true;
    }

    /// <summary>
    /// Skips the 'IsEditing' step and goes straight into IsDropDownOpen
    /// </summary>
    private void Combobox_Loaded(object sender, RoutedEventArgs e)
    {
        ComboBox comboBox = sender as ComboBox;
        comboBox.IsDropDownOpen = true;
    }

    /// <summary>
    /// Skips the 'IsEditing' step and goes straight into Focus
    /// </summary>
    private void TextBox_Loaded(object sender, RoutedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        textBox.Focus();
    }