Search Bar

Search and filtering component, that integrates with list views.

Namespace: LSOne.Controls

Assembly: LSOne.Controls.SearchBar

Syntax

public partial class SearchBar : UserControl, IEditable

Items SearchBar - initial

 

Items SearchBar - all options

SearchBar adnotated

Legend Description
1 Enable/disable search band
2 Search band
3 Remove search band button
4 Add search band button
5 Additional search option checkbox
6 Search button
7 Search bar context menu

SearchBar with inverted buttons

Constructors

Name Description
SearchBar() Default constructor

 

Properties

Name Description
BuddyControl Gets or sets the System.Windows.Forms.Control to which this search bar is attached. Usually a List View.
ButtonsOnRight

Gets or sets the horizontal position of the Add/Remove buttons in each search band: to left or to right (default)

Default value: true

CanLoadDefault

Gets or sets if the current search bar filters and options can be loaded from previously saved settings.

Default value: true

CanSaveDefault

Gets or sets if the current search bar filters and options can be saved.

Default value: true

DefaultNumberOfSections

Gets or sets the number of the search bands to be displayed by default

Default value: 1

EnableCheckbox

Gets or sets the search band apply check box is displayed

Default value: true

FilterExpression Gets the LSOne.Utilities.Expressions.Expression used for filtering all enabled search bands
HasSearchOption Gets or sets if an additional search option is displayed
LayoutString Gets the search bar layout as a string
LayoutStringWithData Gets the search bar layout and data as a string
MaxNumberOfSections

Gets or sets the maximum number of search bands

Default value: 10

SearchButtonTextOverride

Gets or sets the Search button text.

It must be set in the constructor to be applied, not in the designer.

searchBar.BuddyControl = lvVariantItems;
searchBar.SearchButtonTextOverride = Resources.Filter;

SearchOptionChecked

Gets or sets if the additional search option is checked by default

Default value: false

SearchOptionEnabled

Gets or sets if the additional search option is enabled by default

Default value: false

SearchOptionText Gets or sets the additional search option text
SearchParameterResults Gets the selections from the search bar as a List<SearchParameterResult>

 

Methods

Name Description
AddCondition(LSOne.Controls.ConditionType)

Adds a new search band of type LSOne.Controls.ConditionType.ConditionTypeEnum:

  • None
  • Text
  • ComboBox
  • Date
  • DateRange
  • Checkboxes
  • Numeric
  • NumericRange
  • Unknown
  • DateAndTimeRange
Clear()

Clears text from the selected search band

Implementation of IEditable.Clear() method

Copy()

Copy text from the selected search band

Implementation of IEditable.Copy() method

Cut()

Cuts text from the selected search band

Implementation of IEditable.Cut() method

FocusFirstInput() Sets focus on the first enabled search band
GetLocalizedSavingText() Returns the localized string for "Saving default layout" menu option
GetSelectionString(List<IDataEntity>) Deprecated
GetUsedSectionKeys() Returns a List<string> containing the identification string (LSOne.Controls.ConditionType.TypeKey) of each search band
LoadFactoryDefaults() Resets the search bar to its initial state
LoadFromSetupString(string) Initializes the search bar layout and data from the given string
Paste()

Paste text to the selected search band

Implementation of IEditable.Paste() method

RecalculateLayout() Adjusts the display location of each search band
SelectAll() Implementation of IEditable.SelectAll() method
UsesBar(string) Selects all text from the selected search band

 

Events

Name Description
AdjustSize Occurs when the BuddyControl is unavailable but the search bar was changed (by adding / removing a search band)
LoadDefaults Occurs when the "Load default layout" menu item is clicked
ResetSections Occurs when the "Reset" menu item is clicked
SaveAsDefault Occurs when the "Save as default layout" menu item is clicked
SearchClicked Occurs when the "Search" button is clicked
SearchOptionChanged Occurs when the additional search option check box is checked or unchecked
SetupConditions Occurs on search bar loading
UnknownControlAdd Occurs when the user clicks the plus sign to add a new search band embedding an unknown control
UnknownControlGetSelection Occurs when the filter expression is constructed or then the layout is saved if the search bar contains at least one search band embedding and unknown control
UnknownControlHasSelection Occurs when the user selected some data in the search band embedding and unknown control
UnknownControlRemove Occurs when the user removes a search band embedding and unknown control
UnknownControlSetSelection Occurs when the search band embedding an unknown control is added to the search bar

 

