Click here to Skip to main content
11,578,524 members (61,132 online)
Click here to Skip to main content

Building a Search Text Box Control with WPF

, 3 Sep 2010 CPOL 68.4K 5.9K 85
Rate this:
Please Sign up or sign in to vote.
Another convenient control for your WPF applications.

Introduction

I've worked a lot with database applications. Sometimes, providing the capability to search through stored items is a critical requirement. Items may have many fields and, of course, they may be located in different tables. These raise the question of how to design an elegantly effective user interface supporting the capability. I tried some user interface prototypes, but none of them made me feel satisfied. A good solution came up when I used Windows Explorer.

clip_image002

Figure 1: The search text box on the top-right corner of Windows Explorer

The combination of the search button, the text label, and the text box is quite amazing. A lot of space is saved, and the functional design is good. I wanted to use such controls in my applications, but .NET Framework has not provided any standard control like this one. In this article, I'm demonstrating a solution based on WPF. Many thanks fly to David Owens for his wonderful article at http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/. Technically, his document showed me a practical way to realize my own Search Text Box control which has more functionalities. Now, let's get started!

Designing the control

Figure 2: The control's layout

We're going to create a custom control exposing the following properties:

  • LabelText - When the text box is blank, we'll display this text instead. The default value is "Search".
  • LabelTextColor - The color of the label text. The default will be "Gray".
  • ShowSectionButton - Decides to show the section button or not. This property is very useful if you allow users to search items based on a set of criteria.
  • SectionsList - Holds a list of sections which correspond to the data columns.
  • SectionsStyle - The style of section items. You can choose between CheckBoxStyle, RadioBoxStyle, or NormalStyle.
  • OnSearch - This event is spawn whenever the search button is clicked or the Enter key is pressed.

Here are some images of the control I created:

clip_image006

Figure 3: A sections list styled by CheckBoxStyle

clip_image008

Figure 4: A sections list styled by RadioBoxStyle

clip_image010

Figure 5: List of previous keywords

Creating the layout

The file Generic.xaml contains the XAML code for laying out the control. All that we're doing is modifying the property template.

<ResourceDictionary> <!-- ... -->
  <Style x:Key="{x:Type l:SearchTextBox}" TargetType="{x:Type l:SearchTextBox}">
    <!-- ... -->
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type l:SearchTextBox}">
            <!- XAML code for creating the layout goes here -->
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

Displaying the lists

To customize a standard list box with the above styles, I added another Resource Dictionary file which is named as ListBoxEx.xaml. The file contains definitions of the three styles. We need an adjustment to the way that our lists' items are rendered. For example, if we want our items to have CheckBoxStyle, we simply alter the template ListBoxItem like this:

<Setter Property="ItemContainerStyle">  
<Setter.Value>
        <Style TargetType="{x:Type ListBoxItem}" >
            <Setter Property="Margin" Value="2" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <CheckBox Focusable="False"
                            IsChecked="{Binding Path=IsSelected, Mode=TwoWay,
                            RelativeSource={RelativeSource TemplatedParent} }">
                            <ContentPresenter></ContentPresenter>
                        </CheckBox>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Setter.Value>
</Setter>

With RadioBoxStyle, we must ensure that: at a particular time, there's only one item selected. I don't want to use lengthy C# code to attain this task. Everything seems so easy when every RadioBoxStyle item shares the same Group name:

<Setter Property="ItemContainerStyle">
    <Setter.Value>
        <Style TargetType="{x:Type ListBoxItem}" >
            <Setter Property="Margin" Value="2" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <RadioButton Focusable="False" GroupName="RadioListBoxItems"
                            IsChecked="{Binding Path=IsSelected, Mode=TwoWay,
                            RelativeSource={RelativeSource TemplatedParent} }">
                            <ContentPresenter></ContentPresenter>
                        </RadioButton>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Setter.Value>
</Setter>

So far so good; the remainder is programmatically showing the lists whenever users click on the section button or the previous button.

private Popup m_listPopup = new Popup();private ListBoxEx m_listSection = null;
private ListBoxEx m_listPreviousItem = null;
 
private void BuildPopup()
{
    // initialize the pop up
    m_listPopup.PopupAnimation = PopupAnimation.Fade;
    m_listPopup.Placement = PlacementMode.Relative;
    m_listPopup.PlacementTarget = this;
    m_listPopup.PlacementRectangle = new Rect(0, this.ActualHeight, 30, 30);
    m_listPopup.Width = this.ActualWidth;
    // initialize the sections' list
    if (ShowSectionButton)
    {
        m_listSection = new ListBoxEx((int)m_itemStyle + 
                                  ListBoxEx.ItemStyles.NormalStyle);

        // ...
    }
 
    // initialize the previous items' list
    m_listPreviousItem = new ListBoxEx();
    // ...
}
 
