Skip to the content.

Cookbook: Creating custom input editors

Input editors are useful to let the user configure values or properties for your node/input right where they are relevant. Creating a custom editor involves two parts: a custom view and a custom viewmodel.

In this section, we will create an editor for strings. More complex examples can be found in the shader editor example app. Also note that while this example uses ValueEditorViewModel, you can also use NodeEndpointEditorViewModel if you want something more bare-bones.

ViewModel

Create a new class and let it inherit from ValueEditorViewModel<string>. All subclasses of ValueEditorViewModel have a Value property that is automatically used by ValueInputEditorViewModel. In the constructor of the new class, assign a default value to the property. In order to link the view to the viewmodel, you also need to register it with ReactiveUI.

The result looks like this:

public class StringValueEditorViewModel : ValueEditorViewModel<string>
{
    static StringValueEditorViewModel()
    {
        Splat.Locator.CurrentMutable.Register(() => new StringValueEditorView(), typeof(IViewFor<StringValueEditorViewModel>));
    }

    public StringValueEditorViewModel()
    {
        Value = "";
    }
}

View

Create a new UserControl and add a textbox to the XAML:

<TextBox x:Name="TextBox" MinWidth="100"/>

In the code-behind, have the control implement IViewFor<StringValueEditorViewModel> and bind the text in the textbox to the Value property in the ViewModel.

public partial class StringValueEditorView : IViewFor<StringValueEditorViewModel>
{
    #region ViewModel
    public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(nameof(ViewModel),
        typeof(StringValueEditorViewModel), typeof(StringValueEditorView), new PropertyMetadata(null));

    public StringValueEditorViewModel ViewModel
    {
        get => (StringValueEditorViewModel)GetValue(ViewModelProperty);
        set => SetValue(ViewModelProperty, value);
    }

    object IViewFor.ViewModel
    {
        get => ViewModel;
        set => ViewModel = (StringValueEditorViewModel)value;
    }
    #endregion

    public StringValueEditorView()
    {
        InitializeComponent();

        this.WhenActivated(d => {
            this.Bind(ViewModel, vm => vm.Value, v => v.TextBox.Text).DisposeWith(d);
        });
    }
}