WPF DataGrid – DataGridComboBoxColumn v1 Intro


Intro


If you haven’t already, you can download the DataGrid v1 bits and source here.  DataGridComboBoxColumn has had a make-over since the CTP release.  In particular, the whole data binding story has been updated so that you can accomplish basic ComboBox tasks that before required some tedious workarounds.  While other stock columns such as DataGridTextColumn and DataGridCheckBoxColumn use Binding for the visual to data hook up, DataGridComboBoxColumn uses a different route with three possible ways to hook up a binding.  Here are the APIs that are specific to the DataGridComboBoxColumn:



public class DataGridComboBoxColumn : DataGridColumn


{


  public string DisplayMemberPath { get; set; }


  public IEnumerable ItemsSource { get; set; }


  public virtual BindingBase SelectedItemBinding { get; set; }


  public virtual BindingBase SelectedValueBinding { get; set; }


  public string SelectedValuePath { get; set; }     


  public virtual BindingBase TextBinding { get; set; }


}


 


The three mechanisms to hook up the binding are:


·         SelectedItemBinding


·         SelectedValueBinding


·         TextBinding


These three bindings basically map to the cell’s content being bound to ComboBox.SelectedItem, ComboBox.SelectedValue, or ComboBox.Text respectively.  SelectedValuePath and DisplayMemberPath are convenience methods on a ComboBox control and apply to ComboBox.SelectedValuePath and ComboBox.DisplayMemberBinding respectively.  Overall, you can think of these APIs as convenience methods that apply to the ComboBox element of the cell.  Let’s go through some use cases.


Some examples


When the column is bound to a primitive data type such as int, string, or bool, and you want the ComboBox to have a list of similar items to choose from, you can use SelectedItemBinding like so:



<dg:DataGridComboBoxColumn SelectedItemBinding=”{Binding ShipCity}”>


  <dg:DataGridComboBoxColumn.ItemsSource>


    <col:ArrayList>


      <sys:String>Redmond</sys:String>


      <sys:String>Bellevue</sys:String>


      <sys:String>Seattle</sys:String>


      <sys:String>Renton</sys:String>


    </col:ArrayList>


  </dg:DataGridComboBoxColumn.ItemsSource>


</dg:DataGridComboBoxColumn>


 


ShipCity is a string type so the ComboBox.SelectedItem maps correctly to the item in the DataGrid’s column. 


Let’s say I have a foreign key relationship between an Orders table and a Customers table.  Orders contains a CustomerID foreign key and will be the ItemsSource for the DataGrid.  I can setup a DataGridComboBoxColumn with Customers being its ItemsSource and hooking up the SelectedValueBinding like so:                                  



<dg:DataGridComboBoxColumn SelectedValueBinding=”{Binding CustomerID}”


  SelectedValuePath=”CustomerID”


  DisplayMemberPath=”ContactName”


  Header=”CustomerID (ContactName alias using SelectedValueBinding)”


  ItemsSource=”{Binding Source={StaticResource customerDataProvider}}”>


 


SelectedValueBinding maps to Orders’ CustomerID, which also maps to Customers’ CustomerID through SelectedValuePath.  I use DisplayMemberPath to alias the CustomerID with a more user friendly value to the end user. 


You can download the solution to these examples here.

DataGrid_V1_ComboBoxColumnSamples.zip