Remarks

Below is a list of all functions and properties that need to be set in order to add a search panel to a view in Site Manager.

  1. in View constructor

    
    searchBar1.BuddyControl = lvCustomers;
    searchBar1.FocusFirstInput();
    				

    If the search bar does not display properly in relation to the list view at window resize then these lines must be moved in the constructor, so that they're executed earlier

  2. in SaveUserInterface() - if the sorting of the list view or any search options should be saved per user

    
    public override void SaveUserInterface()
    {
    	string newSortSetting = lvCustomers.SortSetting;
    	
    	if (newSortSetting != sortSetting.Value)
    	{
    		sortSetting.Value = newSortSetting;
    		sortSetting.UserSettingExists = true;
    		
    		PluginEntry.DataModel.Settings.SaveSetting(PluginEntry.DataModel, SortSettingID, SettingsLevel.User, sortSetting);
    	}
    }
    

  3. SetupConditions event on Search bar
    • to configure the search bands the event SetupConditions on the SearchBar has to be implemented

      
      private void searchBar1_SetupConditions(object sender, EventArgs e)
      {
      	//add search bands options and conditions
      	
      	//the SetupCondition event should always end with calling LoadDefault event to load a user-specific filter if it exists
      	searchBar1_LoadDefault(this, EventArgs.Empty);
      }
      

    • Search band options and conditions

      
      //Textbox for entering any search text
      searchBar1.AddCondition(new ConditionType(Resources.Description, "Description", ConditionType.ConditionTypeEnum.Text));
      searchBar1.AddCondition(new ConditionType(Resources.Variant, "Variant", ConditionType.ConditionTypeEnum.Text));
      searchBar1.AddCondition(new ConditionType(Resources.BarCode, "BarCode", ConditionType.ConditionTypeEnum.Text));
      
      //Textbox for entering search text, with a fixed combobox size and tooltip
      searchBar1.AddCondition(new ConditionType(Resources.Description, "Description", ConditionType.ConditionTypeEnum.Text, fixedComboBoxSize: 50, displayToolTip: true));
      
      //Combobox that has a specific translated text
      searchBar1.AddCondition(new ConditionType(Resources.BlockingStatus, "Blocked", ConditionType.ConditionTypeEnum.ComboBox, blockedList, 0));  
      
      //Dates with date range
      searchBar1.AddCondition(new ConditionType(Resources.Date, "Date", ConditionType.ConditionTypeEnum.DateRange, false, DateTime.Now.Date.AddMonths(-1).AddDays(-1), false, DateTime.Now.Date.AddDays(-1)));
      
      //Date and time range
      searchBar1.AddCondition(new ConditionType(Resources.DateRange, "DateRange", ConditionType.ConditionTypeEnum.DateAndTimeRange, false, DateTime.Now.Date, false, DateTime.Now.Date));
      
      //Checkboxes
      searchBar1.AddCondition(new ConditionType(Resources.Types, "Types", ConditionType.ConditionTypeEnum.Checkboxes,
      									Resources.PaymentTypesIntoAccount, true,
      									Resources.PaymentTypesCharged, true,
      									Resources.PaymentTypesOtherTenders, true));
      
      //Numeric textbox
      searchBar1.AddCondition(new ConditionType(Resources.Balance, "Balance", ConditionType.ConditionTypeEnum.Numeric));
      									
      //Unknown control
      searchBar1.AddCondition(new ConditionType(Resources.RetailGroup, "RetailGroup", ConditionType.ConditionTypeEnum.Unknown));
      searchBar1.AddCondition(new ConditionType(Resources.RetailDepartment, "RetailDepartment", ConditionType.ConditionTypeEnum.Unknown));
      searchBar1.AddCondition(new ConditionType(Resources.TaxGroup, "TaxGroup", ConditionType.ConditionTypeEnum.Unknown));
      searchBar1.AddCondition(new ConditionType(Resources.Vendor, "Vendor", ConditionType.ConditionTypeEnum.Unknown));
      searchBar1.AddCondition(new ConditionType(Resources.SpecialGroup, "SpecialGroup", ConditionType.ConditionTypeEnum.Unknown));
      searchBar1.AddCondition(new ConditionType(Resources.Attribute, "Attribute", ConditionType.ConditionTypeEnum.Unknown));
      

  4. SearchClicked event on Search bar

    It varies between the views what is needed to be done in this event i.e. to show a progress dialog or not

    
    private void searchBar1_SearchClicked(object sender, EventArgs e)
    {            
    	ShowProgress((sender1, e1) => LoadItems(), GetLocalizedSearchingText());
    }											
    

  5. Apply filtering when loading items in the list view
    • use searchBar.SearchParametersResults to retrieve the parameters that were selected for the filtering
    • each search band needs to have it's own variable to store the selected parameter for the filtering
    
    string idOrDescription = null;
    bool idOrDescriptionBeginsWith = true;
    RecordIdentifier salesTaxGroupID = null;
    RecordIdentifier priceGroupID = null;
    RecordIdentifier lineDiscountGroupID = null;
    RecordIdentifier totalDiscountGroupID = null;
    DataLayer.BusinessObjects.Customers.Customer.BlockedEnum? isBlocked = null;
    bool? showDeleted = null;
    
    List<SearchParameterResult> results = searchBar1.SearchParameterResults;
    
    foreach (SearchParameterResult result in results)
    {
    	switch (result.ParameterKey)
    	{
    		case "Description":
    			idOrDescription = result.StringValue;
    			idOrDescriptionBeginsWith = (result.SearchModification == SearchParameterResult.SearchModificationEnum.BeginsWith);
    			break;
    		case "SalesTaxGroup":
    			salesTaxGroupID = ((DualDataComboBox)result.UnknownControl).SelectedData.ID;
    			break;
    		case "PriceGroup":
    			priceGroupID = ((DualDataComboBox)result.UnknownControl).SelectedData.ID;
    			break;
    		case "LineDiscountGroup":
    			lineDiscountGroupID = ((DualDataComboBox)result.UnknownControl).SelectedData.ID;
    			break;
    		case "TotalDiscountGroup":
    			totalDiscountGroupID = ((DualDataComboBox)result.UnknownControl).SelectedData.ID;
    			break;
    		case "Blocked":
    			switch (result.ComboSelectedIndex)
    			{
    				case 1:
    					isBlocked = DataLayer.BusinessObjects.Customers.Customer.BlockedEnum.All;
    					break;
    				case 2:
    					isBlocked = DataLayer.BusinessObjects.Customers.Customer.BlockedEnum.Invoice;
    					break;
    				case 3:
    					isBlocked = DataLayer.BusinessObjects.Customers.Customer.BlockedEnum.Nothing;
    					break;
    				default:
    					isBlocked = null;
    					break;
    			}
    			break;
    		case "Deleted":
    			showDeleted = result.CheckedValues[0];
    			break;
    	}
    }						
    
  6. SaveAsDefault event of the Search bar - to save the current filter

    
    private Setting searchBarSetting; // private variable in the page/view/dialog
    private static Guid BarSettingID = new Guid("1A53C2AE-F175-476B-A687-6FB76D34B891"); // create a new GUID for this variable in each view/page/dialog
    private void searchBar1_SaveAsDefault(object sender, EventArgs e)
    {
    	string layoutString = searchBar1.LayoutStringWithData;
    	
    	if (searchBarSetting.LongUserSetting != layoutString)
    	{
    		searchBarSetting.LongUserSetting = layoutString;
    		searchBarSetting.UserSettingExists = true;
    		
    		PluginEntry.DataModel.Settings.SaveSetting(PluginEntry.DataModel, BarSettingID, SettingsLevel.User, searchBarSetting);
    	}
    	
    	ShowTimedProgress(searchBar1.GetLocalizedSavingText());
    	//((ViewBase)Parent.Parent.Parent).ShowTimedProgress(searchBar1.GetLocalizedSavingText()); - if the view doesn't inherit from ViewBase then this needs to be used instead of the line above
    }
    

  7. LoadDefault event of the Search bar - to load a previously saved filter

    
    private Setting searchBarSetting; // private variable in the page/view/dialog
    private static Guid BarSettingID = new Guid("1A53C2AE-F175-476B-A687-6FB76D34B891"); // create a new GUID for this variable in each view/page/dialog
    
    private void searchBar1_LoadDefault(object sender, EventArgs e)
    {
    	searchBarSetting = PluginEntry.DataModel.Settings.GetLongSetting(PluginEntry.DataModel, BarSettingID, SettingType.UISetting,"");
    	
    	if (searchBarSetting != null && searchBarSetting.LongUserSetting != "")
    	{
    		searchBar1.LoadFromSetupString(searchBarSetting.LongUserSetting);
    	}
    }
    

 

