Click here to Skip to main content
Click here to Skip to main content

WPF Custom ComboBox

, 15 Oct 2009
Rate this:
Please Sign up or sign in to vote.
WPF ComboBox with DataGrid popup

Introduction

This article presents a custom ComboBox with popup DataGrid. Instead of a simple list box control, the control shows a popup with fully featured WPF ToolKit DataGrid. You can find several sites and forums that discuss how you can implement custom combobox with DataGrid or ListView popup control. This article shows how such a control can be implemented in Windows application as well as CustomDataGridComboBox column in DataGrid. CustomComboBox control derived from ComboBox with some additional properties. With these properties, you can easily implement DataGrid columns in popup control.

Using WPF Custom ComboBox Control

Firstly, we are presenting the usage of the CustComboBox in Windows application. The following XAML code shows the implementation of the control. The control is bounded to some DataSource, with specified DisplayMemberPath. After defining datasource, columns of DataGrid popup are defined as a content of CustComboBox.

<local:CustComboBox Height="23" ItemsSource="
	{Binding Collection}" DisplayMemberPath="Property1" 
	IsEditable="True" >

	<toolKit:DataGridTextColumn Header="Header 1" 
		Binding="{Binding Property1, Mode=Default}" />
	<toolKit:DataGridTextColumn Header="Header 2" 
		Binding="{Binding Property2, Mode=Default}"/>
	<toolKit:DataGridTextColumn Header="Header 3" 
		Binding="{Binding Property3, Mode=Default}"/>

</local:CustComboBox>

Except DataGrid columns' definition as Content, the control is the same as the ordinary ComboBox control. All features of the ComboBox are also available in the control.

Implementation of CustComboBox Class

Code-Behind Class Implementation

The CustComboBox is a custom WPF control derived from ComboBox. CustComboBox class is decorated with ContentPropertyAttribute which means the columns of the control can be defined as a content. The class contains the following fields:

  • partPopupDatagrid – Part name of the popupDataGrid used in XAML part implementation
  • columns- Collection of DataGrid columns
  • popupDataGrid DataGrid popup control

and readonly Columns property:

[DefaultProperty("Columns")]
[ContentProperty("Columns")]
public class CustComboBox : ComboBox
{
   private const string partPopupDataGrid = "PART_PopupDataGrid";
   private ObservableCollection<datagridtextcolumn /> columns;
   private DataGrid popupDataGrid;

   static CustComboBox()
    {
       DefaultStyleKeyProperty.OverrideMetadata(typeof(CustComboBox), 
       	new FrameworkPropertyMetadata(typeof(CustComboBox)));
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public ObservableCollection<datagridtextcolumn /> Columns
    {
       get
        {
         if (this.columns == null)
         {
           this.columns = new ObservableCollection<datagridtextcolumn />();
         }
         return this.columns;
        }
    }

The main part of the code-behind class implementation is virtual member OnApplyTemplate. This method connects popup control with DataGrid and columns. First, find the template part of the DataGrid popup control, define the columns, and implement some events for managing selection in DataGrid popup.

public override void OnApplyTemplate()
    {
       if (popupDataGrid == null)
         {    
           popupDataGrid = this.Template.FindName(partPopupDataGrid, this) as DataGrid;
           if (popupDataGrid != null && columns != null)
           {
             for (int i = 0; i < columns.Count; i++)
               popupDataGrid.Columns.Add(columns[i]);

             popupDataGrid.PreviewMouseDown += 
             	new MouseButtonEventHandler(popupDataGrid_PreviewMouseDown);
             popupDataGrid.SelectionChanged += 
             	new SelectionChangedEventHandler(popupDataGrid_SelectionChanged);
           }
        }
        base.OnApplyTemplate();
    }

Code-Behind Class Implementation

Every WPF custom control can be implemented in XAML, where we defined Template and Style of the custom control. The style and template of our control is almost the same as an ordinary ComboBox control, except a ScrollViewer where it replaced is with DataGrid. The following XAML shows part of the implementation:

<Popup x:Name="PART_Popup" AllowsTransparency="true" 
	IsOpen="{Binding IsDropDownOpen, 
	RelativeSource={RelativeSource TemplatedParent}}" 
	Placement="Bottom" PopupAnimation="{DynamicResource 
		{x:Static SystemParameters.ComboBoxPopupAnimationKey}}" 
		Grid.ColumnSpan="2">
<Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw"
	MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding
	ActualWidth, ElementName=Placement}" Color="Transparent">
<Border x:Name="DropDownBorder" Background="{DynamicResource {x:Static
	SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static
	SystemColors.WindowFrameBrushKey}}" BorderThickness="1">

<toolKit:DataGrid x:Name="PART_PopupDataGrid" 
	ItemsSource="{TemplateBinding ItemsSource}" 
	AutoGenerateColumns="False" IsReadOnly="True" 
	IsSynchronizedWithCurrentItem="True" 
	SelectionMode="Single" HeadersVisibility="Column" 
	SelectedIndex="{TemplateBinding SelectedIndex}" 
	DisplayMemberPath="{TemplateBinding DisplayMemberPath}" 
	Focusable="False" SelectedItem="{TemplateBinding SelectedItem}" 
	SelectedValue="{TemplateBinding SelectedValue}" 
	SelectedValuePath="{TemplateBinding SelectedValuePath}" 
	RowDetailsVisibilityMode="Collapsed" Tag="{TemplateBinding Tag}" 
	MaxHeight="{TemplateBinding MaxDropDownHeight}" 
	IsTextSearchEnabled="{TemplateBinding IsTextSearchEnabled}" 
	CanUserSortColumns="True">
</toolKit:DataGrid>
</Border>
</Microsoft_Windows_Themes:SystemDropShadowChrome>
</Popup>

Bold code is an implementation of the DataGrid as a popup control. The next phase in the implementation is the selection and closing popup when selecting an item. In code–behind, we implemented SelectionChangedEventHandler and PreviewMouseDown events to control selection and closing popup.

CustComboBox Control as a DataGrid Column Control

Sample Image - maximum width is 600 pixels

The second part of the article presents the control integrated into DataGrid column controls. The new column control DataGridCustComboBoxColumn is an extended control of the DataGridComboBoxColumn. The following code snippet show the implementation:

[DefaultProperty("Columns")]
[ContentProperty("Columns")]
public class CustDataGridComboBoxColumn : DataGridComboBoxColumn
  {
    //Columns of DataGrid
    private ObservableCollection<datagridtextcolumn /> columns;
    //Cust Combobox  cell edit
    private  CustComboBox comboBox ;
      
    public CustDataGridComboBoxColumn();
        
    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e);

   //The property is default and Content property for CustComboBox
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
   public ObservableCollection<datagridtextcolumn /> Columns;

   protected override FrameworkElement GenerateEditingElement
	(DataGridCell cell, object dataItem);

   protected override object PrepareCellForEdit
	(FrameworkElement editingElement, RoutedEventArgs editingEventArgs);

   protected override bool CommitCellEdit(FrameworkElement editingElement);
 }

Similar to the previous implementation, we have Columns as a Content property to setup columns in popup control. To get control to appear in DataGrid, the three methods of the base class were overridden:

  • GenerateEditingElement
  • PrepareCellForEdit
  • CommitCellEdit

Using CustDataGridComboBoxColumn Control

The following code example shows how to define CustDataGridComboBoxColumn into WPF DataGrid.

<toolKit:DataGrid Name="ordersDataGrid" IsSynchronizedWithCurrentItem="
	True" ItemsSource="{Binding Source={StaticResource ordersViewSource}}" 
					AutoGenerateColumns="False" RowHeight="25" 
					Margin="6,6,6,35">

	<toolKit:DataGrid.Columns>
		<bhCustCtrl:CustDataGridComboBoxColumn x:Name="custComboBoxCol" 
		Width="150" Header="Customers" 
		SelectedValueBinding="{Binding CustomerID}"
		SelectedValuePath="CustomerID" DisplayMemberPath="ContactName"
		ItemsSource="{Binding Source={StaticResource customerViewSource}}">

			<toolKit:DataGridTextColumn Header="ContactName" 
				Binding="{Binding ContactName, Mode=Default}" />
			<toolKit:DataGridTextColumn Header="CompanyName" 
				Binding="{Binding CompanyName, Mode=Default}" />

		</bhCustCtrl:CustDataGridComboBoxColumn>	

		<bhCustCtrl:CustDataGridComboBoxColumn x:Name="emplComboBoxCol" 
		Width="150" Header="Employees" 
		SelectedValueBinding="{Binding EmployeeID}"
		SelectedValuePath="EmployeeID" DisplayMemberPath="FirstName"
		ItemsSource="{Binding Source={StaticResource employeeViewSource}}">

			<toolKit:DataGridTextColumn Header="FirstName" 
				Binding="{Binding FirstName, Mode=Default}" />
			<toolKit:DataGridTextColumn Header="LastName" 
				Binding="{Binding LastName, Mode=Default}" />
		</bhCustCtrl:CustDataGridComboBoxColumn>

		<toolKit:DataGridTextColumn Width="100" Header="
			OrderDate" Binding="{Binding Path=OrderDate}"/>
		<toolKit:DataGridTextColumn Width="100" Header="
			ShipName" Binding="{Binding Path=ShipName}"/>
		<toolKit:DataGridTextColumn Width="100" Header="
			ShipAddress" Binding="{Binding Path=ShipAddress}" />
		<toolKit:DataGridTextColumn Width="100" Header="
			ShipCity" Binding="{Binding Path=ShipCity}" />
	</toolKit:DataGrid.Columns>
