Jan 17, 2013

Search By TextBox and Grid

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
namespace URTextBox
{
    [ToolboxBitmap(typeof(TextBox))]
    public class URTextBox:TextBox
    {
        #region Fields
        public DataTable DataSource { get; set; }
        public int DropdownWith { get; set; }
     
        public string[] FilterColumns { get; set; }
        public string[] DisplayColumns { get; set; }  
        public string ValueColumn { get; set; }
     
     
        #endregion
        #region private Fields
           
        private Panel panel;
        private System.Windows.Forms.DataGridView DataGridView;
        // the parent Form of this control
        private Form ParentForm
        {
            get { return this.Parent.FindForm(); }
        }
        #endregion

        public URTextBox():base()
        {
            // the sample dictionary en-EN.dic is stored here when form1 is loaded (see form1.Load event)
            // assigning some default values
            // minimum characters to be typed before suggestions are displayed


            DataSource = new DataTable();
         
            // the dataGridView used for suggestions
         
            this.DataGridView = new System.Windows.Forms.DataGridView();
            this.DataGridView.AllowUserToAddRows = false;
            this.DataGridView.AllowUserToDeleteRows = false;
            this.DataGridView.AutoGenerateColumns = false;
            this.DataGridView.Name = "dataGridView";
            this.DataGridView.MultiSelect = false;
            this.DataGridView.RowHeadersVisible = false;
            this.DataGridView.ReadOnly = true;
            this.DataGridView.BackgroundColor = System.Drawing.Color.White;
            this.DataGridView.DefaultCellStyle.ForeColor = System.Drawing.Color.Black;
            //this.DataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.DisplayedCells;
            this.DataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;          
            this.DataGridView.DoubleClick += new System.EventHandler(this.dataGridView_DoubleClick);
            this.DataGridView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.dataGridView_KeyDown);
            // the panel to hold the listbox later on
            this.panel = new Panel();
            this.panel.Visible = false;
            this.panel.Font = this.Font;
            // to be able to fit to changing sizes of the parent form
            this.panel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
            // initialize with minimum size to avoid overlaping or flickering problems
            this.panel.ClientSize = new System.Drawing.Size(1, 1);
            this.panel.Name = "SuggestionPanel";
            this.panel.Padding = new System.Windows.Forms.Padding(0, 0, 0, 0);
            this.panel.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
            this.panel.BackColor = Color.Transparent;
            this.panel.ForeColor = Color.Transparent;
            this.panel.Text = "";
            this.panel.PerformLayout();
            // add the listbox to the panel if not already done
            if (!panel.Controls.Contains(DataGridView))
            {
                this.panel.Controls.Add(DataGridView);
            }

            // make the listbox fill the panel
            this.DataGridView.Dock = DockStyle.Fill;
            DropdownWith = 0;
        }
        #region Events
        private void SetColumns()
        {
         
            for (int i = 0; i < DataSource.Columns.Count; i++)
            {
                string ColumnName= DataSource.Columns[i].ColumnName;
                System.Windows.Forms.DataGridViewTextBoxColumn col=new DataGridViewTextBoxColumn();
                col.DataPropertyName = ColumnName;
                col.HeaderText = ColumnName;
                col.Name = ColumnName;
                if (!DataGridView.Columns.Contains(ColumnName))
                {
                    DataGridView.Columns.Add(col);
                }
            }
            if (DisplayColumns != null)
            {

                if (DisplayColumns.Length > 0)
                {
                    for (int i = 0; i < DataGridView.Columns.Count; i++)
                    {
                        DataGridView.Columns[i].Visible = false;
                    }
                    foreach (string item in DisplayColumns)
                    {
                        DataGridView.Columns[item].Visible = true;
                    }

                }
                else
                {
                    for (int i = 0; i < DataGridView.Columns.Count; i++)
                    {
                        DataGridView.Columns[i].Visible = true;
                    }
                }
            }
         
        }

