Intersoft ClientUI 8 > ClientUI Controls > Control Library > Data Controls Overview > UXDataSearchBox |
UXDataSearchBox is an enhanced UXSearchBox control with built-in QueryDescriptor integration.
UXDataSearchBox is inherited from UXSearchBox which shares all the common features of UXSearchBox. In UXSearchBox, you need to create your own search provider and by checking the QueryText and IsSearching property. With the introduction of QueryDescriptor, UXDataSearchBox provides an easier way to search data through the QueryDescriptor integration. To learn more about other features in UXDataSearchBox, see UXDataComboBox Overview.
The following code shows how to use UXDataSearchBox to search your data using the QueryDescriptor feature.
View |
Copy Code
|
---|---|
<Intersoft:DockPanel FillChildMode="Custom"> <Intersoft:DockPanel.DataContext> <ViewModels:DataSearchBoxViewModel/> </Intersoft:DockPanel.DataContext> <Grid Intersoft:DockPanel.Dock="Top"> <Intersoft:UXDataSearchBox HorizontalAlignment="Right" Margin="0,8,4,4" MinWidth="160" x:Name="SampleControl1" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors}" FilterMemberPath="Description" FilterOperator="StartsWith" WatermarkText="Search Assets" WatermarkTextVisibility="Visible" Height="25" VerticalAlignment="Bottom"/> </Grid> <Grid Intersoft:DockPanel.IsFillElement="True"> <Intersoft:UXGridView QueryOperation="Server" AutoGenerateColumns="False" ItemsSource="{Binding Items}" IsBusy="{Binding IsBusy, Mode=TwoWay}" IsRefreshed="{Binding IsRefreshed, Mode=TwoWay}" CanUserPage="True" PageSize="20" PageDescriptor="{Binding QueryDescriptor.PageDescriptor}" SortDescriptors="{Binding QueryDescriptor.SortDescriptors}"> <Intersoft:UXGridView.Columns> <Intersoft:UXGridViewTextColumn Header="Assets ID" Binding="{Binding AssetsID}" IsReadOnly="True"/> <Intersoft:UXGridViewTextColumn Header="Description" Binding="{Binding Description}"/> <Intersoft:UXGridViewTextColumn Header="Assets Status" Binding="{Binding AssetsStatusID}"/> <Intersoft:UXGridViewCheckBoxColumn Header="Warranty" Binding="{Binding Warranty}" /> <Intersoft:UXGridViewTextColumn Header="Department" Binding="{Binding DepartmentID}"/> <Intersoft:UXGridViewTextColumn Header="Supplier" Binding="{Binding SupplierID}"/> <Intersoft:UXGridViewTextColumn Header="Purchased Price" Binding="{Binding PurchasedPrice, StringFormat=c2}" CellHorizontalAlignment="Right" /> <Intersoft:UXGridViewTextColumn Header="Date Acquired" Binding="{Binding DateAcquired, StringFormat=MMM/dd/yyyy}"/> <Intersoft:UXGridViewTextColumn Header="Date Sold" Binding="{Binding DateSold, StringFormat=MMM/dd/yyyy}" /> <Intersoft:UXGridViewTextColumn Header="Next Schedule" Binding="{Binding NextSchedule, StringFormat=MMM/dd/yyyy}"/> </Intersoft:UXGridView.Columns> </Intersoft:UXGridView> </Grid> </Intersoft:DockPanel> |
GridViewModelBase |
Copy Code
|
---|---|
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.ServiceModel.DomainServices.Client; using Intersoft.Client.Data.ComponentModel; using Intersoft.Client.Framework; using Intersoft.ClientUI.Samples.DataControls.ModelServices; namespace Intersoft.ClientUI.Samples.DataControls.ViewModels { /// <summary> /// Represents a generic ViewModel base class that supports server-side data access to WCF RIA Services using QueryDescriptor. /// </summary> /// <remarks> /// The <see cref="GridViewModelBase"/> class exposes four properties that you can bind to the View elements. /// For the automatic query to work, bind the QueryDescriptor property to the View element that supports QueryDescriptor /// such as UXGridView, UXDataFilter and UXDataPager. /// </remarks> public abstract class GridViewModelBase<T> : ValidationViewModelBase where T : Entity { #region Fields private bool _isBusy; private bool _isPrerequisiteDataLoaded; private IEnumerable _items; private T _selectedItem; private IEnumerable<object> _selectedItems; private QueryDescriptor _queryDescriptor; #endregion #region Constructor /// <summary> /// Initializes a new instance of the <see cref="GridViewModelBase"/> class. /// </summary> public GridViewModelBase() { this._isPrerequisiteDataLoaded = true; this.QueryDescriptor = new QueryDescriptor(); this.Presenter = new MessagePresenter(); this.IsBusy = true; this.QueryLatency = 0.6; } #endregion #region Properties private double QueryLatency { get; set; } /// <summary> /// Gets a value that indicates whether the application is currently in design-time mode. /// </summary> protected bool IsInDesignMode { get { return Intersoft.Client.Framework.ISControl.IsInDesignModeStatic; } } /// <summary> /// Gets or sets a value that indicates whether the prerequisite data is loaded. /// </summary> protected virtual bool IsPrerequisiteDataLoaded { get { return _isPrerequisiteDataLoaded; } set { if (_isPrerequisiteDataLoaded != value) { _isPrerequisiteDataLoaded = value; OnPropertyChanged("IsPrerequisiteDataLoaded"); if (value) this.QueryDescriptor.RaiseQueryChanged(); } } } /// <summary> /// Gets the <see cref="MessagePresenter"/> instance. /// </summary> protected virtual MessagePresenter Presenter { get; private set; } /// <summary> /// Gets the data repository instance that implements <see cref="IDataRepository"/>. /// </summary> protected virtual IDataRepository DataSource { get; private set; } /// <summary> /// Gets or sets a value indicating the currently selected item. /// </summary> public T SelectedItem { get { return _selectedItem; } set { if (_selectedItem != value) { if (_selectedItem != null) _selectedItem.PropertyChanged -= new PropertyChangedEventHandler(OnSelectedItemPropertyChanged); T _oldItem = _selectedItem; _selectedItem = value; OnSelectedItemChanged(_oldItem, value); if (_selectedItem != null) _selectedItem.PropertyChanged += new PropertyChangedEventHandler(OnSelectedItemPropertyChanged); OnPropertyChanged("SelectedItem"); } } } /// <summary> /// Gets or sets a collection of multiple selected items. /// </summary> public IEnumerable<object> SelectedItems { get { return _selectedItems; } set { if (_selectedItems != value) { _selectedItems = value; OnPropertyChanged("SelectedItems"); } } } /// <summary> /// Gets or sets a value representing the collection of data. /// </summary> public IEnumerable Items { get { return _items; } set { if (_items != value) { _items = value; OnPropertyChanged("Items"); } } } /// <summary> /// Gets or sets a value that indicates whether the data repository is busy processing a query based on the given <see cref="QueryDescriptor"/>. /// </summary> public bool IsBusy { get { return _isBusy; } set { if (_isBusy != value) { _isBusy = value; OnPropertyChanged("IsBusy"); } } } /// <summary> /// Gets or sets a <see cref="QueryDescriptor"/> instance which provides the required information for data query purpose. /// </summary> public QueryDescriptor QueryDescriptor { get { return _queryDescriptor; } set { if (_queryDescriptor != value) { if (_queryDescriptor != null) _queryDescriptor.QueryChanged -= new EventHandler(OnQueryChanged); _queryDescriptor = value; _queryDescriptor.QueryChanged += new EventHandler(OnQueryChanged); OnPropertyChanged("QueryDescriptor"); } } } #endregion #region Virtual Methods /// <summary> /// Called when the data repository needs to fetch data from the repository, either during initial load, or due to query change. /// </summary> /// <param name="dataSource">An instance of the data repository.</param> protected virtual void LoadData(IDataRepository dataSource) { if (!this.IsInDesignMode && dataSource == null) throw new ArgumentNullException("dataSource should not be null."); this.DataSource = dataSource; this.LoadData(); } /// <summary> /// Called when the data repository needs to fetch data from the repository, either during initial load, or due to query change. /// </summary> protected virtual void LoadData() { this.IsBusy = true; this.DataSource.GetData ( this.QueryDescriptor, // QueryDescriptor need to have sort descriptor specified if you enable data paging. // You can add descriptor by grouping the data using UXGridView.GroupDescriptor, or set the sort information in UXGridView.SortDescriptor. (items) => { this.IsBusy = false; this.Items = new PagedCollectionView(items); }, (totalItemCount) => { if (totalItemCount != -1) this.QueryDescriptor.PageDescriptor.TotalItemCount = totalItemCount; }, (error) => { this.IsBusy = false; this.Presenter.ShowErrorMessage( "An exception has occurred during data loading.\n" + "Message: " + error.Message + "\n" + "Stack Trace: " + error.StackTrace); } ); } /// <summary> /// Called when one of the properties in the <see cref="SelectedItem"/> object is changed. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The data related to the event.</param> protected virtual void OnSelectedItemPropertyChanged(object sender, PropertyChangedEventArgs e) { } /// <summary> /// Called when one of the properties in the <see cref="QueryDescriptor"/> object is changed. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The data related to the event.</param> protected virtual void OnQueryChanged(object sender, EventArgs e) { // Perform data retrieval in 0.6ms latency to ensure smooth transition. By default, transition took ~0.3ms. // If transition is not applied in the View, it's not necessary to use ExecuteTimeOut method. Utility.ExecuteTimeOut(this.QueryLatency, () => { if (this.IsPrerequisiteDataLoaded) { this.LoadData(); this.QueryLatency = 0; } }); } /// <summary> /// Called when the <see cref="SelectedItem"/> property changes. /// </summary> /// <param name="oldItem">The old selected item.</param> /// <param name="newItem">The new selected item.</param> protected virtual void OnSelectedItemChanged(T oldItem, T newItem) { } #endregion } } |
DataSearchBoxViewModel |
Copy Code
|
---|---|
using System.Collections; using Intersoft.Client.Data.ComponentModel; using Intersoft.ClientUI.Samples.DataControls.ModelServices; using Intersoft.ClientUI.Samples.Web; using System.ComponentModel; namespace Intersoft.ClientUI.Samples.DataControls.ViewModels { public class DataSearchBoxViewModel : GridViewModelBase<CompanyAsset> { public DataSearchBoxViewModel() : base() { this.IsPrerequisiteDataLoaded = false; if (!this.IsInDesignMode) { this.AssetsStatusSource = AssetsStatusRepository.Instance; this.CompanyDepartmentsSource = CompanyDepartmentsRepository.Instance; this.SuppliersSource = SuppliersRepository.Instance; this.LoadAssetsStatus(); this.LoadCompanyDepartments(); this.LoadSuppliers(); } this.QueryDescriptor.SortDescriptors.Add(new SortDescriptor() { PropertyName = "AssetsID", Direction = ListSortDirection.Ascending }); } private IEnumerable _assetsStatus; private IEnumerable _companyDepartments; private IEnumerable _suppliers; private bool _isAssetsStatusLoaded; private bool _isCompanyDepartmentsLoaded; private bool _isSuppliersLoaded; public IEnumerable AssetsStatus { get { return this._assetsStatus; } set { if (_assetsStatus != value) { _assetsStatus = value; OnPropertyChanged("AssetsStatus"); } } } protected IDataRepository AssetsStatusSource { get; set; } public IEnumerable CompanyDepartments { get { return this._companyDepartments; } set { if (_companyDepartments != value) { _companyDepartments = value; OnPropertyChanged("CompanyDepartments"); } } } protected IDataRepository CompanyDepartmentsSource { get; set; } protected override IDataRepository DataSource { get { return CompanyAssetsRepository.Instance; } } public bool IsAssetsStatusLoaded { get { return _isAssetsStatusLoaded; } set { if (_isAssetsStatusLoaded != value) { _isAssetsStatusLoaded = value; OnPropertyChanged("IsAssetsStatusLoaded"); if (value) this.NotifyPrerequisteDataLoaded(); } } } public bool IsCompanyDepartmentsLoaded { get { return _isCompanyDepartmentsLoaded; } set { if (_isCompanyDepartmentsLoaded != value) { _isCompanyDepartmentsLoaded = value; OnPropertyChanged("IsCompanyDepartmentsLoaded"); if (value) this.NotifyPrerequisteDataLoaded(); } } } public bool IsSuppliersLoaded { get { return _isSuppliersLoaded; } set { if (_isSuppliersLoaded != value) { _isSuppliersLoaded = value; OnPropertyChanged("IsSuppliersLoaded"); if (value) this.NotifyPrerequisteDataLoaded(); } } } public IEnumerable Suppliers { get { return this._suppliers; } set { if (_suppliers != value) { _suppliers = value; OnPropertyChanged("Suppliers"); } } } protected IDataRepository SuppliersSource { get; set; } private void LoadAssetsStatus() { this.AssetsStatusSource.GetData ( (items) => { this.AssetsStatus = items; this.IsAssetsStatusLoaded = true; }, (error) => { this.Presenter.ShowErrorMessage( "An exception has occurred during data loading\n." + "Message: " + error.Message + "Stack Trace: " + error.StackTrace); } ); } private void LoadCompanyDepartments() { this.CompanyDepartmentsSource.GetData ( (items) => { this.CompanyDepartments = items; this.IsCompanyDepartmentsLoaded = true; }, (error) => { this.Presenter.ShowErrorMessage( "An exception has occurred during data loading\n." + "Message: " + error.Message + "Stack Trace: " + error.StackTrace); } ); } private void LoadSuppliers() { this.SuppliersSource.GetData ( (items) => { this.Suppliers = items; this.IsSuppliersLoaded = true; }, (error) => { this.Presenter.ShowErrorMessage( "An exception has occurred during data loading\n." + "Message: " + error.Message + "Stack Trace: " + error.StackTrace); } ); } private void NotifyPrerequisteDataLoaded() { if (this.IsAssetsStatusLoaded && this.IsCompanyDepartmentsLoaded && this.IsSuppliersLoaded) this.IsPrerequisiteDataLoaded = true; } } } |
Notice that you only need to bind the FilterDescriptors in your XAML and handle the QueryChanged in your ViewModel. The UXDataSearchBox will pass the filter descriptors based on FilterMemberPath, FilterOperator and the user's input query.
If the FilterMemberPath property is not specified, UXDataSearchBox will use DisplayMemberPath for the filtering purpose. |