</toolKit:DataGrid> 

That's all!

About the Demo

The demo application uses the NorthWind database to present some data. You can find it on this site.

History

  • 14/10/2009: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Bahrudin Hrnjica
Software Developer (Senior)
Bosnia And Herzegovina Bosnia And Herzegovina
Senior Software Developer at daenet.eu and Microsoft MVP for Visual C#.
Follow on   Twitter   Google+

Comments and Discussions

 
Questionworks great except for one problem PinmemberMember 915347927-May-14 8:08 
QuestionDataRowView Problem Pinmembersharathgt28-Apr-14 18:13 
GeneralAwesome Article Pinmemberyashdeepsahni21-Feb-14 10:42 
GeneralVery nice control: ported succesfully to .NET Framework 4.5 Pinmemberpgmo186913-Feb-14 6:12 
GeneralMy vote is 5 PinmemberGiang Son9-Sep-13 15:27 
QuestionIs it possible to redevelop your project in Visual Studio 2010 (without toolkit) to successful use the control in .NET Framework 4.0 applications? PinmemberEugene_Buzin4-Jul-13 3:36 
AnswerRe: Is it possible to redevelop your project in Visual Studio 2010 (without toolkit) to successful use the control in .NET Framework 4.0 applications? [modified] PinmemberBahrudin Hrnjica4-Jul-13 19:49 
QuestionThank you very much Pinmembersvasudevan18-Jan-13 11:56 
QuestionpopupDataGrid is null OnDropDownOpened when ItemsSource Bound to an ObservableCollection PinmemberTom Chien20-Sep-12 10:43 
QuestionSource cannot open in visual studio 2010 Pinmemberkishor N Mali15-Jun-12 2:15 
AnswerRe: Source cannot open in visual studio 2010 PinmemberSerge Desmedt24-Aug-12 22:37 
QuestionHow to add Checkbox columns into control? Pinmemberxqandpan16-Jan-12 20:12 
GeneralI need to display multi select and multi column combobox. Can I add checkbox column with your control? PinmemberA. Raees15-Jun-11 22:16 
QuestionHow can i Make this Dropdown become Editable ? PinmemberGopi.V8-Oct-10 4:11 
AnswerRe: How can i Make this Dropdown become Editable ? PinmemberBahrudin Hrnjica4-Jul-13 19:59 
GeneralWPF Custom ComboBox PinmemberLearning_abc16-Sep-10 5:09 
GeneralRe: WPF Custom ComboBox PinmemberBahrudin Hrnjica16-Sep-10 7:40 
GeneralRe: WPF Custom ComboBox PinmemberLearning_abc16-Sep-10 9:11 
GeneralRe: WPF Custom ComboBox PinmemberLearning_abc12-Nov-10 10:35 
GeneralHI PinmemberRavenet16-Oct-09 0:08 
GeneralRe: HI PinmemberBahrudin Hrnjica16-Oct-09 2:03 
GeneralRe: HI PinmemberRavenet16-Oct-09 3:34 
GeneralInteresantna kontrola Bahrudine Pinmemberzirexba15-Oct-09 22:23 
GeneralRe: Interesantna kontrola Bahrudine PinmemberBahrudin Hrnjica16-Oct-09 1:58 
GeneralOpenExpressApp Pinmemberzhoujingen15-Oct-09 16:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 15 Oct 2009
Article Copyright 2009 by Bahrudin Hrnjica
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid