Intersoft ClientUI 8 > ClientUI Controls > Control Library > Editor Controls Overview > UXQueryBuilder |
UXQueryBuilder is an advanced data filtering control for Silverlight and WPF that allows user to visually build complex filter definitions. Designed with a sleek user interface, UXQueryBuilder lets users easily understand complex condition hierarchy and allow users to intuitively interact with each condition. Comes with full MVVM support and integration with all ClientUI data controls, adding the query builder functionality to your business applications is truly a breeze.
The QueryDescriptor class provides powerful and flexible creation of data filters through the use of CompositeFilterDescriptor or CompositeFilterDescription. Consider the following code that represents a composite nested filters:
C# |
Copy Code
|
---|---|
CompositeFilterDescriptor composite = new CompositeFilterDescriptor(); composite.FilterDescriptors.Add(new FilterDescriptor { PropertyName = "Garage", Value = true, Operator = FilterOperator.IsEqualTo }); composite.FilterDescriptors.Add(new FilterDescriptor { PropertyName = "Baths", Value = 2, Operator = FilterOperator.IsGreaterThan }); composite.LogicalOperator = FilterCompositionLogicalOperator.And; CompositeFilterDescriptor outerComposite = new CompositeFilterDescriptor(); outerComposite.FilterDescriptors.Add(new FilterDescriptor { PropertyName = "Price", Value=35000, Operator = FilterOperator.IsLessThan}); outerComposite.FilterDescriptors.Add(new FilterDescriptor { PropertyName="YearBuilt", Value = new DateTime(1988,12,13), Operator = FilterOperator.IsGreaterThan}); outerComposite.FilterDescriptors.Add(composite); outerComposite.LogicalOperator = FilterCompositionLogicalOperator.And; |
As the hierarchy of composite filters gets more complex, it will be significantly more difficult to maintain the codes or manipulate the composite filters in an intuitive manner during runtime. Compare the same code used to produce the visual representation of the filters using UXQueryBuilder:
UXQueryBuilder provides graphical representation and ultimate ease-of-use to interact with complex filters through a sleek and intuitive user interface. UXQueryBuilder serves as a client-side control that translates complex queries in the form of a visual representation and sends the designated filters to QueryDescriptor without writing any code. UXQueryBuilder is a fully customizable query editor which supports industry-standard WCF RIA and DevForce data sources.
This section provides a quick start on how to use UXQueryBulider in the simplest scenario. To learn more about the user interface of UXQueryBuilder, see UI Highlights section below.
UXQueryBuilder is designed to be able to handle both server and client side operations. The server side operation takes advantage of QueryDescriptor class while the client side operation takes advantage of the PagedCollectionView.
For more information on how to configure UXQueryBuilder to handle server-side operation, see How-to: Use UXQueryBuilder for server side operation. Also, to configure UXQueryBuilder to handle client-side operation, see How-to: Use UXQueryBuilder for client side operation.
There are three main parts in UXQueryBuilder: PropertyName, FilterOperator, and Value. The following section explains in details about the approaches used to customize each of these parts and suit UXQueryBuilder to your business model.
Listing properties in property name in UXQueryBuilder can be done in two ways: using ObjectType or FilterPropertiesSource.
ObjectType provides a way to list properties by specifying the type of the model directly into UXQueryBuilder .
Take the following object model as an example.
Order_Detail.cs |
Copy Code
|
---|---|
using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Intersoft.Client.Data.ComponentModel; namespace ClientUI._2012R2.Preview.DomainModel { public partial class Order_Detail { public class Order_DetailFilterMetadata { [Display(Name = "Order ID")] public int OrderID { get; set; } [Display(Name = "Product ID")] public int ProductID { get; set; } [Display(Name = "UnitPrice")] public decimal UnitPrice { get; set; } [Display(Name = "Quantity")] public short Quantity { get; set; } [Display(Name = "Discount")] public float Discount { get; set; } } } } |
The DisplayAttribute determines the display name of the property. If DisplayAttribute does not exist, then the property name will be listed as display name. Bind the object model to the ObjectType property of UXQueryBuilder. The ObjectType takes the Type property of the object model.
XAML |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder ObjectType="{Binding ObjectType}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" /> |
You can also achieve the same result by binding an IEnumerable<CustomClass> to FilterPropertiesSource property of UXQueryBuilder in the view model and providing the respective member path in the view.
C# |
Copy Code
|
---|---|
this._orderDetailsFilterMemberData = new ObservableCollection<FilterMemberData> { new FilterMemberData { PropertyDisplay = "Order ID", PropertyType = typeof(int), PropertyName = "OrderID" }, new FilterMemberData { PropertyDisplay = "Product ID", PropertyType = typeof(int), PropertyName = "ProductID" }, new FilterMemberData { PropertyDisplay = "Unit Price", PropertyType = typeof(decimal), PropertyName = "UnitPrice" }, new FilterMemberData { PropertyDisplay = "Quantity", PropertyType = typeof(short), PropertyName = "Quantity" }, new FilterMemberData { PropertyDisplay = "Discount", PropertyType = typeof(float), PropertyName = "Discount" }, }; |
XAML |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder FilterPropertiesSource="{Binding OrderDetailsFilterMemberData}" QueryOperation="Server" EnableNestedFilter="{Binding EnabledNestedFilter}" PropertyDisplayMemberPath="PropertyDisplay" PropertyNameMemberPath="PropertyName" PropertyTypeMemberPath="PropertyType" /> |
UXQueryBuilder allows room for further customization for generation of property names through the use of IncludeNavigationProperties and PropertyListMode properties. These properties give developers refined control over UXQueryBuilder property generation.
The IncludeNavigationProperties property enables UXQueryBuilder to list nested navigation properties in the object model. You can enable it by setting IncludeNavigationProperties to true.
Using the previous object model:
Order_Detail.cs |
Copy Code
|
---|---|
using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Intersoft.Client.Data.ComponentModel; namespace ClientUI._2012R2.Preview.DomainModel { public partial class Order_Detail { public class Order_DetailFilterMetadata { public int OrderID { get; set; } public int ProductID { get; set; } public decimal UnitPrice { get; set; } public short Quantity { get; set; } public float Discount { get; set; } public Product Product { get; set; } } } } |
XAML |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder ObjectType="{Binding ObjectType}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" IncludeNavigationProperties="True"/> |
XAML |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder FilterPropertiesSource="{Binding ProductsFilterMemberData}" ParentNameMemberPath="ParentName" PropertyDisplayMemberPath="PropertyDisplay" PropertyNameMemberPath="PropertyName" PropertyTypeMemberPath="PropertyType" PropertyPreferredFilterOperatorMemberPath="PreferredFilterOperator" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" IncludeNavigationProperties="True"/> |
To use navigation properties in conjunction with FilterPropertiesSource, you need to specify the ParentNameMemberPath.
C# |
Copy Code
|
---|---|
this._orderDetailsFilterMemberData = new ObservableCollection<FilterMemberData> { new FilterMemberData { PropertyDisplay = "Order ID", PropertyType = typeof(int), PropertyName = "OrderID" }, new FilterMemberData { PropertyDisplay = "Product ID", PropertyType = typeof(int), PropertyName = "ProductID" }, new FilterMemberData { PropertyDisplay = "Unit Price", PropertyType = typeof(decimal), PropertyName = "UnitPrice" }, new FilterMemberData { PropertyDisplay = "Quantity", PropertyType = typeof(short), PropertyName = "Quantity" }, new FilterMemberData { PropertyDisplay = "Discount", PropertyType = typeof(float), PropertyName = "Discount" }, new FilterMemberData { PropertyDisplay = "ProductID", PropertyType = typeof(int), PropertyName = "Product.Product", ParentName = "Product"}, new FilterMemberData { PropertyDisplay = "ProductName", PropertyType = typeof(string), PropertyName = "Product.ProductName", ParentName = "Product"}, }; |
PropertyListMode allows UXQueryBuilder to generate properties based on the FilterMemberAttribute, IgnoreFilterMemberAttribute, DataMemberAttribute and IgnoreDataMemberAtrtibute. PropertyListMode consists of three modes: All, FilterMemberOnly, and FilterMemberAndDataMember. You can specify which properties not to be included during property generation by utilizing the IgnoreFilterMemberAttribute or IgnoreDataMemberAttribute and set the PropertyListMode accordingly.
By setting PropertyListMode to PropertyListMode.All, UXQueryBuilder will list all properties related to the object model. However, this may cause UXQueryBuilder to list unwanted properties.
Setting PropertyListMode to PropertyListMode.FilterMemberOnly will cause UXQueryBuilder to list all properties with the FilterMemberAttribute.
UXQueryBuilder will list all properties with either FilterMemberAttribute or DataMemberAttribute when PropertyListMode is set to PropertyListMode.FilterMemberAndDataMember.
You can customize which properties will be listed by specifying FilterMemberAttribute as follows:
Order_Detail.cs |
Copy Code
|
---|---|
using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Intersoft.Client.Data.ComponentModel; namespace ClientUI._2012R2.Preview.DomainModel { [FilterMetadata(typeof(Order_DetailFilterMetadata))] public partial class Order_Detail { public class Order_DetailFilterMetadata { [FilterMember] public int OrderID { get; set; } [IgnoreFilterMember] public int ProductID { get; set; } [IgnoreFilterMember] public decimal UnitPrice { get; set; } [IgnoreFilterMember] public short Quantity { get; set; } [FilterMember] public float Discount { get; set; } [FilterMember] public Product Product { get; set; } } } } |
FilterPropertiesSource is not affected by PropertyListMode. Simply do not include unwanted properties in the view model.
This section elaborates how developers can customize the filter operator generated by the selected property.
By default, UXQueryBuilder provides predefined operators for common property types.
Numeric types and DateTime: IsEqualTo, IsGreaterThan, IsGreaterThanOrEqualTo, IsLessThan, IsLessThanOrEqualTo, IsNotEqualTo.
String type: Contains, DoesNotContain, EndsWith, IsContainedIn, IsEqualTo, StartsWith, IsNullOrEmpty.
Other types: IsEqualTo, IsNotEqualTo.
UXQueryBuilder provides the option for developers to include a specific set of filter operators by excluding undesired filter operators. The following example will demonstrate how to exclude specific set of operators in both ObjectType and FilterPropertiesSource scenario.
Order_Detail.cs |
Copy Code
|
---|---|
using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Intersoft.Client.Data.ComponentModel; namespace ClientUI._2012R2.Preview.DomainModel { [FilterMetadata(typeof(Order_DetailFilterMetadata))] public partial class Order_Detail { public class Order_DetailFilterMetadata { [FilterMember(ExcludeFilterOperator = ExcludeFilterOperator.IsEqualTo ^ ExcludeFilterOperator.IsGreaterThan ^ ExcludeFilterOperator.IsGreaterThanOrEqualTo)] public int OrderID { get; set; } [IgnoreFilterMember] public int ProductID { get; set; } [IgnoreFilterMember] public decimal UnitPrice { get; set; } [IgnoreFilterMember] public short Quantity { get; set; } [FilterMember] public float Discount { get; set; } [FilterMember] public Product Product { get; set; } } } } |
You can specify multiple ExcludeFilterOperator by using the ^ (caret) sign.
Currently, ExcludeFilterOperator is not available in FilterPropertiesSource.
PreferredFilterOperator is used to auto-select a filter operator when a property is selected, giving a more intuitive experience in using the UXQueryBuilder.
Order_Detail.cs |
Copy Code
|
---|---|
using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Intersoft.Client.Data.ComponentModel; namespace ClientUI._2012R2.Preview.DomainModel { [FilterMetadata(typeof(Order_DetailFilterMetadata))] public partial class Order_Detail { public class Order_DetailFilterMetadata { [FilterMember(PreferredFilterOperator = FilterOperator.IsGreaterThanOrEqualTo)] public int OrderID { get; set; } [IgnoreFilterMember] public int ProductID { get; set; } [IgnoreFilterMember] public decimal UnitPrice { get; set; } [IgnoreFilterMember] public short Quantity { get; set; } [FilterMember] public float Discount { get; set; } [FilterMember] public Product Product { get; set; } } } } |
Simply add ExcludeFilterOperator property in the your custom class and specify the PropertyPreferredFilterOperatorMemberPath in the view.
C# |
Copy Code
|
---|---|
this._orderDetailsFilterMemberData = new ObservableCollection<FilterMemberData> { new FilterMemberData { PropertyDisplay = "Order ID", PropertyType = typeof(int), PropertyName = "OrderID", PreferredFilterOperator = FilterOperator.IsGreaterThanOrEqualTo}, new FilterMemberData { PropertyDisplay = "Product ID", PropertyType = typeof(int), PropertyName = "ProductID" }, new FilterMemberData { PropertyDisplay = "Unit Price", PropertyType = typeof(decimal), PropertyName = "UnitPrice" }, new FilterMemberData { PropertyDisplay = "Quantity", PropertyType = typeof(short), PropertyName = "Quantity" }, new FilterMemberData { PropertyDisplay = "Discount", PropertyType = typeof(float), PropertyName = "Discount" }, new FilterMemberData { PropertyDisplay = "ProductID", PropertyType = typeof(int), PropertyName = "Product.Product", ParentName = "Product"}, new FilterMemberData { PropertyDisplay = "ProductName", PropertyType = typeof(string), PropertyName = "Product.ProductName", ParentName = "Product"}, }; |
XAML |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder FilterPropertiesSource="{Binding OrderDetailsFilterMemberData}" QueryOperation="Server" PropertyDisplayMemberPath="PropertyDisplay" ParentNameMemberPath="ParentName" PropertyNameMemberPath="PropertyName" PropertyTypeMemberPath="PropertyType" PropertyPreferredFilterOperatorMemberPath="PreferredFilterOperator" /> |
By default, UXQueryBuilder provides four value editors for common data types as follows:
String/Other : UXTextBox
DateTime : UXDateTimePicker
Boolean/Enum : UXComboBox
Numeric : UXCurrencyEditor
DataListProvider provides a convenient way to enhance the filter experience by providing a predefined set of values to the value editor in the object model. Suppose the user would like to search for SupplierID. It will be quite an unpleasant experience if the user would have to type the ID of the Supplier to execute the filter process. In this scenario, DataListProvider can be used to enhance the filter experience.
ModelSnippet |
Copy Code
|
---|---|
namespace ClientUI._2012R2.Preview.DomainModel { [FilterMetadata(typeof(ProductFilterMetadata))] [DisplayMember("ProductName")] public partial class Product { public class ProductFilterMetadata { [FilterMember] [DataListProvider("ClientUI._2012R2.Preview.DataListProvider.SupplierDataListProvider")] [Display(Name = "Supplier ID")] public System.Nullable<int> SupplierID { get; set; } } } } |
SupplierDataListProvider.cs |
Copy Code
|
---|---|
using System; using System.Collections; using System.Linq; using ClientUI._2012R2.Preview.DomainModel; using IdeaBlade.EntityModel; using Intersoft.Client.Data.ComponentModel; using Intersoft.Client.Data.ComponentModel.CollectionViews; using Intersoft.Client.UI.Editors; namespace ClientUI._2012R2.Preview.DataListProvider { public class SupplierDataListProvider : EditorDataProvider { public SupplierDataListProvider() { this._manager = new NorthwindEntities(); this.IsAsync = true; this.DisplayMemberPath = "CompanyName"; this.SelectedValuePath = "SupplierID"; } private NorthwindEntities Manager { get { return this._manager ?? (this._manager = new NorthwindEntities()); } } private NorthwindEntities _manager; public override bool IsAsync { get; set; } public override IEnumerable GetData() { throw new NotImplementedException(); } public override object GetSingle(object item) { throw new NotImplementedException(); } public override void BeginGetDataAsync(Guid token) { if (this.Manager != null) { var supplierQuery = this.Manager.Suppliers; this.Manager.ExecuteQueryAsync(supplierQuery, op => { if (op.CompletedSuccessfully) { this.EndGetDataAsync(token, op.Results); } }); } } public override void BeginSingleAsync(Guid token, object item) { if (this.Manager != null) { FilterDescriptor filterDescriptor = item as FilterDescriptor; FilterDescription filterDescription = item as FilterDescription; PropertyGridDefinition property = item as PropertyGridDefinition; int supplierID = 0; if (filterDescriptor != null && filterDescriptor.Value != null) supplierID = (int)filterDescriptor.Value; else if (filterDescription != null && filterDescriptor.Value != null) supplierID = (int)filterDescription.Value; else if (property != null && property.Value != null) supplierID = (int)property.Value; var supplierQuery = this.Manager.Suppliers.Where(o => o.SupplierID == supplierID); this.Manager.ExecuteQueryAsync(supplierQuery, op => { if (op.CompletedSuccessfully) { this.EndGetSingleAsync(token, op.Results.FirstOrDefault()); } }); } } public override string DisplayMemberPath { get; set; } public override string SelectedValuePath { get; set; } } } |
The following illustration shows the value editor automatically changed to UXComboBox when DataListProvider is used. When users select a value from the combobox control, the actual value (usually the unique ID) of the selection will be set to the filter descriptor behind the scene. This powerful feature is particularly useful to address common business applications such as in master-detail scenarios.
You can customize the default editors provided by UXQueryBuilder by specifying explicit styles and target the appropriate value editor.
XAML |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder Intersoft:DockPanel.Dock="Top" ObjectType="{Binding ObjectType}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" > <Intersoft:UXQueryBuilder.DateTimeEditorStyle> <Style TargetType="Intersoft:UXDateTimePicker"> <Setter Property="MinHeight" Value="24" /> <Setter Property="CornerRadius" Value="0,4,4,0" /> <Setter Property="IsAdvancingCaret" Value="True"/> <Setter Property="FirstDayOfWeek" Value="Monday"/> </Style> </Intersoft:UXQueryBuilder.DateTimeEditorStyle> <Intersoft:UXQueryBuilder.DefaultEditorStyle> <Style TargetType="Intersoft:UXTextBox"> <Setter Property="MinHeight" Value="24" /> <Setter Property="CornerRadius" Value="0,4,4,0" /> <Setter Property="WatermarkText" Value="Specify Value"/> <Setter Property="WatermarkTextVisibility" Value="Visible"/> <Setter Property="MaxLength" Value="250"/> </Style> </Intersoft:UXQueryBuilder.DefaultEditorStyle> </Intersoft:UXQueryBuilder> |
The following snippet code shows how to customize the default editor using EditorDefinition.
XAML |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder Intersoft:DockPanel.Dock="Top" ObjectType="{Binding ObjectType}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server"> <Intersoft:UXQueryBuilder.EditorDefinitions> <Intersoft:EditorDefinition TargetType="System.Nullable'1[System.DateTime]"> <Intersoft:EditorDefinition.EditorStyle> <Style TargetType="Intersoft:UXDateTimePicker"> <Setter Property="MinHeight" Value="24" /> <Setter Property="CornerRadius" Value="0,4,4,0" /> <Setter Property="IsAdvancingCaret" Value="True" /> <Setter Property="FirstDayOfWeek" Value="Monday" /> </Style> </Intersoft:EditorDefinition.EditorStyle> </Intersoft:EditorDefinition> <Intersoft:EditorDefinition> <Intersoft:EditorDefinition.EditorStyle> <Style TargetType="Intersoft:UXCurrencyEditor"> <Setter Property="MaxLength" Value="5" /> <Setter Property="MinHeight" Value="24" /> <Setter Property="CornerRadius" Value="0,4,4,0" /> <Setter Property="WatermarkText" Value="Specify Value" /> <Setter Property="WatermarkTextVisibility" Value="Visible" /> </Style> </Intersoft:EditorDefinition.EditorStyle> <Intersoft:EditorDefinition.PropertyDefinitions> <Intersoft:PropertyDefinition Name="OrderID" Type="System.Int32"></Intersoft:PropertyDefinition> </Intersoft:EditorDefinition.PropertyDefinitions> </Intersoft:EditorDefinition> </Intersoft:UXQueryBuilder.EditorDefinitions> </Intersoft:UXQueryBuilder> |
IEditorSelector provides a way to customize the default editor programmatically.
EditorSelector.cs |
Copy Code
|
---|---|
using Intersoft.Client.UI.Editors; using Intersoft.Client.UI.Aqua.UXInput; namespace ClientUI._2012R2.Preview.Selectors { public class EditorSelector : IEditorSelector { public void ResolveSelector(EditorSelectorArgs args) { switch (args.PropertyName) { case "UnitPrice": UXCurrencyEditor unitPriceEditor = args.EditorObject as UXCurrencyEditor; unitPriceEditor.EditMask = "C2"; break; case "UnitsInStock": UXCurrencyEditor unitsInStockEditor = args.EditorObject as UXCurrencyEditor; unitsInStockEditor.EditMask = "N0"; break; case "UnitsOnOrder": UXCurrencyEditor unitsOnOrderEditor = args.EditorObject as UXCurrencyEditor; unitsOnOrderEditor.EditMask = "N0"; break; } } } } |
XAML |
Copy Code
|
---|---|
<Intersoft:UXPage.Resources> <Selector:EditorSelector x:Key="EditorSelector" /> </Intersoft:UXPage.Resources> <Intersoft:UXQueryBuilder ObjectType="{Binding ObjectType}" EditorSelector="{StaticResource EditorSelector}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" /> |
You can use DataTemplate to override the default value editor.
XAML |
Copy Code
|
---|---|
<Intersoft:UXPage.Resources> <DataTemplate x:Key="NumericEditorTemplate"> <Intersoft:UXNumericUpDown Value="{Binding Value, Mode=TwoWay}" /> </DataTemplate> </Intersoft:UXPage.Resources> <Intersoft:UXQueryBuilder ObjectType="{Binding ObjectType}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" NumericEditorTemplate="{StaticResource NumericEditorTemplate}" /> |
You can use EditorDefinition to override the default editor.
Example Title |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder ObjectType="{Binding ObjectType}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server"> <Intersoft:UXQueryBuilder.EditorDefinitions> <Intersoft:EditorDefinition TargetType="System.Nullable'1[System.DateTime]"> <Intersoft:EditorDefinition.EditorTemplate> <DataTemplate> <Intersoft:UXDateTimeUpDown Value="{Binding Value, Mode=TwoWay}" CornerRadius="0,4,4,0" MinHeight="24" MinWidth="100" /> </DataTemplate> </Intersoft:EditorDefinition.EditorTemplate> </Intersoft:EditorDefinition> <Intersoft:EditorDefinition> <Intersoft:EditorDefinition.EditorTemplate> <DataTemplate> <Intersoft:UXNumericUpDown Value="{Binding Value, Mode=TwoWay}" CornerRadius="0,4,4,0" MinHeight="24" MinWidth="100" /> </DataTemplate> </Intersoft:EditorDefinition.EditorTemplate> <Intersoft:EditorDefinition.PropertyDefinitions> <Intersoft:PropertyDefinition Name="Freight" Type="System.Nullable'1[System.Decimal]" /> </Intersoft:EditorDefinition.PropertyDefinitions> </Intersoft:EditorDefinition> </Intersoft:UXQueryBuilder.EditorDefinitions> </Intersoft:UXQueryBuilder> |
You can also override the default value editors programmatically using IEditorSelector.
EditorSelector.cs |
Copy Code
|
---|---|
using System.Windows; using Intersoft.Client.UI.Controls; using Intersoft.Client.UI.Editors; using Intersoft.Client.UI.Aqua.UXInput; namespace ClientUI._2012R2.Preview.Selectors { public class EditorSelectorTemplate : IEditorSelector { public DataTemplate UnitsInStockEditor { get; set; } public DataTemplate UnitsOnOrderEditor { get; set; } public DataTemplate UnitPriceEditor { get; set; } public void ResolveSelector(EditorSelectorArgs args) { if (args.PropertyName == "UnitPrice") { if (!(args.EditorObject is UXNumericUpDown)) args.EditorTemplate = this.UnitPriceEditor; } if (args.PropertyName == "UnitsInStock") { if (!(args.EditorObject is UXSliderBar)) args.EditorTemplate = this.UnitsInStockEditor; } if (args.PropertyName == "UnitsOnOrder") { if (!(args.EditorObject is UXSliderBar)) args.EditorTemplate = this.UnitsOnOrderEditor; } } } } |
XAML |
Copy Code
|
---|---|
<Intersoft:UXPage.Resources> <DataTemplate x:Key="UnitPriceEditor"> <Intersoft:UXNumericUpDown MinWidth="100" MinHeight="24" CornerRadius="0,4,4,0" Value="{Binding Value, Mode=TwoWay}" /> </DataTemplate> <DataTemplate x:Key="UnitsOnOrderEditor"> <Intersoft:UXSliderBar Value="{Binding Value, Mode=TwoWay}" Maximum="100" Minimum="0" LargeChange="10" SmallChange="1"/> </DataTemplate> <DataTemplate x:Key="UnitsInStockEditor"> <Intersoft:UXSliderBar Value="{Binding Value, Mode=TwoWay}" Maximum="100" Minimum="0" LargeChange="10" SmallChange="1"/> </DataTemplate> <Selector:EditorSelectorTemplate x:Key="EditorSelector" UnitPriceEditor="{StaticResource UnitPriceEditor}" UnitsOnOrderEditor="{StaticResource UnitsOnOrderEditor}" UnitsInStockEditor="{StaticResource UnitsInStockEditor}" /> </Intersoft:UXPage.Resources> <Intersoft:UXQueryBuilder ObjectType="{Binding ObjectType}" EditorSelector="{StaticResource EditorSelector}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" /> |
You can also specify EditorType in the model to override the default editor.
Order_Detail.cs |
Copy Code
|
---|---|
[FilterMetadata(typeof(ProductFilterMetadata))] [DisplayMember("ProductName")] public partial class Product { public class ProductFilterMetadata { [FilterMember(EditorTypeName = "ClientUI._2012R2.Preview.Views.UXQueryBuilder.QueryBuilderProductNameSelector")] [Display(Name = "Product Name")] public string ProductName { get; set; } } } |
When EnableNestedFilter property is set to true, UXQueryBuilder enables the creation of nested filters. You can set EnableNestedFilter to false if you do not need the user to create complex nested filters. EnableNestedFilter will not have any effect if there is only one filter item in the filter collection.
UXQueryBuilder enables predefined composite filter to take effect upon first load by simply creating a composite filter and bind the composite filter to the CompositeFilter property.
C# |
Copy Code
|
---|---|
CompositeFilterDescriptor composite = new CompositeFilterDescriptor(); composite.FilterDescriptors.Add(new FilterDescriptor() { PropertyName = "OrderDate", Value = new DateTime(1996, 1, 1), Operator = FilterOperator.IsGreaterThanOrEqualTo }); composite.FilterDescriptors.Add(new FilterDescriptor() { PropertyName = "OrderDate", Value = new DateTime(1997, 1, 1), Operator = FilterOperator.IsLessThanOrEqualTo }); this.PredefinedCompositeFilterDescriptor = composite; this.QueryDescriptor.FilterDescriptors.Add(composite); |
XAML |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder ObjectType="{Binding ObjectType}" CompositeFilter="{Binding PredefinedCompositeFilterDescriptor}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" /> |
UXQueryBuilder features save and loading of filters for future reusability. After creating a complex set of filters, users are able to save the filter into industry-standard JSON (JavaScript Object Notation) format and load them. This feature is not enabled by default. For example, you can create a UXButton with command that calls UXQueryBuilderCommands.Save or UXQueryBuilderCommands.Load accordingly.
XAML |
Copy Code
|
---|---|
<StackPanel> <Intersoft:UXButton Command="Intersoft:UXQueryBuilderCommands.Save" Content="Save Filters" CommandTarget="{Binding ElementName=UXQueryBuilder}"/> <Intersoft:UXButton Command="Intersoft:UXQueryBuilderCommands.Load" Content="Load Filters" CommandTarget="{Binding ElementName=UXQueryBuilder}"/> </StackPanel> |
EditMouseGesture property defines the mouse gesture needed for UXQueryBuilder to enter editing mode, consisting of SingleClick, DoubleClick and SecondClick.
Localization is available to UXQueryBuilder by utilizing the ResourceOverride and overriding each string, shown as follows:
C# |
Copy Code
|
---|---|
<Intersoft:UXQueryBuilder Intersoft:DockPanel.Dock="Top" ObjectType="{Binding ObjectType}" FilterDescriptors="{Binding QueryDescriptor.FilterDescriptors, Mode=TwoWay}" QueryOperation="Server" EnableNestedFilter="{Binding EnabledNestedFilter}" IncludeNavigationProperties="{Binding IncludeNavigationProperties}" PropertyListMode="{Binding SelectedPropertyListMode}" > <Intersoft:UXQueryBuilder.ResourceOverride> <Intersoft:UXQueryBuilderResource BooleanValueFalse="Falsch" BooleanValueTrue="Wahr" /> </Intersoft:UXQueryBuilder.ResourceOverride> </Intersoft:UXQueryBuilder> |
The following section highlights the UI elements in UXQueryBuilder.
If there is only one item, UXQueryBuilder will hide the composite logical operator button, as this element is considered to have no use when there is not at least two filter items.
When the Add Condition button is clicked, UXQueryBuilder will smooth animate to show the composite logical operator button, as well as adding one more item to the filter items collection. You can also use Ctrl+Shift+A to add condition.
If EnableNestedFilter is set to true and there is more than one filter item, then Add Nested Condition button will appear. You cannot add a nested filter when there is only one item in the collection.
If the Add Group button is pressed, UXQueryBuilder will convert the current filter item to a composite filter, retaining the previous filter.
The nested condition will also be added with a smooth animation.
The composite logical operator is used to change the logical operator for the currently selected composite filter. You can also Add Condition, Add Group and Delete inside the dropdown.
When Delete button is pressed, UXQueryBuilder will delete the current filter item. You can also press Delete on the keyboard to delete the filter item.
If there is only one filter item, UXQueryBuilder will revert to its original state, with composite logical operator button hidden.
When Clear button is pressed, UXQueryBuilder will automatically clear all filter items and restore UXQueryBuilder to initial state.
When Filter button is pressed, the filter process takes place. UXQueryBuilder automatically validates when either PropertyName or Value is not specified. You can also use Shift+Enter to execute the filter process anytime.
If all filters are considered valid, then the filter process will continue.
Despite its nature to handle complex queries, UXQueryBuilder is designed to give an intuitive keyboard navigation experience.
The following figure will illustrate how Tab cycles is handle in UXQueryBuilder.
Pressing Up and Down key when focused on a filter item will intuitively cycle between filter items.
Pressing Delete will delete the current filter item. Pressing Ctrl+Shift+A will either Add Condition (when focused to an item) or Add Nested Condition (when focused to composite logical operator button or add condition button).