As of ComponentOne's November 2017 release, end users can now easily write expressions using ExpressionEditor, a stand-alone desktop control for WinForms, WPF, and UWP that enters, evaluates, and passes expressions.

Expressions — which are representations of a value — are widely used throughout data management, data visualization, and report definitions to retrieve, calculate, display, group, sort, filter parameters, and format data. In the past, developers wrote all the expressions, which were mostly hard-coded in the application.

Today, end users want more control over data to visualize and analyze it based on their business needs. While experienced developers might not find writing expressions difficult, it’s not easy for end users to write them without using a visual editor. ExpressionEditor changes this, giving developers and end users alike an effortless expression-writing experience.

While end users will benefit from being able write expressions effortlessly, developers can also benefit from ExpressionEditor by taking advantage of advanced features to write complex expressions in less time and without errors.

ExpressionEditor provides a full-fledged IDE editing experience that includes IntelliSense, syntax highlighting, error information on entering invalid expressions, and more.

In this blog, we'll primarily talk about:

Major Features

Stand-alone ExpressionEditor

Expression editors are typically available as built-in editors with controls — like grids, charts, and reports — where these editors are normally used. ComponentOne’s ExpressionEditor is a complete stand-alone editor that can be integrated with any data-bound control.

Smart Code Completion (Visual Studio-like IntelliSense)

ExpressionEditor reduces the need to remember functions, displaying them along with their definitions. As you start typing in the editor, a list of available functions that match the typed characters is displayed in a selectable drop-down, speeding up the search you would otherwise have to perform manually.

For example, if you type “r” and wait for the code completion to list all methods that start with “r,” Rand() method will appear at the top of the list. Press the tab key, and it fills in the Rand. You can type “b” after “r,” and the RandBetween method will be automatically added after pressing the tab key.

Smart Code Completion

Syntax Highlighting

With Syntax highlighting, it becomes easier for users to identify distinct elements in an expression. Displaying expression elements in different colors makes expressions more readable and easier to understand.

In the following screenshot, expression elements are color-coded:

  • Function names are green.
  • Fields are purple.
  • Numbers are pink.
  • Strings are brown.

Syntax Highlighting

200+ Built-in Functions and Operators

ComponentOne ExpressionEditor provides more than 200 built-in simple and complex functions and operators.

Broadly, these functions and operators are categorized as follows:

  • Aggregate functions
  • DateTime functions
  • Logical functions
  • Math functions
  • Convert functions
  • Text functions
  • Operators

UI Components

ComponentOne's ExpressionEditor is primarily comprised of two components:

  1. C1ExpressionEditor — This is the edit area, where users type expressions. Features like smart code completion and syntax highlighting are available in this component.

  2. C1ExpressionEditorPanel — This panel displays a categorized view of built-in functions and operators.

ExpressionEditor UI Components

Setting Up ExpressionEditor

In this section, we’ll go through the steps a developer needs to take to set up ExpressionEditor for end users by integrating the two UI components.

Create an Expression Editor in a WPF project following these steps:

1. Add an Expression Editor component to the Visual Studio Toolbox using C1.WPF.ExpressionEditor.4 dll, as shown below.

Adding an expression editor component

2. Add references to C1.WPF.ExpressionEditor.4 and C1.WPF.4 dlls and build the project.

3. Open MainWindow.xaml and replace the existing XAML with the following code:

<Window x:Class="ExpressionEditorDemo.MainWindow"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml"
 mc:Ignorable="d"
 d:DesignHeight="400" d:DesignWidth="500">
  <Grid>
    <Border BorderBrush="Black" BorderThickness="0,0,01">
      <Grid Background="White">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
      </Grid.RowDefinitions>
<c1:C1ExpressionEditor x:Name="ExpressionEditor" MinHeight="100" Width="{Binding
ActualWidth, ElementName=ExpressionPanel}"/>
<c1:C1ExpressionEditorPanel x:Name="ExpressionPanel" ExpressionEditor="{Binding
ElementName=ExpressionEditor}" Grid.Row="1"/>
<StackPanel Orientation="Horizontal" Grid.Row="2">
      <TextBlock Text="Result:" FontWeight="Bold"/>
      <TextBlock x:Name="Result" Text="" />
</StackPanel>
<TextBlock x:Name="Errors" Grid.Row="3" Foreground="Red" TextWrapping="Wrap"
HorizontalAlignment="Left" VerticalAlignment="Top" MinHeight="25" />
           </Grid>
        </Border>
      </Grid>
     </Window>

4. Open MainWindow.xaml.cs and add the following code for the ExpressionChanged event:

public MainWindow()
        {
        InitializeComponent();
      ExpressionEditor.ExpressionChanged += ExpressionEditor_ExpressionChanged;
        }

private void ExpressionEditor_ExpressionChanged(object sender, EventArgs e)
         {
           C1ExpressionEditor editor = sender as C1ExpressionEditor;

           if (!editor.IsValid)
           {
             Result.Text = "";
             Errors.Text = "";

          editor.GetErrors().ForEach(x => {Errors.Text += x.FullMessage + "\n";});
              }
              else
          {
                Result.Text = editor.Evaluate()?.ToString();
                Errors.Text = "";

           }
         }

This code evaluates the expression entered in ExpressionEditor and displays the result for valid expressions in the result textbox. It also displays errors for invalid expressions in the error textbox.

5. Build and run the application.

6. Enter a valid expression in the category box.

Using ExpressionEditor

In the above section, we saw how to set up ExpressionEditor. Next, we’ll take look at how to use ExpressionEditor with any data-bound control. For the scope of this blog, we’ll briefly describe how to use ExpressionEditor with the ComponentOne FlexGrid control.

While viewing data in a grid, users often need to view selective data. FlexGrid lets users filter data based on different criteria by providing an out-of-box filter bar. However, at times, a user might need to accomplish multi-condition filtering across several columns using operators. In those scenarios, ExpressEditor is helpful, because it enables users to easily write these kind of filter expressions quickly.

Using ExpressionEditor

In the screenshot above, the expression ReorderLevel<10 lets end users define a filter criterion to display only those rows in which a product’s reorder level is below 10. You can write any expression to filter records just as we did in this example.

Integration of ExpressionEditor with the FlexGrid control can be done at design time — by setting AllowEditingExpression property to true — or through code.

Implement ExpressionEditor to FlexGrid through code using these steps:

1. To filter records, you must set the editor's data source as C1FlexGrid data source.

ExpressionEditor.DataSource = flexGrid.CollectionView.CurrentItem;

2. Now, provide an expression to filter records with using flexGrid.CollectionView.Filter as shown below:

ExpressionEditor.Expression = "[Price] < 1000";

flexGrid.CollectionView.Filter = new Predicate<object>(Contains);

 private bool Contains(object obj)
   {
               C1ExpressionEditor _editor = new C1ExpressionEditor();
    _editor.Expression = ExpressionEditor.Expression;
    _editor.DataSource = obj as Product;
    var value = _editor.Evaluate();
    var ret = true;
    if (value != null)
        Boolean.TryParse(value.ToString(), out ret);
      return ret;
   }

In the next blog post, we'll talk in-depth about using ExpressionEditor with different data-bound controls.