private void HidePopup()
{
    m_listPopup.IsOpen = false;
}
 
private void ShowPopup(UIElement item)
{
    m_listPopup.StaysOpen = true;
    m_listPopup.Child = item;
    m_listPopup.IsOpen = true;
}

private void ChooseSection_MouseDown(object sender, MouseButtonEventArgs e)
{

    if (SectionsList == null)
        return;
    if (SectionsList.Count != 0)
        ShowPopup(m_listSection);
}

private void PreviousItem_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (m_listPreviousItem.Items.Count != 0)
        ShowPopup(m_listPreviousItem);
}

Raising the Search event

Whenever users request to start a new search either by clicking on the search button or entering a keyword, an event OnSearch will be fired. A class named SearchEventArgs provides data for the event.

public class SearchEventArgs: RoutedEventArgs{
    private string m_keyword="";
 
    public string Keyword
    {
        get { return m_keyword; }
        set { m_keyword = value; }
    }
    private List<string> m_sections= new List<string>();
 
    public List<string> Sections
    {
        get { return m_sections; }
        set { m_sections = value; }
    } 
    public SearchEventArgs(): base(){
 
    }
    public SearchEventArgs(RoutedEvent routedEvent): base(routedEvent){
 
    }
}

I've chosen to override the method OnKeyDown to create the event. This is shown below:

protected override void OnKeyDown(KeyEventArgs e) {
    if (e.Key == Key.Escape) {
        this.Text = "";
    }
    else if ((e.Key == Key.Return || e.Key == Key.Enter)) {
        RaiseSearchEvent();
    }
    else {
        base.OnKeyDown(e);
    }
}
 
private void RaiseSearchEvent() {
    if (this.Text == "")
        return;
    if(!m_listPreviousItem.Items.Contains(this.Text))
        m_listPreviousItem.Items.Add(this.Text);
 
 
    SearchEventArgs args = new SearchEventArgs(SearchEvent);
    args.Keyword = this.Text;
    if(m_listSection != null){
        args.Sections = (List<string>)m_listSection.SelectedItems.Cast<string>().ToList();
    }
    RaiseEvent(args);
}

How to use the control

That's it; now the control is ready for action. To use it, you can go through these steps:

  1. Make a reference to the assembly SearchTextBox.dll which contains our control.
  2. Create a namespace in XAML markup like the following in your application XAML namespace:
  3. <Window x:Class="TestUI.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:l="clr-namespace:UIControls;assembly=SearchTextBox"
            Title="Window1" Height="423" Width="487">
  4. Create an instance of the control in the markup:
  5. <l:SearchTextBox Height="39" Margin="118,52,116,0" 
          VerticalAlignment="Top" Name="m_txtTest" Background="AliceBlue" />
  6. Implement the C# code-behind:
    • Create a using directive to use the control in the namespace UIControls.
    • using UIControls;
    • Initialize the control with the appropriate information, for example:
    • public Window1()
      {
          InitializeComponent();
       
          // Supply the control with the list of sections
          List<string> sections = new List<string> {"Author", 
                                     "Title", "Comment"};
          m_txtTest.SectionsList = sections;
       
          // Choose a style for displaying sections
          m_txtTest.SectionsStyle = SearchTextBox.SectionsStyles.RadioBoxStyle;
       
          // Add a routine handling the event OnSearch
          m_txtTest.OnSearch += new RoutedEventHandler(m_txtTest_OnSearch);
      }
       
      void m_txtTest_OnSearch(object sender, RoutedEventArgs e)
      {
          SearchEventArgs searchArgs = e as SearchEventArgs;
       
          // Display search data
          string sections = "\r\nSections(s): ";
          foreach (string section in searchArgs.Sections)
              sections += (section + "; ");
          m_txtSearchContent.Text = "Keyword: " + searchArgs.Keyword + sections;
      }

Conclusion

I hope you liked this article. Any feedback from you is valuable to me for making the control better. Thanks for reading!

License

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

Share

About the Author

Le Duc Anh
Product Manager MVCorp
Vietnam Vietnam
I'm a computer freak. Application Security & Big Data are my research fields.

You may also be interested in...

