We've made a custom control with a clear button, which should delete the form where the control is used. We also use ReactiveProperty to implement Commands in the ViewModel.
MyControl ViewModel
internal sealed class MyControlViewModel : IDisposable
{
public ReactiveCommand Clear { get; set; } = new ReactiveCommand();
#region IDisposable
// (dispose commands)
#endregion
}
MyControl View
<UserControl (namespaces)>
<UserControl.DataContext>
<local:MyControlViewModel/>
</UserControl.DataContext>
<Button Command="{Binding Clear, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">Clear</Button>
</UserControl>
code behind:
public sealed partial class MyControl : UserControl, IDisposable
{
public MyControl()
{
InitializeComponent();
_subscriptions.Add(ViewModel?.Clear.Subscribe(o => Clear?.Execute(o)));
}
internal MyControlViewModel ViewModel => (MyControlViewModel)DataContext;
#region DependencyProperty
public static readonly DependencyProperty ClearProperty =
DependencyProperty.Register(nameof(Clear), typeof(ICommand), typeof(MyControl), new PropertyMetadata(null));
public ICommand Clear
{
get { return (ICommand) GetValue(ClearProperty); }
set { SetValue(ClearProperty, value); }
}
#endregion
#region IDisposable
// (dispose subscriptions, properties, commands)
#endregion
}
Main ViewModel
internal sealed class MainViewModel : IDisposable
{
public MainViewModel()
{
Clear = InputText.Select(t => !string.IsNullOrEmpty(t)).ToReactiveCommand();
_subscriptions.Add(Clear.Subscribe(_ => InputText.Value = string.Empty));
}
public ReactiveCommand Clear { get; set; }
public ReactiveProperty<string> InputText { get; set; }
= new ReactiveProperty<string>(string.Empty, ReactivePropertyMode.DistinctUntilChanged);
#region IDisposable
// (dispose subscriptions, properties, commands)
#endregion
}
Main View
<Page (namespaces)>
<Page.DataContext>
<main:MainViewModel />
</Page.DataContext>
<local:MyControl x:Name="myControl" Clear="{Binding Clear}" />
</Page>
Unfortunately, the binding in the Main View does not work and the Clear property of MyControl's View is always null
.
Remarks
It works by setting the Property manually, but it isn't what I want:
public sealed partial class MainPage
{
public MainPage()
{
InitializeComponent();
myControl.Clear = ViewModel.Clear;
}
private MainViewModel ViewModel => (MainViewModel) DataContext;
}
The question is how to do it properly using only data binding in XAML.
Edit
The reason why the binding is failing is obvious when trying this:
myControl.SetBinding(ViewModel.ClearAll, new Binding("ClearAll"));;
This code can't compile because ViewModel.ClearAll
is a ReactiveCommand
and therefore not assignable to a DependencyProperty
.
Solution
For binding to ICommand
, it is required to use {x:Bind Path}
instead of {Binding Path}
.
See also: MSDN: Event Binding and ICommand