Skip to main content

Fluent API Support

  • 4 minutes to read

Fluent APIs utilize method cascading to relay the instruction context of a subsequent call. By doing so, a Fluent API follows the same natural language rules as those utilized by people. As a result, a well-constructed Fluent API provides more human-friendly code that is easier to perceive and understand.

Tip

To get started with Fluent API concepts, refer to the following article: Code First Fluent API.

The DevExpress MVVM Framework provides extension methods to build Fluent API expressions for any task: from binding simple properties to relating MVVM behaviors with specific events.

Property Binding and UI Triggers

Related article: Data Bindings and Notifications

  • Simple property binding.

    mvvmContext.ViewModelType = typeof(ViewModel);
    var fluentAPI = mvvmContext.OfType<ViewModel>();
    fluentAPI.SetBinding(editor, e => e.EditValue, x => x.Title);
    //ViewModel
    public virtual string Title { get; set; }
    
  • Binding to nested properties.

    mvvmContext.ViewModelType = typeof(ViewModel);
    var fluent = mvvmContext.OfType<ViewModel>();
    fluent.SetBinding(editor, e => e.EditValue, x => x.Child.Title);
    //ViewModel
    public NestedViewModel Child { get; private set; }
    //NestedViewModel
    public virtual string Title { get; set; }
    
  • UI Triggers.

    mvvmContext.ViewModelType = typeof(UIViewModel);
    var fluentAPI = mvvmContext.OfType<UIViewModel>();
    fluentAPI.SetTrigger(x => x.IsActive, (active) =>
    {
        label.Text = active ? "Active" : "Inactive";
    });
    //UIViewModel
    public virtual bool IsActive { get; set; }
    

Command Binding

Related article: Commands

  • Parameterized commands with CanExecute conditions.

    mvvmContext.ViewModelType = typeof(ViewModel);
    int parameter = 4;
    var fluentAPI = mvvmContext.OfType<ViewModel>();
    fluentAPI.BindCommand(commandButton, (x, p) => x.DoSomething(p), x => parameter);
    
    //ViewModel
    public class ViewModel {
        public void DoSomething(int p) {
            //. . .
        }
    
        public bool CanDoSomething(int p) {
            return (2 + 2) == p;
        }
    }
    
  • Asynchronous commands.

    mvvmContext.ViewModelType = typeof(ViewModel);
    var fluentAPI = mvvmContext.OfType<ViewModel>();
    fluentAPI.BindCommand(commandButton, x => x.DoSomethingAsynchronously());
    fluentAPI.BindCancelCommand(cancelButton, x => x.DoSomethingAsynchronously());
    
    //ViewModel
    public class ViewModelWithAsyncCommandAndCancellation 
        public Task DoSomethingAsynchronously() {
            return Task.Factory.StartNew(() =>
            {
                var asyncCommand = this.GetAsyncCommand(x => x.DoSomethingAsynchronously());
                for(int i = 0; i <= 100; i++) {
                    if(asyncCommand.IsCancellationRequested) // cancellation check
                        break;
                    //. . .
                }
            });
        }
    }
    
  • The WithCommand extension allows you to bind a command to one or multiple target UI elements.

    //binding to one UI element
    fluent.WithCommand(x => x.DoSomething())
           .Bind(btnDoSomething);
    //binding to multiple UI elements
    fluent.WithCommand(x => x.DoSomething())
           .Bind(btn1DoSomething)
           .Bind(btn2DoSomething);
    fluent.WithCommand(x => x.DoSomethingAsynchronously())
           .Bind(btnDo)
           .BindCancel(btnCancel);
    
  • Command triggers allow you to automatically call specific methods before the target command is executed, after that, or when this command’s CanExecute condition changes.

    fluent.WithCommand(x => x.DoSomething())
           .After(() => AfterDoSomethingExecuted());
    fluent.WithCommand(x => x.DoSomething())
           .Before(() => BeforeDoSomethingExecuted());
    fluent.WithCommand(x => x.DoSomething())
           .OnCanExecuteChanged(() => WhenCanDoSomethingChanged());
    

Attaching Behaviors

Related article: Behaviors

  • Confirmation behavior.

    mvvmContext.WithEvent<ChangingEventArgs>(editor, "EditValueChanging")
        .Confirmation(behavior =>
        {
            behavior.Caption = "CheckEdit State changing";
            behavior.Text = "This checkEdit's checked-state is about to be changed. Are you sure?";
        });
    
  • Event-To-Command Behaviors

    mvvmContext.ViewModelType = typeof(ViewModel);
    mvvmContext.WithEvent<ViewModel, EventArgs>(thirdPartyButton, "Click")
        .EventToCommand(x => x.DoSomething());
    
    //ViewModel
    public void DoSomething() {
        //. . .
    }
    
  • Key-To-Command and Keys-To-Command Behaviors

    mvvmContext.OfType<KeyAwareViewModel>()
            .WithKey(memo, Keys.A)
            .KeyToCommand(x => x.OnAKey());
    mvvmContext.OfType<KeyAwareViewModel>()
            .WithKeys(memo, new Keys[] { Keys.A, Keys.B, Keys.C })
            .KeysToCommand(x => x.OnKey(Keys.None), args => args.KeyCode);