Comments (34)

  1. UPDATE: DataGridComboBoxColumn has been updated from CTP to V1. See the post here for the updates to

  2. UPDATE: DataGridComboBoxColumn has been updated from CTP to V1. See the post here for the updates to

  3. Ruler says:

    How do i get the values selected by user inside the datagrid?

    with the normal combobox i can do

    comboname.SelectedValue

  4. regev says:

    how do you handle with copy-paste in DataGridComboBoxColumn?

  5. Ruler,

    You can get the selected rows through DataGrid.SelectedItems and you can get the selected cells through DataGrid.SelectedCells.

  6. Peter says:

    Great stuff! Much better than some of the hoops you had to jump through with the CTP. Thanks!

  7. Sachet says:

    Can you please tell me how i can add autocomplete and autosuggest feature to the DataGridComboBoxColumn?

  8. Sachet,

    Try setting the EditingElementStyle in a DataGridComboBoxColumn,

    <dg:DataGridComboBoxColumn.EditingElementStyle>

                           <Style TargetType="ComboBox">

                               <Setter Property="IsEditable" Value="True" />

                           </Style>                    

    </dg:DataGridComboBoxColumn.EditingElementStyle>

  9. Sachet says:

    when i set the editing element style in DataGridComboBoxColumn, it only enable me to be able to type in to the combobox, it does not filter the items in the combobox to display only the items matching the text being typed… I have been able to get this done in a regular combobox using the code shown below. Could you please help me as to how i can get the same feature here in the DataGridComboBoxColumn, possibly by modifying the code below?

    Thank you.

    myComboBox.ItemsSource = myItemsList;

    myComboBox.IsEditable = true;

    myComboBox.IsTextSearchEnabled = false;

    myComboBox.Loaded += delegate

    {

       TextBox textBox = myComboBox.Template.FindName("PART_EditableTextBox", myComboBox) as TextBox;

       Popup popup = myComboBox.Template.FindName("PART_Popup", myComboBox) as Popup;

       if (textBox != null)

       {

           textBox.TextChanged += delegate

           {

               popup.IsOpen = true;

               myComboBox.Items.Filter += a =>

               {

                    myItems selectedItem = (myItems)a;

                    if (a.ToString().Contains(textBox.Text))

                    {

                         return true;

                    }

                    else

                    {

                         return false;

                    }

                };

           };

       }

    };

  10. Sachet,

    From the sample on this post, I was able to update the EditingElementStyle of the ComboBoxColumn and get the autocomplete support without having to write my own filter.  Maybe it’s something you are doing in your DataGridComboBoxColumn.  I suggest trying the sample on this post and diff’ing it with your implementation of DataGridComboBoxColumn.

  11. Sachet says:

    Thank you for replying so quickly, i have already downloaded your sample application. I even set the IsEditable property to true. But the problem is still the same, i.e. when i enter the text in to the combobox column the visible items in the dropdown box remain the same, whereas in the autocomplete combobox normally a popup would appear showing only the set of items that match the text entered by us. If you could use the following code and run the application, maybe you could understand me more clearly,

    //————–Window4.xaml————-

    <Window x:Class="WpfApplication1.Window4"

       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;

       xmlns:c="clr-namespace:DotNetZen.AutoFilteredComboBox"

       Title="AutoCompleteComboBoxDemo" Height="300" Width="300">

       <StackPanel>

           <ComboBox Height="30" Width="200" IsEditable="True" Name="comboBox">

               <TextBlock>Item type 1</TextBlock>

               <TextBlock>Item type 2</TextBlock>

               <TextBlock>Object class 1</TextBlock>

               <TextBlock>New Method</TextBlock>

           </ComboBox>        

       </StackPanel>

    </Window>

    //————————————–

    //———Window4.xaml.cs————–

    using System.Windows;

    using System.Windows.Controls;

    using System.Windows.Controls.Primitives;

    namespace WpfApplication1

    {

       /// <summary>

       /// Interaction logic for Window4.xaml

       /// </summary>

       public partial class Window4 : Window

       {

           public Window4()

           {

               InitializeComponent();

               comboBox.IsTextSearchEnabled = false;

               comboBox.Loaded += delegate

               {

                   TextBox textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;

                   Popup popup = comboBox.Template.FindName("PART_Popup", comboBox) as Popup;

                   if (textBox != null)

                   {

                       textBox.TextChanged += delegate

                       {

                           popup.IsOpen = true;

                           comboBox.Items.Filter += a =>

                           {

                               TextBlock b = (TextBlock)a;

                               if (b.Text.Contains(textBox.Text))

                               {

                                   return true;

                               }

                               return false;

                           };

                       };

                   }

               };

           }

       }

    }

    //———————–

    I wanted to emulate the features in the combobox above in the DataGridComboBoxCloumn. Could you kindly look at it and help me?

    Thank you

  12. Sachet,

    I’m still looking into why it’s not working for DataGridComboBoxColumn but I tested it out with DataGridTemplateColumn and it works just fine.  For the time being give DataGridTemplateColumn a try if you are in a rush.

  13. Sachet says:

    Could you please give me the code of the autocomplete sample that you found to be working using DataGridTemplateColumn.

    I used the method shown in the following blog post that i found yesterday,

    http://www.dev102.com/2008/08/07/how-to-access-a-wpf-control-which-is-located-in-a-datatemplate/

    It shows a method of accessing the Combobox that we define in the DataTemplate for DataGridTemplateColumn through code. Combining that method and the autocomplete combox sample that i showed above i was able to get autocomplete support.

    BUT now the problem is that when I type something into the combobox in any one row of the datagrid the dropdown boxes of the same combobox column in all rows open up at the same time.

    I need to find a way to reference the combobox in each row separately.

  14. Sachet says:

    Actually what i wanted to do is that I need a datagrid which would have initially only one blank row, the user should be able to add as many entries as he wishes. The datagrid consists of two columns, a combobox column and a Text box column. The combobox consists of a large no of items hence autosuggest, like the one seen in the Windows "Run" Dialog Window is required.

    Is this possible to be done with the datagrid or would i have to search for other controls like the ListView or maybe create a custom control???

    Thanks

  15. Sachet,

    Here is the code for the DataGridTemplateColumn support.  Also, the scenario that you describe is doable with the DataGrid.

    <dg:DataGridTemplateColumn Header="Cake TemplateColumn" >

                       <dg:DataGridTemplateColumn.CellTemplate>

                           <DataTemplate>

                               <TextBlock Text="{Binding Path=Cake, Mode=OneWay}"/>

                           </DataTemplate>

                       </dg:DataGridTemplateColumn.CellTemplate>

                       <dg:DataGridTemplateColumn.CellEditingTemplate>

                           <DataTemplate>

                               <ComboBox IsEditable="True"

                                         IsTextSearchEnabled="False"

                                         Loaded="ComboBoxLoaded"

                                         SelectedItem="{Binding Path=Cake, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">

                                   <ComboBox.ItemsSource>

                                       <col:ArrayList>

                                           <sys:String>Chocolate</sys:String>

                                           <sys:String>Vanilla</sys:String>

                                           <sys:String>Strawberry</sys:String>

                                           <sys:String>Cookie</sys:String>

                                           <sys:String>Pound Cake</sys:String>

                                       </col:ArrayList>

                                   </ComboBox.ItemsSource>

                               </ComboBox>

                           </DataTemplate>

                       </dg:DataGridTemplateColumn.CellEditingTemplate>

                   </dg:DataGridTemplateColumn>

    private void ComboBoxLoaded(object sender, RoutedEventArgs e)

           {

               ComboBox comboBox = sender as ComboBox;

               TextBox textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;

               if (textBox != null)

               {

                   textBox.TextChanged += (s, args) =>

                       {

                           comboBox.IsDropDownOpen = true;

                           comboBox.Items.Filter += a =>

                           {

                               string value = (string)a;

                               if (value.Contains(textBox.Text))

                               {

                                   return true;

                               }

                               return false;

                           };

                       };

               }

           }

  16. Sachet says:

    Hi,

    I tried the code you gave above… It is certainly giving Autosuggest feature but did you notice that when there are multiple rows of data in the datagrid, the value selected in the combobox of one particular row automatically becomes the selected value of comboboxes of all the rows…

    how is it possible to refer to the selected values of the combobox column of each row separately?

    thanks

  17. BRanck says:

    Hi Vince,

    I am loading the WPF datagrid V1 from a text File using a data adapter to read the file. Prior to loading I build a Schema.ini (that includes column header text and other column definitions) and save it next to the text file in its directory.  

    This all works fine.

    However, once I am done with the text file, I need to load a different text file (with the same name) that now has new and different data.

    My problem is that I cannot figure out how to clear or reset the data grid.  The new data loads just fine but the Headers are now repeated in the grid with a number 1 after each of the duplicate header names. If I do it a third time, I have yet another set of headers (and I presume columns) now with the column name and a 2.

    So could you point me to a way to Reset or Clear the WPF DataGrid, or perhaps remove the old columns prior to loading the second time? I would prefer to do it in VB code behind. I tried looping in the grids columns colection without success so far.

  18. Senthil says:

    I want to display hierarchical data in the datagrid. First column is Categorys datacombobox column and the second column is the subcategories datacombobox column. Based on the first selection column the second column combobox need to be populated. How to do this in the datagrid. I searched so many articals and somany websites regarding this issue. Still I am searching for this. Could u help me in this regard.

    Category table columns: id and name

    subcategorys table columns: id , name and cateogry_id

    I need to store in the table all the id values only. Please help.

  19. Here’s another DataGrid sample using the WPF Toolkit .&#160; It includes Creating templates for DataGridTemplateColumn

  20. Neo says:

    Is there a way to dynamically set the value for a SelectedIndex in Datagrid tag? Txs

    <dg:DataGrid SelectedIndex=""

  21. Neo,

    Try setting up a data binding.

    <dg:DataGrid SelectedIndex="{Binding Path=<some property>}"

  22. Peter says:

    Vincent, could you please give me a hint how I could use the text that is displayed in the DataGridComboBoxColumn inside the RowDetailsTemplate? As I only have an ID (int) at hand I would like to display the text in a TextBlock in the RowDetailsTemplate too. How can I bind them together?

    TIA,

    Peter

  23. Peter,

    I don’t think you can bind the textblock in the RowDetailsTemplate to the ComboBox in the cell.  Maybe you can do something similar like the ComboBox.  Pass the RowDetailsTemplate the binding for the ID and the other data to show a different display value.

  24. Ramesh says:

    hi,

    i have datagride inside combo that combo did’t binding anybody help me

    Advance wishes

  25. Mike Graham says:

    Ha !!  Figured it out 🙂

    I couldn’t figure out why my code didn’t work and yours did…  Here it is if anyone else is interested…

    I was using this class for my list of items in the combo:

       public class ModeComboItem

       {

           public string SyncModeValue;

           public string SyncModeText;

       }

    but needed to be using this class instead !!

       public class ModeComboItem

       {

           public string SyncModeValue { get; set; }

           public string SyncModeText { get; set; }

       }

    small change…  big improvement 🙂

  26. Md Rasool says:

    plz tell me how to select the iten present in comboboxcolumn wpf datagrid

  27. Bhargav Joshi says:

    I am trying to add a tooltip to a DataGridComboBoxColumn cell. I am able to display the tooltip in editing mode by setting EditingElementStyle. However, when I set the ElementStyle with target type TextBlock it throws an exception saying that the type TextBlock does not match TextBlockComboBox. Also, I am not able to find the type TextBlockComboBox as a public type in the toolkit.

    Please help! Thanks

  28. Frank says:

    I am binding the DataContext of a DataGrid to a class that contains an ObservableCollection of properties in XAML. Then, I create each column programmatically in C# and bind them to each specific property.

    How can you make each row’s DataGridComboBoxColumn ItemsSource bind to a different array?

  29. Santhosh says:

    Hi Vince,

    How to reset or clear the contents of the datagrid?

    Also, at initialization, I need to display 4 empty rows which the user may subsequently populate with data. How to display empty rows in datagrid?

    Thanks,

  30. Santhosh,

    To clear content you can just clear your items source that the DataGrid is bound to.  For adding four empty rows, you can add four items with default initialization.  

  31. Abhishek says:

    How can I create a combobox in a datagrid column in the C# code class through get-set property.

    I could manage to create check box in grid view column through get -set property code.(WPF)

    Like, the code below brings a check box on front end datagrid column at run time.And works well with the data integration too.

    public bool Enabled

           {

               get

               {

                   if (this._sublocation.Enabled > 0)

                       return true;

                   else

                       return false;

               }

               set

               {

                   if (value == true && this._sublocation.Enabled < 1)

                       this._sublocation.Enabled = 1;

                   else if (value == false && this._sublocation.Enabled > 0)

                       this._sublocation.Enabled = 0;

                   else

                       return;

                   base.OnPropertyChanged("Enabled");

               }

           }

  32. ivan_ says:

    vinsibal,

    Why SelectedItems property is not a Dependency Property?

    How can I bind it to ViewModel?

    Do I have to create AttachedProperty for that?

    Thanks,

    Ivan

Skip to main content