Skip to content

Latest commit

 

History

History
120 lines (116 loc) · 5.16 KB

README.md

File metadata and controls

120 lines (116 loc) · 5.16 KB

Bindery

Bindery aims to support fluent MVVM binding definition for WinForms applications.

Projects

  • Bindery:
    • Contains the static Create factory class
    • Dependent on the System.Reactive package
    • Please note that it may be necessary to install the System.Reactive.Compatibility package in the main project of a consuming application in order to resolve conflicts between the System.Reactive package and older versions of System.Reactive-related libraries (such as Sytem.Reactive.Linq).

Assumptions

  • A View Model is a binding source, an object of any type. Full binding functionality requires a View Model to properly implement INotifyPropertyChanged.
  • A Control is a binding target, an object that implements IBindableComponent. A Control supports the full range of binding functionality.
  • A Target is a binding target, an object of any type. A Target only supports a limited set of binding functionality.
  • A Command is an object that implements ICommand.

Code Examples

Binding

Create a root binder for the view model
var binder = Bindery.Create.Binder(viewModel);
Create a root binder and set the default subscription scheduler to schedule actions on the form's thread
var binder = Bindery.Create.Binder(viewModel, new ControlScheduler(form));
Dispose of a binder

Diposing of a binder removes all bindings and disposes of all subcriptions created by the binder.

binder.Dispose();
Register external disposables with the binder

This can be used to tie the lifetime of other objects to the binder's lifetime.

binder.RegisterDisposable(disposableViewModel, disposableCommand);
Bind a view model property to a control property
// Two-way binding
binder.Control(textBox).Property(c => c.Text).Bind(vm => vm.Name); 
// One-way binding from source to control
binder.Control(form).Property(c => c.UseWaitCursor).Get(vm => vm.IsBusy); 
// One-way binding from control to source
binder.Control(textBox).Property(c => c.Text).Set(vm => vm.Name); 
Bind an integer view model property to a string control property
binder.Control(textBox).Property(c => c.Text).Get(vm => vm.Age, Convert.ToString);
Bind a button's Click event to a command

This also "binds" the control's Enabled property to the command's CanExecute method.

ICommand command = new CommandImplementation(viewModel);
binder.Control(button).OnClick(command);
Bind a form's MouseMove event to a command
ICommand command = new CommandImplementation(viewModel);
binder.Control(form).OnEvent<MouseEventArgs>("MouseMove")
  .Transform(o => o.Where(ctx => ctx.Args.Button==MouseButtons.Left).Select(ctx => new {ctx.Args.X, ctx.Args.Y})) 
  // Mouse coords are passed to command.Execute()
  .Execute(command);
Bind a form's MouseMove event arguments to a view model property
binder.Control(form).OnEvent<MouseEventArgs>("MouseMove")
  .Transform(o => o.Select(ctx => new MyCoord{X = ctx.Args.X, Y = ctx.Args.Y}))
  .Set(vm => vm.CurrentMouseCoords);
Bind to a non-control target object

Non-control targets support a limited set of binding options. Two-way binding and one-way binding from target to source are not supported.

binder.Target(target).Property(t => t.Status).Get(vm => vm.Status);

Observable subscriptions

Trigger an action when a view model property changes
binder.OnPropertyChanged(vm => vm.ErrorMessage).Subscribe(msg => DisplayErrorDialog(msg));
Subscribe to a button's Click event to close the form
binder.Control(cancelButton).OnClick().Subscribe(ctx => form.Close());
Subscribe to a form's Closed event to dispose of the binder
binder.Control(form).OnEvent("Closed").Subscribe(ctx => binder.Dispose());
Create an observable subscription to execute a command
binder.Observe(viewModel.Observable).Execute(command);
Overriding the default scheduler to execute the command immediately on each observed object
binder.Observe(viewModel.Observable).ObserveOn(Scheduler.Immediate).Execute(command);
Subscribe to an observable with full subscription syntax support
binder.Observe(viewModel.Observable).Subscribe(
  ctx=>ctx.OnNext(oVal => OnNextAction(oVal))
       .OnError(ex => HandleException(ex))
       .OnComplete(() => OnCompleteAction()));
Create an observable subscription to call an async method
binder.Observe(viewModel.Observable).SubscribeAsync(msg => command.ExecuteAsync(msg.Value));

Event to observable conversion

IObservable<string> mouseMoveButtons =
  Bindery.Create.ObservableFor(form).Event<MouseEventArgs>("MouseMove")
       .Select(ctx => Convert.ToString(ctx.Args.Button));