using System; using System.Reactive.Disposables; using System.Reactive.Linq; using Avalonia; using Avalonia.VisualTree; using Avalonia.Controls; using ReactiveUI; namespace Avalonia.ReactiveUI { /// /// A ReactiveUI that implements the interface and /// will activate your ViewModel automatically if the view model implements . /// When the DataContext property changes, this class will update the ViewModel property with the new DataContext /// value, and vice versa. /// /// ViewModel type. public class ReactiveUserControl : UserControl, IViewFor where TViewModel : class { public static readonly StyledProperty ViewModelProperty = AvaloniaProperty .Register, TViewModel?>(nameof(ViewModel)); /// /// Initializes a new instance of the class. /// public ReactiveUserControl() { // This WhenActivated block calls ViewModel's WhenActivated // block if the ViewModel implements IActivatableViewModel. this.WhenActivated(disposables => { }); this.GetObservable(ViewModelProperty).Subscribe(OnViewModelChanged); } /// /// The ViewModel. /// public TViewModel? ViewModel { get => GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } object? IViewFor.ViewModel { get => ViewModel; set => ViewModel = (TViewModel?)value; } protected override void OnDataContextChanged(EventArgs e) { ViewModel = DataContext as TViewModel; } private void OnViewModelChanged(object? value) { if (value == null) { ClearValue(DataContextProperty); } else if (DataContext != value) { DataContext = value; } } } }