Comments and Discussions

 
Questionbug Pin
ntnk19841-Dec-14 16:22
memberntnk19841-Dec-14 16:22 
AnswerRe: bug Pin
Le Duc Anh2-Dec-14 14:03
memberLe Duc Anh2-Dec-14 14:03 
QuestionGreat tool, but one question Pin
Member 105971415-Nov-14 10:03
memberMember 105971415-Nov-14 10:03 
QuestionWonderful Pin
Member 1098405215-Aug-14 10:53
memberMember 1098405215-Aug-14 10:53 
QuestionThe 'x' button isn't user friendly. Pin
wa1gon12-Sep-13 7:17
memberwa1gon12-Sep-13 7:17 
AnswerRe: The 'x' button isn't user friendly. Pin
weaponx729-Jan-14 4:09
memberweaponx729-Jan-14 4:09 
QuestionWhere is the part for binding data for searching to searchbox control? Pin
Duška Miloradović11-Aug-13 22:42
memberDuška Miloradović11-Aug-13 22:42 
AnswerRe: Where is the part for binding data for searching to searchbox control? Pin
Le Duc Anh11-Aug-13 23:34
memberLe Duc Anh11-Aug-13 23:34 
GeneralRe: Where is the part for binding data for searching to searchbox control? Pin
Daisy M12-Aug-13 0:42
memberDaisy M12-Aug-13 0:42 
GeneralRe: Where is the part for binding data for searching to searchbox control? Pin
Le Duc Anh12-Aug-13 4:01
memberLe Duc Anh12-Aug-13 4:01 
Generalmy vote of 4 Pin
ARIA 52-Dec-12 23:39
memberARIA 52-Dec-12 23:39 
GeneralMy vote of 5 Pin
nikhil _singh25-Oct-12 2:23
membernikhil _singh25-Oct-12 2:23 
GeneralRe: My vote of 5 Pin
Le Duc Anh25-Oct-12 3:08
memberLe Duc Anh25-Oct-12 3:08 
Questionneed help for create same control on windows form Pin
Nilesh Makavana12-Aug-12 8:53
memberNilesh Makavana12-Aug-12 8:53 
AnswerRe: need help for create same control on windows form Pin
Le Duc Anh12-Aug-12 16:52
memberLe Duc Anh12-Aug-12 16:52 
GeneralRe: need help for create same control on windows form Pin
Nilesh Makavana14-Aug-12 19:33
memberNilesh Makavana14-Aug-12 19:33 
i am developing windows application and i need that so.
thank you.
i will try to use it in windows application.
GeneralMessage Automatically Removed Pin
28-Jun-12 4:01
memberMahBulgaria28-Jun-12 4:01 
QuestionClear button is not functioning Pin
NikolayKa4-Apr-12 9:32
memberNikolayKa4-Apr-12 9:32 
AnswerRe: Clear button is not functioning Pin
Le Duc Anh4-Apr-12 13:45
memberLe Duc Anh4-Apr-12 13:45 
AnswerRe: Clear button is not functioning Pin
jim19107-Dec-12 11:15
memberjim19107-Dec-12 11:15 
GeneralRe: Clear button is not functioning Pin
Le Duc Anh7-Dec-12 13:44
memberLe Duc Anh7-Dec-12 13:44 
GeneralRe: Clear button is not functioning Pin
jim19107-Dec-12 14:23
memberjim19107-Dec-12 14:23 
GeneralMy vote of 5 Pin
Dean Oliver1-Feb-12 0:33
memberDean Oliver1-Feb-12 0:33 
GeneralMy vote of 5 Pin
Kanasz Robert18-Jan-12 21:38
mvpKanasz Robert18-Jan-12 21:38 
GeneralMy vote of 5 Pin
Vincenzo Rocco1-Sep-10 11:41
memberVincenzo Rocco1-Sep-10 11:41 
GeneralRe: My vote of 5 Pin
Le Duc Anh5-Nov-10 16:52
memberLe Duc Anh5-Nov-10 16:52 
GeneralA few recommendations Pin
Paul B.25-Aug-10 7:01
memberPaul B.25-Aug-10 7:01 
GeneralRe: A few recommendations Pin
Le Duc Anh25-Aug-10 14:58
memberLe Duc Anh25-Aug-10 14:58 
GeneralUsing from Silverlight Pin
AndrusM24-Aug-10 0:15
memberAndrusM24-Aug-10 0:15 
GeneralRe: Using from Silverlight Pin
Le Duc Anh26-Aug-10 15:06
memberLe Duc Anh26-Aug-10 15:06 
GeneralUsefull Pin
sinun23-Aug-10 10:07
membersinun23-Aug-10 10:07 
GeneralRe: Usefull Pin
Le Duc Anh23-Aug-10 16:09
memberLe Duc Anh23-Aug-10 16:09 
GeneralMy vote of 4 Pin
Pranay Rana19-Aug-10 21:37
memberPranay Rana19-Aug-10 21:37 
GeneralMy vote of 3 Pin
anishmehta18-Aug-10 6:58
memberanishmehta18-Aug-10 6:58 

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 | Terms of Use | Mobile
Web03 | 2.8.150603.1 | Last Updated 3 Sep 2010
Article Copyright 2010 by Le Duc Anh
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid