Editable ComboBox with XCeed DataGrid
I’ve recently started using XCeed’s DataGrid for WPF instead of he WPF toolkit DataGrid because overall it seems to have more features. One of the problems which I couldn’t find any reference to was using editable comboboxes when editing an item. I’m using an ObjectDataProvider as the ItemsSource for a ComboBox, but I wanted to let a user type a value as well as select one from the list.
The solution I eventually used lets a user add an item to the list of items which can then be selected when editing other items in the DataGrid.
Once you’ve declared the ObjectDataProvider in XAML, you need a CellEditor template for the column which will use the ComboBox (code below).
<xcdg:Column.CellEditor> <xcdg:CellEditor> <xcdg:CellEditor.EditTemplate> <DataTemplate> <ComboBox x:Name="cboMeasurement" IsVisibleChanged="cbo_IsVisibleChanged" ItemsSource="{Binding Collection,Source={StaticResource measurementProvider}}" SelectedValue="{xcdg:CellEditorBinding}" IsEditable="True" Foreground="Black" IsSynchronizedWithCurrentItem="True" /> </DataTemplate> </xcdg:CellEditor.EditTemplate> </xcdg:CellEditor> </xcdg:Column.CellEditor>
In my example, measurementProvider is an ObjectDataProvider bound to a wrapper class containing a list of objects (of class Ingredient) in the Collection property. The event which adds a new item to the data source fires when the ComboBox loses visibility (because the row is exiting edit mode), then the new item is added with:
/// <summary> /// Adds a new measurement to the list of available measurements when a new value is typed. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private void cbo_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { ComboBox cbo = sender as ComboBox; if(cbo != null && !Measurements.Contains(cbo.Text)) { string itm = cbo.Text.Trim(); Measurements.Add(itm); Ingredient currentIngredient = dgIngredients.CurrentItem as Ingredient; if(currentIngredient != null) { currentIngredient.Measurement = itm; } } }
Update 27th September 2009: This method introduces a bug with XCeed’s control which means that the first time a row is edited, the change from the ComboBox is not saved. For some reason, the ComboBox is not null, but it’s Text property is null.
After spending hours trying to start, then cancel an edit, cancelling edits and virtually everything else I used the following (hacky) solution.
private bool firstEdit = true; private void InsertionRow_Loaded(object sender, RoutedEventArgs e) { insertionRow = sender as BetterInsertionRow; } /// <summary> /// Adds a new measurement to the list of available measurements when a new value is typed. /// </summary> private void cbo_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { if(firstEdit) { firstEdit = false; return; } ComboBox cbo = sender as ComboBox; if(cbo != null && !Measurements.Contains(cbo.Text)) { string itm = cbo.Text.Trim(); Measurements.Add(itm); Ingredient currentIngredient; if(dgIngredients.CurrentItem != null) { // row being edited currentIngredient = dgIngredients.CurrentItem as Ingredient; } else { // insertionrow is in focus (new item being added) currentIngredient = insertionRow.DataContext as Ingredient; } if(currentIngredient != null) { currentIngredient.Measurement = itm; } } }
This still doesn’t fix the problem, and seems to work intermittently, though it’s better than the default behaviour. The consequence is that the first time a row is edited, if a new item is added to the list, it’s not saved due to the text still being empty. Subsequent edits seem to work.

Comments
Leave a Comment