title: WPF ComboBox with checkboxes and textbox with search field
body: <p>I have gone through this thread </p>
  
  <p><a href="https://stackoverflow.com/questions/859227/looking-for-a-wpf-combobox-with-checkboxes">Looking for a WPF ComboBox with checkboxes</a>
  and tried to include <code>TextBox</code> in the <code>DataTemplate</code> but not able to view the <code>TextBox</code> on running the application. I have created a <code>UserControl</code> as follows</p>
  
  <pre><code>&lt;UserControl x:Class="MyProj.UserControls.MultiSelectComboBox"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
           mc:Ignorable="d" 
           d:DesignHeight="300" d:DesignWidth="300"&gt;
  &lt;ComboBox
      x:Name="MultiSelectCombo"  
      SnapsToDevicePixels="True"
      OverridesDefaultStyle="True"
      ScrollViewer.HorizontalScrollBarVisibility="Auto"
      ScrollViewer.VerticalScrollBarVisibility="Auto"
      ScrollViewer.CanContentScroll="True"
      IsSynchronizedWithCurrentItem="True"
                         &gt;
      &lt;ComboBox.ItemTemplate&gt;
          &lt;DataTemplate&gt;
              &lt;StackPanel Orientation="Horizontal"&gt;
                **&lt;TextBlock Text="{Binding Text, Mode=TwoWay}" Tag="{RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}"
                     Width="100" /&gt;**
                  &lt;CheckBox Content="{Binding Text}"
                        IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"
                        Tag="{RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}"
                         Click="CheckBox_Click" Width="20"          /&gt;
              &lt;/StackPanel&gt;
          &lt;/DataTemplate&gt;
      &lt;/ComboBox.ItemTemplate&gt;
      &lt;ComboBox.Template&gt;
          &lt;ControlTemplate TargetType="ComboBox"&gt;
              &lt;Grid &gt;
  
                  &lt;ToggleButton 
                      x:Name="ToggleButton" 
                     Grid.Column="2" IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
                      Focusable="false"                           
                      ClickMode="Press" HorizontalContentAlignment="Left" &gt;
                      &lt;ToggleButton.Template&gt;
                          &lt;ControlTemplate&gt;
                              &lt;Grid&gt;
                                  &lt;Grid.ColumnDefinitions&gt;
                                      &lt;ColumnDefinition Width="*"/&gt;
                                      &lt;ColumnDefinition Width="18"/&gt;
                                  &lt;/Grid.ColumnDefinitions&gt;
                                  &lt;Border
                x:Name="Border" 
                Grid.ColumnSpan="2"
                CornerRadius="2"
                Background="White"
                BorderBrush="Silver"
                BorderThickness="1,1,1,1" /&gt;
                                  &lt;Border 
                  x:Name="BorderComp" 
                Grid.Column="0"
                CornerRadius="2" 
                Margin="1" 
               Background="White"
                BorderBrush="Black"
                BorderThickness="0,0,0,0" &gt;
                                      &lt;TextBlock Text="{Binding Path=Text,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" 
                                             Background="White" Padding="3" /&gt;
                                  &lt;/Border&gt;
                                  &lt;Path 
                x:Name="Arrow"
                Grid.Column="1"     
                Fill="Black"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Data="M 0 0 L 4 4 L 8 0 Z"/&gt;
                              &lt;/Grid&gt;
                          &lt;/ControlTemplate&gt;
                      &lt;/ToggleButton.Template&gt;
                  &lt;/ToggleButton&gt;
                  &lt;Popup 
                      Name="Popup"
                      Placement="Bottom"                        
                      AllowsTransparency="True" 
                      Focusable="False"  IsOpen="{TemplateBinding IsDropDownOpen}"
                      PopupAnimation="Slide"&gt;
                      &lt;Grid 
                                Name="DropDown"
                                SnapsToDevicePixels="True"  
                          MinWidth="{TemplateBinding ActualWidth}"
                                MaxHeight="{TemplateBinding MaxDropDownHeight}"&gt;
                          &lt;Border 
                                  x:Name="DropDownBorder"
                                 BorderThickness="1" Background="White"
                                  BorderBrush="Black"/&gt;
                          &lt;ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True" DataContext="{Binding}"&gt;
                              &lt;StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" /&gt;
                          &lt;/ScrollViewer&gt;
                      &lt;/Grid&gt;
                  &lt;/Popup&gt;
              &lt;/Grid&gt;
              &lt;ControlTemplate.Triggers&gt;
                  &lt;Trigger Property="HasItems" Value="false"&gt;
                      &lt;Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/&gt;
                  &lt;/Trigger&gt;
                  &lt;Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true"&gt;
                      &lt;Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/&gt;
                      &lt;Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/&gt;
                  &lt;/Trigger&gt;
              &lt;/ControlTemplate.Triggers&gt;
          &lt;/ControlTemplate&gt;
      &lt;/ComboBox.Template&gt;
  &lt;/ComboBox&gt;
  </code></pre>
  
  <p></p>
  
  <p>and here is the code</p>
  
  <pre><code>     using System;
      using System.Collections.ObjectModel;
      using System.Windows;
      using System.Windows.Controls;
      using System.Linq;
      using System.Collections.Generic;
      using System.Text;
      using System.ComponentModel;
      using System.Runtime.CompilerServices;
  
      namespace MyProj.UserControls
      {
          /// &lt;summary&gt;
          /// Interaction logic for MultiSelectComboBox.xaml
          /// &lt;/summary&gt;
      public partial class MultiSelectComboBox : UserControl
      {
          private ObservableCollection&lt;Node&gt; _nodeList;
  
          public MultiSelectComboBox()
          {
              InitializeComponent();
              _nodeList = new ObservableCollection&lt;Node&gt;();
          }
  
          #region Dependency Properties
  
          public event EventHandler CheckBoxClick;
  
          public static readonly DependencyProperty ItemsSourceProperty =
               DependencyProperty.Register("ItemsSource", typeof(Lexicon&lt;string, int&gt;), typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(null,
          new PropertyChangedCallback(OnItemsSourceChanged)));
  
          public static readonly DependencyProperty SelectedItemsProperty =
           DependencyProperty.Register("SelectedItems", typeof(Lexicon&lt;string, int&gt;), typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(null,
       new PropertyChangedCallback(OnSelectedItemsChanged)));
  
          public static readonly DependencyProperty TextProperty =
             DependencyProperty.Register("Text", typeof(string), typeof(MultiSelectComboBox), new UIPropertyMetadata(string.Empty));
  
          public static readonly DependencyProperty DefaultTextProperty =
              DependencyProperty.Register("DefaultText", typeof(string), typeof(MultiSelectComboBox), new UIPropertyMetadata(string.Empty));
  
  
  
          public Lexicon&lt;string, int&gt; ItemsSource
          {
              get { return (Lexicon&lt;string, int&gt;)GetValue(ItemsSourceProperty); }
              set
              {
                  SetValue(ItemsSourceProperty, value);
              }
          }
  
          public Lexicon&lt;string, int&gt; SelectedItems
          {
              get { return (Lexicon&lt;string, int&gt;)GetValue(SelectedItemsProperty); }
              set
              {
                  SetValue(SelectedItemsProperty, value);
              }
          }
  
          public string Text
          {
              get { return (string)GetValue(TextProperty); }
              set { SetValue(TextProperty, value); }
          }
  
          public string DefaultText
          {
              get { return (string)GetValue(DefaultTextProperty); }
              set { SetValue(DefaultTextProperty, value); }
          }
          #endregion
  
          #region Events
          private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
          {
              MultiSelectComboBox control = (MultiSelectComboBox)d;
              control.DisplayInControl();
          }
  
          private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
          {
              MultiSelectComboBox control = (MultiSelectComboBox)d;
              control.SelectNodes();
              control.SetText();
          }
  
          private void CheckBox_Click(object sender, RoutedEventArgs e)
          {
              CheckBox clickedBox = (CheckBox)sender;
  
              if (clickedBox.Content.ToString() == "All")
              {
                  if (clickedBox.IsChecked.Value)
                  {
                      foreach (Node node in _nodeList)
                      {
                          node.IsSelected = true;
                      }
                  }
                  else
                  {
                      foreach (Node node in _nodeList)
                      {
                          node.IsSelected = false;
                      }
                  }
  
              }
              else
              {
                  int _selectedCount = 0;
                  foreach (Node s in _nodeList)
                  {
                      if (s.IsSelected &amp;&amp; s.Text != "All")
                          _selectedCount++;
                  }
                  if (_selectedCount == _nodeList.Count - 1)
                      _nodeList.FirstOrDefault(i =&gt; i.Text == "All").IsSelected = true;
                  else
                      _nodeList.FirstOrDefault(i =&gt; i.Text == "All").IsSelected = false;
              }
              SetSelectedItems();
              SetText();
              if (this.CheckBoxClick != null)
                  this.CheckBoxClick(this, e);
  
          }
          #endregion
  
  
          #region Methods
          private void SelectNodes()
          {
              foreach (KeyValuePair&lt;string, int&gt; keyValue in SelectedItems)
              {
                  Node node = _nodeList.FirstOrDefault(i =&gt; i.Text == keyValue.Key);
                  if (node != null)
                      node.IsSelected = true;
              }
          }
  
          private void SetSelectedItems()
          {
              if (SelectedItems == null)
                  SelectedItems = new Lexicon&lt;string, int&gt;();
              SelectedItems.Clear();
              foreach (Node node in _nodeList)
              {
                  if (node.IsSelected &amp;&amp; node.Text != "All")
                  {
                      if (this.ItemsSource.Count &gt; 0)
  
                          SelectedItems.Add(node.Text, node.Id);
                  }
              }
          }
  
          //private void DisplayInControl()
          //{
          //    _nodeList.Clear();
  
          //    foreach (KeyValuePair&lt;string, int&gt; keyValue in this.ItemsSource)
          //    {
          //        Node node = null;
          //        if (this.ItemsSource.Count == 1)
          //            node = new Node(keyValue.Key);
  
          //        else
          //            node = new Node(keyValue.Key);
          //        _nodeList.Add(node);
          //        if (this.ItemsSource.Count == 1) SetSelectedItems();
          //    }
          //    MultiSelectCombo.ItemsSource = _nodeList;
          //    if (this.ItemsSource.Count == 1) SetText();
          //    else
          //        this.Text = "--Select--";
  
          //}
  
          private void DisplayInControl()
          {
              _nodeList.Clear();
              if (this.ItemsSource.Count &gt; 0)
                  _nodeList.Add(new Node("All", false, -1));
              foreach (KeyValuePair&lt;string, int&gt; keyValue in this.ItemsSource)
              {
                  Node node = new Node(keyValue.Key, false, keyValue.Value);
                  _nodeList.Add(node);
              }
              MultiSelectCombo.ItemsSource = _nodeList;
              this.Text = "--Select--";
          }
          private void SetText()
          {
              if (this.SelectedItems != null)
              {
                  StringBuilder displayText = new StringBuilder();
                  foreach (Node s in _nodeList)
                  {
                      if (s.IsSelected == true &amp;&amp; s.Text == "All")
                      {
                          displayText = new StringBuilder();
                          displayText.Append("All");
                          break;
                      }
                      else if (s.IsSelected == true &amp;&amp; s.Text != "All")
                      {
                          displayText.Append(s.Text);
                          displayText.Append(',');
                      }
                  }
                  this.Text = displayText.ToString().TrimEnd(new char[] { ',' });
              }
              // set DefaultText if nothing else selected
              if (string.IsNullOrEmpty(this.Text))
              {
                  this.Text = this.DefaultText;
              }
          }
  
          #endregion
  
      }
  
      public class Node : INotifyPropertyChanged
      {
  
          private string _text;
          private bool _isSelected;
          private int _id;
          #region ctor
          public Node(string text, bool selected, int id)
          {
              Text = text;
              IsSelected = selected;
              Id = id;
          }
          #endregion
  
          #region Properties
  
          public int Id
          {
              get
              {
                  return _id;
              }
              set
              {
                  _id = value;
                  NotifyPropertyChanged("Id");
              }
          }
          public string Text
          {
              get
              {
                  return _text;
              }
              set
              {
                  _text = value;
                  NotifyPropertyChanged("Text");
              }
          }
          public bool IsSelected
          {
              get
              {
                  return _isSelected;
              }
              set
              {
                  _isSelected = value;
                  NotifyPropertyChanged("IsSelected");
              }
          }
          #endregion
  
          public event PropertyChangedEventHandler PropertyChanged;
          protected void NotifyPropertyChanged(string propertyName)
          {
              if (PropertyChanged != null)
              {
                  PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
              }
          }
  
      }
  }
  </code></pre>
  
  <p>So can some one let me know what changes do I need to do for displaying the <code>TextBox</code> on top of the <code>CheckBoxes</code> so that when I enter some text it should filter and give me the results</p>