Unknown controls

If there are unknown controls in the SetupConditions code then all the Unknown events must be implemented.

Each unknown control needs to be added specifically in the UnknownControlAdd event of the Search bar and any events needed to display data, clear data, initialize and what ever else is needed for this

specific search condition have to be added to the control and then implemented separately for each control.

To prevent a memory leak, all events that were added in the UnknownControlAdd event need to be removed in the UnknownControlRemove event of the search bar

 
  1. UnknownControlAdd event of the Search bar
    • this event is fired off when the user clicks the + sign to add a new search band and then selects from a combo box what to filter by

      
      private void searchBar1_UnknownControlAdd(object sender, UnknownControlCreateArguments args)
      {
      	switch (args.TypeKey)
      	{
      		case "RetailGroup":
      			args.UnknownControl = new DualDataComboBox();
      			args.UnknownControl.Size = new Size(200, 21);
      			args.MaxSize = 200;
      			args.AutoSize = false;
      			((DualDataComboBox) args.UnknownControl).SkipIDColumn = true; Note: depends on the data if this property is needed or not
      			((DualDataComboBox)args.UnknownControl).ShowDropDownOnTyping = true;
      			((DualDataComboBox)args.UnknownControl).SelectedData = new DataEntity("", "");
      			
      			((DualDataComboBox) args.UnknownControl).DropDown += new EventHandler(RetailDepartments_DropDown);
      			break;
      			
      		case "RetailDepartment":
      			args.UnknownControl = new DualDataComboBox();
      			args.UnknownControl.Size = new Size(200, 21);
      			args.MaxSize = 200;
      			args.AutoSize = false;
      			((DualDataComboBox)args.UnknownControl).ShowDropDownOnTyping = true;
      			((DualDataComboBox)args.UnknownControl).SelectedData = new DataEntity("", "");
      			((DualDataComboBox) args.UnknownControl).RequestData += new EventHandler(RetailDepartments_RequestData);
      			
      			break;
      		
      		case "Source":
      			args.UnknownControl = new DualDataComboBox();
      			args.UnknownControl.Size = new Size(200, 21);
      			args.UnknownControl.Name = "Source";
      			args.MaxSize = 200;
      			args.AutoSize = false;
      			((DualDataComboBox) args.UnknownControl).SkipIDColumn = true;
      			((DualDataComboBox) args.UnknownControl).ShowDropDownOnTyping = true;
      			((DualDataComboBox) args.UnknownControl).SelectedData = new DataEntity("", "");
      			
      			((DualDataComboBox) args.UnknownControl).RequestData += new EventHandler(Source_RequestData);
      			
      			break;
      		
      		case "SpecialGroup":
      			//same as above but has the RequestData event
      		case "Vendor":
      			//same as above but has the RequestData event
      		case "TaxGroup":
      			//same as above but has the RequestData event
      		case "Attribute":
      			var dualDataComboBox = new DualDataComboBox();
      			      
      			dualDataComboBox.MaxLength = 32767;
      			dualDataComboBox.SelectedData = null;
      			dualDataComboBox.SkipIDColumn = true;
      			       
      			dualDataComboBox.ShowDropDownOnTyping = true;
      			
      			ItemSearchFlagSelectionList selectionList = new ItemSearchFlagSelectionList(Providers.RetailItemData.ItemSearchFlags);
      			dualDataComboBox.SelectedData = selectionList;
      			dualDataComboBox.DropDown += Attribute_DropDown;
      			dualDataComboBox.SelectedDataChanged += Attribute_SelectedDataChanged;
      			
      			dualDataComboBox.Size = new Size(200, 21);
      			args.UnknownControl = dualDataComboBox;
      			args.MaxSize = 200;
      			args.AutoSize = false;
      			
      			break;
      	}
      }
      			

    • Any data load events of the unknown control(s) like RequestData for each combo box needs to be implemented

      
      private void Source_RequestData(object sender, EventArgs e)
      {
      	((DualDataComboBox) sender).SkipIDColumn = true;
      	((DualDataComboBox) sender).SetData(GetConfigurationListForSearch(ConfigurationType.Source), null); //SetData needs a list for IDataEntities
      }
      

    • If the data that is being retrieved is part of the SearchTypeEnum then the below code is enough

      
      void RetailDepartments_DropDown(object sender, DropDownEventArgs e)
      {
      	((DualDataComboBox)sender).SkipIDColumn = true;
      	e.ControlToEmbed = new SingleSearchPanel(PluginEntry.DataModel, false, e.DisplayText, SearchTypeEnum.RetailDepartmentsMasterID, "");
      }
      

  2. UnknownControlRemove event of the Search bar

    
    private void searchBar1_UnknownControlRemove(object sender, UnknownControlArguments args)
    {
    	switch (args.TypeKey)
    	{
    		case "RetailGroup":
    			((DualDataComboBox)args.UnknownControl).DropDown -= RetailGroup_DropDown;
    			break;
    		
    		case "RetailDepartment":
    			((DualDataComboBox)args.UnknownControl).DropDown -= RetailDepartments_DropDown;
    			break;
    		
    		case "SpecialGroup":
    			((DualDataComboBox)args.UnknownControl).DropDown -= SpecialGroups_DropDown;
    			break;
    		
    		case "Vendor":
    			((DualDataComboBox)args.UnknownControl).RequestData -= Vendors_RequestData;
    			break;
    		
    		case "TaxGroup":
    			((DualDataComboBox)args.UnknownControl).RequestData -= TaxGroup_RequestData;
    			break;
    		
    		case "Attribute":
    			((DualDataComboBox)args.UnknownControl).DropDown -= Attribute_DropDown;
    			((DualDataComboBox)args.UnknownControl).SelectedDataChanged -= Attribute_SelectedDataChanged;
    			break;
    	}
    }
    

  3. UnknownControlHasSelection event of the Search bar
    • fired off when something has been selected in the controls that were added as Unknown controls
    • what is done here depends on the type of data being displayed in these search bands

    
    private void searchBar1_UnknownControlHasSelection(object sender, UnknownControlSelectionArguments args)
    {
    	switch (args.TypeKey)
    	{
    		case "RetailGroup":
    		case "RetailDepartment":
    		case "SpecialGroup":
    		case "Vendor":
    		case "TaxGroup":
    		args.HasSelection = ((DualDataComboBox)args.UnknownControl).SelectedData.ID != "" && ((DualDataComboBox)args.UnknownControl).SelectedData.ID != RecordIdentifier.Empty;
    		break;
    	
    	case "Attribute":
    		args.HasSelection = true;
    		break;
    	}
    }
    

  4. UnknownControlGetSelection event of the Search bar
    • fires off when the ID of the value that the user selected is retrieved
    • what is done here depends on the type of data being displayed in these search bands

    
    private void searchBar1_UnknownControlGetSelection(object sender, UnknownControlSelectionArguments args)
    {
    	switch (args.TypeKey)
    	{
    		case "RetailGroup":
    		case "RetailDepartment":
    		case "SpecialGroup":
    		case "Vendor":
    		case "TaxGroup":
    		case "Attribute":
    			args.Selection = (string)((DualDataComboBox)args.UnknownControl).SelectedData.ID;
    			break;
    	}
    }
    
    

  5. UnknownControlSetSelection event of the Search bar
    • fires off when the unknown controls must display the value the user selected
    • what is done here depends on the type of data being diplayed in these search bands

    
    private void searchBar1_UnknownControlSetSelection(object sender, UnknownControlSelectionArguments args)
    {
    	DataEntity entity = null;
    	switch (args.TypeKey)
    	{
    		case "RetailGroup":
    			entity = Providers.RetailGroupData.Get(PluginEntry.DataModel, args.Selection);
    			break;
    		case "RetailDepartment":
    			entity = Providers.RetailDepartmentData.Get(PluginEntry.DataModel, args.Selection);
    			break;
    		case "SpecialGroup":
    			entity = Providers.SpecialGroupData.Get(PluginEntry.DataModel, args.Selection);
    			break;
    		case "Vendor":
    			entity = Providers.VendorData.Get(PluginEntry.DataModel, args.Selection);
    			break;
    		case "TaxGroup":
    			entity = Providers.ItemSalesTaxGroupData.Get(PluginEntry.DataModel, args.Selection);
    			break;
    	}
    	((DualDataComboBox)args.UnknownControl).SelectedData = entity ?? new DataEntity("", "");
    }		
    

See also