Christian St.
Christian St.

Reputation: 1911

Update DataGrid's ItemsSource on SelectionChanged event of a ComboBox

I subscribed to a SelectionChangedEvent on a ComboBox in a DataGrid with the following code:

public static DataGridTemplateColumn CreateComboboxColumn(string colName, Binding textBinding, SelectionChangedEventHandler selChangedHandler = null)
{
    var cboColumn = new DataGridTemplateColumn {Header = colName};
...
    if (selChangedHandler != null)
        cboFactory.AddHandler(Selector.SelectionChangedEvent, selChangedHandler);
...
    return cboColumn;
}

The handler I actually register contains:

private void ComboBoxSelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
    Console.WriteLine(@"selectHandler");
    var cboBox = sender as ComboBox;
    if (cboBox == null)
        return;

    if (cboBox.IsDropDownOpen) // a selection in combobox was made
    {
        CommitEdit();
    }
    else // trigger the combobox to show its list
        cboBox.IsDropDownOpen = true;
}

... and is located in my custom DataGrid class.

If I select an item in the ComboBox, e.AddedItems and cboBox.SelectedItem contains the selected value, but nothing is changed on CommitEdit().

What I want is to force a commit to directly update the DataGrid's ItemsSource, when the user selects an item in the drop-down-list. Normally this is raised if the control looses focus...

The link in the solution found in this thread is not available any more and I don't know how to use this code.

Upvotes: 1

Views: 1538

Answers (1)

Christian St.
Christian St.

Reputation: 1911

I created a tricky, but working, solution for my problem. Here's the modified handler from above:

private void ComboBoxSelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
    Console.WriteLine(@"selectHandler");
    var cboBox = sender as ComboBox;
    if (cboBox == null)
        return;

    if (cboBox.IsDropDownOpen) // a selection in combobox was made
    {
        cboBox.Text = cboBox.SelectedValue as string;
        cboBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right));
    }
    else // user wants to open the combobox
        cboBox.IsDropDownOpen = true;
}

Because my ComboBoxColumn is a custom DataGridTemplateColumn I force it to show its list, when the user first selects the cell.

To change the bound items value I manually overwrite the displayed text with recently selected item and force the UI to select another item (in this case the control to the right) to make an implicit call to CellEditEnding event, which (in my case) commits the whole row:

private bool _isManualEditCommit = false;
private void _CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    // commit a manual edit
    // this if-clause prevents double execution of the EditEnding event
    if (!_isManualEditCommit)
    {   
        Console.WriteLine(@"_CellEditEnding() manualeditcommit");
        _isManualEditCommit = true;
        CommitEdit(DataGridEditingUnit.Row, true);
        _isManualEditCommit = false;
        checkRow(e.Row);
    }
}

Maybe I could help somebody with this "dirty" solution ;-)

Upvotes: 1

Related Questions