        // selects the current item
        private bool SelectItem()
        {
         
                // if the ListBox is not empty
                if (((DataGridView.Rows.Count > 0) && (DataGridView.SelectedRows!=null)))
                {
                    this.Focus();
                    // set the Text of the TextBox to the selected item of the ListBox
                    this.Text = DataGridView.SelectedRows[0].Cells[ValueColumn].Value.ToString();
                 
                    // and hide the ListBox
                    //panel.Focus();
                    this.HideSuggestionListBox();
                    //this.Focus();                  
                }
                return true;
             
         
        }
        private void MoveSelection(int Index)
        {
            // beginning of list
            DataGridView.Focus();
            if (Index >= 0 && Index < DataGridView.Rows.Count)            {
             
                DataGridView.Rows[Index].Selected = true;              
            }
        }
        public DataTable ApplyFilter()
        {
            DataTable dtFilter = new DataTable();
            string FilterValue = this.Text;
            dtFilter = DataSource.Clone();
            string filterExpression = string.Empty;
         
            if (FilterColumns != null)
            {
                if (FilterColumns.Length > 0)
                {
                    foreach (string item in FilterColumns)
                    {
                        filterExpression += "CONVERT(" + item + ", 'System.String') like '%" + FilterValue + "%' OR ";
                    }
                 
                }
            }
            else if (string.IsNullOrEmpty(filterExpression))
            {
                foreach (DataColumn item in DataSource.Columns)
                {
                    filterExpression += "CONVERT(" + item.ColumnName + ", 'System.String') like '%" + FilterValue + "%' OR ";
                }
             
            }
            if (!string.IsNullOrEmpty(filterExpression))
            {
                filterExpression = filterExpression.Substring(0, filterExpression.Length - 3);
                DataView dv=DataSource.DefaultView;

                dv.RowFilter=filterExpression;
                dtFilter = dv.ToTable();
             
            }
            return dtFilter;
        }
        // This is a timecritical part
        // Fills/ refreshed the CurrentAutoCompleteList with appropreate candidates
        private void UpdateCurrentAutoCompleteList()
        {
            SetColumns();
            DataTable dtFilter = ApplyFilter();
            this.DataGridView.DataSource = dtFilter;
            // if there is a ParentForm
            if ((ParentForm != null))
            {
                // get its width
                if (DropdownWith == 0)
                {
                    panel.Width = this.Width;
                }
                else
                {
                    panel.Width = DropdownWith;
                }
                // calculate the remeining height beneath the TextBox
                panel.Height = this.Parent.ClientSize.Height - this.Height - this.Location.Y;
                // and the Location to use
                panel.Location = this.Location + new Size(0, this.Height);
                // Panel and ListBox have to be added to ParentForm.Controls before calling BingingContext
                if (!this.Parent.Controls.Contains(panel))
                {
                    // add the Panel and ListBox to the PartenForm
                    this.Parent.Controls.Add(panel);
                }
                // Update the listBox manually - List<string> dosn't support change events
                // this is the DataSource approche, this is a bit tricky and may cause conflicts,
                // so in case fall back to AddRange approache (see Excursus)
                ((CurrencyManager)DataGridView.BindingContext[DataSource]).Refresh();
            }
        }
        #endregion

        #region Show/Hide Panel Search
        // shows the suggestions in ListBox beneath the TextBox
        // and fitting it into the ParentForm
        private void ShowSuggests()
        {
            // show only if MinTypedCharacters have been typed
         
                // prevent overlapping problems with other controls
                // while loading data there is nothing to draw, so suspend layout
                panel.SuspendLayout();
                // user is typing forward, char has been added at the end of the former input
             
                //handle forward typing with refresh
                UpdateCurrentAutoCompleteList();
                           
                if (((DataSource != null) && DataSource.Rows.Count > 0))
                {
                    // finally show Panel and ListBox
                    // (but after refresh to prevent drawing empty rectangles)
                    panel.Show();
                    // at the top of all controls
                    panel.BringToFront();
                    // then give the focuse back to the TextBox (this control)
                    this.Focus();
                }
                // or hide if no results
                else
                {
                    this.HideSuggestionListBox();
                }
                // prevent overlapping problems with other controls
                panel.ResumeLayout(true);
         
         
        }
        public void HideSuggestionListBox()
        {
            if ((ParentForm != null))
            {
                // hiding the panel also hides the listbox
                panel.Hide();
                // now remove it from the ParentForm (Form1 in this example)
                if (this.ParentForm.Controls.Contains(panel))
                {
                    this.ParentForm.Controls.Remove(panel);
                }
            }
        }
        #endregion    
     
        #region Grid Events
        private void dataGridView_DoubleClick(object sender, EventArgs args)
        {
            // select the current item
            SelectItem();
        }
        private void dataGridView_KeyDown(object sender, KeyEventArgs args)
        {
            if ((args.KeyCode == Keys.Escape))
            {
                HideSuggestionListBox();
            }
            if ((args.KeyCode == Keys.Tab))
            {
                // select the current item
                SelectItem();
            }
            if ((args.KeyCode == Keys.Enter))
            {
                // select the current item
                SelectItem();
            }
         
        }
        #endregion

        #region TextBox Events
     
        // if the user leaves the TextBox, the ListBox and the panel ist hidden
        protected override void OnLostFocus(System.EventArgs e)
        {
            if (!panel.ContainsFocus)
            {
                // call the baseclass event
                base.OnLostFocus(e);
                // then hide the stuff
                this.HideSuggestionListBox();
            }
        }
        protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs args)
        {
            // ** Place Event Handling Code Here **
         
            if (args.KeyCode == Keys.Down)
            {
                if (panel.Visible == false)
                {
                    ShowSuggests();

                }
                MoveSelection(0);
            }

            else if (args.KeyCode == Keys.Escape)
            {
                HideSuggestionListBox();
            }
            else if ((args.KeyCode == Keys.Enter))
            {
                // select the item in the ListBox
                SelectItem();
            }
            else if (args.KeyCode == Keys.Tab)
            {
                SelectItem();
            }
            // work is not done, maybe the base class will process the event, so call it...
            base.OnKeyDown(args);
             
             
         
        }
        // if the input changes, call ShowSuggests()
        protected override void OnKeyUp(KeyEventArgs args)
        {
            // avoids crashing the designer
            if (!this.DesignMode)
            {
                if (!this.ReadOnly)
                {
                    if (this.Focused)
                    {
                        if (args.KeyCode == Keys.Escape)
                        {
                            HideSuggestionListBox();
                        }
                        else
                        {
                            ShowSuggests();
                        }
                    }
                }
            }
            base.OnKeyUp(args);
         
        }
     
        #endregion
    }
}
private void PopulateFilters()
  {
      if (this.DataGridView == null) return;
  
      // Cast the data source to a BindingSource. 
      BindingSource data = this.DataGridView.DataSource as BindingSource;

      // Prevent the data source from notifying the DataGridView of changes. 
      data.RaiseListChangedEvents = false;

      // Cache the current BindingSource.Filter value and then change 
      // the Filter property to temporarily remove any filter for the 
      // current column. 
      String oldFilter = data.Filter;
      data.Filter = FilterWithoutCurrentColumn(oldFilter);

      // Reset the filters dictionary and initialize some flags
      // to track whether special filter options are needed. 
      filters.Clear();
      Boolean containsBlanks = false;
      Boolean containsNonBlanks = false;

      // Initialize an ArrayList to store the values in their original
      // types. This enables the values to be sorted appropriately.  
      ArrayList list = new ArrayList(data.Count);

      // Retrieve each value and add it to the ArrayList if it isn't
      // already present. 
      foreach (Object item in data)
      {
          Object value = null;

          // Use the ICustomTypeDescriptor interface to retrieve properties
          // if it is available; otherwise, use reflection. The 
          // ICustomTypeDescriptor interface is useful to customize

          // which values are exposed as properties. For example, the 
          // DataRowView class implements ICustomTypeDescriptor to expose 
          // cell values as property values.        
          // 
          // Iterate through the property names to find a case-insensitive
          // match with the DataGridViewColumn.DataPropertyName value.
          // This is necessary because DataPropertyName is case-
          // insensitive, but the GetProperties and GetProperty methods
          // used below are case-sensitive.
          ICustomTypeDescriptor ictd = item as ICustomTypeDescriptor;
          if (ictd != null)
          {
              PropertyDescriptorCollection properties = 
                  ictd.GetProperties();
              foreach (PropertyDescriptor property in properties)
              {
                  if (String.Compare(this.OwningColumn.DataPropertyName,
                      property.Name, true /*case insensitive*/,
                      System.Globalization.CultureInfo.InvariantCulture)

                      == 0)
                  {
                      value = property.GetValue(item);
                      break;
                  }
              }
          }
          else
          {
              PropertyInfo[] properties = item.GetType().GetProperties(
                  BindingFlags.Public | BindingFlags.Instance);
              foreach (PropertyInfo property in properties)
              {
                  if (String.Compare(this.OwningColumn.DataPropertyName,
                      property.Name, true /*case insensitive*/,
                     System.Globalization.CultureInfo.InvariantCulture) 
                      == 0)
                  {
                      value = property.GetValue(item, 
                          null /*property index*/);
                      break;
                  }
              }
          }

          // Skip empty values, but note that they are present. 
          if (value == null || value == DBNull.Value)
          {
              containsBlanks = true;
              continue;
          }

          // Add values to the ArrayList if they are not already there.
          if (!list.Contains(value))
          {
              list.Add(value);
          }
      }

      // Sort the ArrayList. The default Sort method uses the IComparable 
      // implementation of the stored values so that string, numeric, and 
      // date values will all be sorted correctly. 
      list.Sort();

      // Convert each value in the ArrayList to its formatted representation
      // and store both the formatted and unformatted string representations
      // in the filters dictionary. 
      foreach (Object value in list)
      {
          // Use the cell's GetFormattedValue method with the column's
          // InheritedStyle property so that the dropDownListBox format
          // will match the display format used for the column's cells. 
          String formattedValue = null;
          DataGridViewCellStyle style = OwningColumn.InheritedStyle;
          formattedValue = (String)GetFormattedValue(value, -1, ref style, 
              null, null, DataGridViewDataErrorContexts.Formatting);

          if (String.IsNullOrEmpty(formattedValue))
          {
              // Skip empty values, but note that they are present.
              containsBlanks = true;
          }
          else if (!filters.Contains(formattedValue))
          {
              // Note whether non-empty values are present. 
              containsNonBlanks = true;

              // For all non-empty values, add the formatted and 
              // unformatted string representations to the filters 
              // dictionary.
              filters.Add(formattedValue, value.ToString());
          }
      }

      // Restore the filter to the cached filter string and 
      // re-enable data source change notifications. 
      if (oldFilter != null) data.Filter = oldFilter;
      data.RaiseListChangedEvents = true;

      // Add special filter options to the filters dictionary
      // along with null values, since unformatted representations
      // are not needed. 
      filters.Insert(0, "(All)", null);
      if (containsBlanks && containsNonBlanks)
      {
          filters.Add("(Blanks)", null);
          filters.Add("(NonBlanks)", null);
      }
  }
Ah, I understand the problem now. Actually your datasource doesn't support Filtering.BindingSource.Filter will work only when your datasource implements IBindingListView
Only underlying lists that implement the IBindingListView interface support filtering.
So, to make it work you've to change your underlying datasource. If you don't wanna use DataViewfor some reason try using BindingSource itself as a datasource.
Hope this helps

0 comments:

Post a Comment

Nam Le © 2014 - Designed by Templateism.com, Distributed By Templatelib