From 7ca89e73b74b79b586b8b2ca91b09a67bfc857da Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 13 Aug 2024 20:42:02 -0700 Subject: [PATCH 1/5] Remove internal `System.Reactive` usage. Only keep old visible API to avoid breaking changes. --- .../Avalonia.Controls.TreeDataGrid.csproj | 4 ++-- .../Data/Core/TypedBindingExpression`2.cs | 6 ++--- .../Experimental/Data/ObservableEx.cs | 2 +- .../Experimental/Data/TypedBinding`2.cs | 1 - .../Models/TreeDataGrid/CheckBoxCell.cs | 23 +++++++++++++------ .../Models/TreeDataGrid/CheckBoxColumn.cs | 3 ++- .../Models/TreeDataGrid/ColumnBase`2.cs | 1 - .../Models/TreeDataGrid/ExpanderCell.cs | 14 +++++++---- .../Models/TreeDataGrid/TextCell.cs | 22 +++++++++++++----- .../Models/TreeDataGrid/TextColumn.cs | 3 ++- .../Utils/CompositeDisposable.cs | 21 +++++++++++++++++ .../Models/TextCellTests.cs | 10 ++++---- 12 files changed, 77 insertions(+), 33 deletions(-) create mode 100644 src/Avalonia.Controls.TreeDataGrid/Utils/CompositeDisposable.cs diff --git a/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj b/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj index d67e9d68..da0c3965 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj +++ b/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj @@ -10,7 +10,7 @@ - - + + diff --git a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/TypedBindingExpression`2.cs b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/TypedBindingExpression`2.cs index b19341af..e21d1dc7 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/TypedBindingExpression`2.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/TypedBindingExpression`2.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Specialized; using System.ComponentModel; -using System.Reactive.Subjects; using Avalonia.Data; +using Avalonia.Reactive; using Avalonia.Utilities; #nullable enable @@ -19,7 +19,7 @@ namespace Avalonia.Experimental.Data.Core /// instantiated on an object. /// public class TypedBindingExpression : LightweightObservableBase>, - ISubject>, + IObserver>, IDescription where TIn : class { @@ -91,7 +91,7 @@ void IObserver>.OnError(Exception error) protected override void Initialize() { _flags &= ~Flags.RootHasFired; - _rootSourceSubsciption = _rootSource.Subscribe(RootChanged); + _rootSourceSubsciption = _rootSource.Subscribe(new AnonymousObserver(RootChanged)); _flags |= Flags.Initialized; } diff --git a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/ObservableEx.cs b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/ObservableEx.cs index 155e251f..0052d296 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/ObservableEx.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/ObservableEx.cs @@ -1,5 +1,5 @@ using System; -using System.Reactive.Disposables; +using Avalonia.Experimental.Data.Core; namespace Avalonia.Experimental.Data { diff --git a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/TypedBinding`2.cs b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/TypedBinding`2.cs index 1c549e6e..8c276ad4 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/TypedBinding`2.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/TypedBinding`2.cs @@ -1,5 +1,4 @@ using System; -using System.Reactive.Disposables; using Avalonia.Data; using Avalonia.Experimental.Data.Core; using Avalonia.Reactive; diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/CheckBoxCell.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/CheckBoxCell.cs index d0cf6df7..7b4840d0 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/CheckBoxCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/CheckBoxCell.cs @@ -1,13 +1,12 @@ using System; -using System.Reactive.Subjects; -using System.Reflection; using Avalonia.Data; +using Avalonia.Reactive; namespace Avalonia.Controls.Models.TreeDataGrid { public class CheckBoxCell : NotifyingBase, ICell, IDisposable { - private readonly ISubject>? _binding; + private readonly IObserver>? _binding; private readonly IDisposable? _subscription; private bool? _value; @@ -18,19 +17,29 @@ public CheckBoxCell(bool? value) } public CheckBoxCell( - ISubject> binding, + IObserver> bindingObserver, + IObservable> bindingObservable, bool isReadOnly, bool isThreeState) { - _binding = binding; + _binding = bindingObserver; IsReadOnly = isReadOnly; IsThreeState = isThreeState; - _subscription = binding.Subscribe(x => + _subscription = bindingObservable.Subscribe(new AnonymousObserver>(x => { if (x.HasValue) Value = x.Value; - }); + })); + } + + [Obsolete("ISubject<> might be removed in the future versions.")] + public CheckBoxCell( + System.Reactive.Subjects.ISubject> binding, + bool isReadOnly, + bool isThreeState) + : this(binding, binding, isReadOnly, isThreeState) + { } public bool CanEdit => false; diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/CheckBoxColumn.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/CheckBoxColumn.cs index 066c69ae..47bd7780 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/CheckBoxColumn.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/CheckBoxColumn.cs @@ -68,7 +68,8 @@ public CheckBoxColumn( public override ICell CreateCell(IRow row) { - return new CheckBoxCell(CreateBindingExpression(row.Model), Binding.Write is null, IsThreeState); + var expression = CreateBindingExpression(row.Model); + return new CheckBoxCell(expression, expression, Binding.Write is null, IsThreeState); } private static Func ToNullable(Expression> getter) diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnBase`2.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnBase`2.cs index f330a793..e1affb5b 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnBase`2.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnBase`2.cs @@ -4,7 +4,6 @@ using System.Linq.Expressions; using Avalonia.Experimental.Data; using Avalonia.Experimental.Data.Core; -using Avalonia.Reactive; namespace Avalonia.Controls.Models.TreeDataGrid { diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ExpanderCell.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ExpanderCell.cs index 2256fc1c..cebb8a46 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ExpanderCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ExpanderCell.cs @@ -1,8 +1,8 @@ using System; using System.ComponentModel; -using System.Reactive.Disposables; using Avalonia.Data; using Avalonia.Experimental.Data.Core; +using Avalonia.Reactive; namespace Avalonia.Controls.Models.TreeDataGrid { @@ -12,7 +12,7 @@ public class ExpanderCell : NotifyingBase, where TModel : class { private readonly ICell _inner; - private readonly CompositeDisposable _subscription = new(); + private readonly IDisposable _subscription; public ExpanderCell( ICell inner, @@ -24,15 +24,19 @@ public ExpanderCell( Row = row; row.PropertyChanged += RowPropertyChanged; - _subscription.Add(showExpander.Subscribe(x => Row.UpdateShowExpander(this, x))); - + var expanderSubscription = showExpander.Subscribe(new AnonymousObserver(x => Row.UpdateShowExpander(this, x))); if (isExpanded is not null) { - _subscription.Add(isExpanded.Subscribe(x => + var isExpandedSubscription = isExpanded.Subscribe(new AnonymousObserver>(x => { if (x.HasValue) IsExpanded = x.Value; })); + _subscription = new CompositeDisposable(expanderSubscription, isExpandedSubscription); + } + else + { + _subscription = expanderSubscription; } } diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextCell.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextCell.cs index fe721f5b..d4975f9a 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextCell.cs @@ -2,15 +2,15 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -using System.Reactive.Subjects; using Avalonia.Data; using Avalonia.Media; +using Avalonia.Reactive; namespace Avalonia.Controls.Models.TreeDataGrid { public class TextCell : NotifyingBase, ITextCell, IDisposable, IEditableObject { - private readonly ISubject>? _binding; + private readonly IObserver>? _binding; private readonly IDisposable? _subscription; [AllowNull] private T? _value; [AllowNull] private T? _cancelValue; @@ -24,19 +24,29 @@ public TextCell(T? value) } public TextCell( - ISubject> binding, + IObserver> bindingSubject, + IObservable> bindingObservable, bool isReadOnly, ITextCellOptions? options = null) { - _binding = binding; + _binding = bindingSubject; IsReadOnly = isReadOnly; _options = options; - _subscription = binding.Subscribe(x => + _subscription = bindingObservable.Subscribe(new AnonymousObserver>(x => { if (x.HasValue) Value = x.Value; - }); + })); + } + + [Obsolete("ISubject<> might be removed in the future versions.")] + public TextCell( + System.Reactive.Subjects.ISubject> binding, + bool isReadOnly, + ITextCellOptions? options = null) + : this(binding, binding, isReadOnly, options) + { } public bool CanEdit => !IsReadOnly; diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextColumn.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextColumn.cs index eac14623..e412ac57 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextColumn.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextColumn.cs @@ -62,7 +62,8 @@ public TextColumn( public override ICell CreateCell(IRow row) { - return new TextCell(CreateBindingExpression(row.Model), Binding.Write is null, Options); + var expression = CreateBindingExpression(row.Model); + return new TextCell(expression, expression, Binding.Write is null, Options); } string? ITextSearchableColumn.SelectValue(TModel model) diff --git a/src/Avalonia.Controls.TreeDataGrid/Utils/CompositeDisposable.cs b/src/Avalonia.Controls.TreeDataGrid/Utils/CompositeDisposable.cs new file mode 100644 index 00000000..80315cc5 --- /dev/null +++ b/src/Avalonia.Controls.TreeDataGrid/Utils/CompositeDisposable.cs @@ -0,0 +1,21 @@ +using System; + +namespace Avalonia; + +internal class CompositeDisposable : IDisposable +{ + private readonly IDisposable _disposable1; + private readonly IDisposable _disposable2; + + public CompositeDisposable(IDisposable disposable1, IDisposable disposable2) + { + _disposable1 = disposable1; + _disposable2 = disposable2; + } + + public void Dispose() + { + _disposable1.Dispose(); + _disposable2.Dispose(); + } +} diff --git a/tests/Avalonia.Controls.TreeDataGrid.Tests/Models/TextCellTests.cs b/tests/Avalonia.Controls.TreeDataGrid.Tests/Models/TextCellTests.cs index 44931703..e358b98f 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Tests/Models/TextCellTests.cs +++ b/tests/Avalonia.Controls.TreeDataGrid.Tests/Models/TextCellTests.cs @@ -18,7 +18,7 @@ public class TextCellTests public void Value_Is_Initially_Read_From_String() { var binding = new BehaviorSubject>("initial"); - var target = new TextCell(binding, true); + var target = new TextCell(binding, binding, true); Assert.Equal("initial", target.Text); Assert.Equal("initial", target.Value); @@ -28,7 +28,7 @@ public void Value_Is_Initially_Read_From_String() public void Modified_Value_Is_Written_To_Binding() { var binding = new BehaviorSubject>("initial"); - var target = new TextCell(binding, false); + var target = new TextCell(binding, binding, false); var result = new List(); binding.Subscribe(x => result.Add(x.Value)); @@ -41,7 +41,7 @@ public void Modified_Value_Is_Written_To_Binding() public void Modified_Text_Is_Written_To_Binding() { var binding = new BehaviorSubject>("initial"); - var target = new TextCell(binding, false); + var target = new TextCell(binding, binding, false); var result = new List(); binding.Subscribe(x => result.Add(x.Value)); @@ -54,7 +54,7 @@ public void Modified_Text_Is_Written_To_Binding() public void Modified_Value_Is_Written_To_Binding_On_EndEdit() { var binding = new BehaviorSubject>("initial"); - var target = new TextCell(binding, false); + var target = new TextCell(binding, binding, false); var result = new List(); binding.Subscribe(x => result.Add(x.Value)); @@ -77,7 +77,7 @@ public void Modified_Value_Is_Written_To_Binding_On_EndEdit() public void Modified_Value_Is_Not_Written_To_Binding_On_CancelEdit() { var binding = new BehaviorSubject>("initial"); - var target = new TextCell(binding, false); + var target = new TextCell(binding, binding, false); var result = new List(); binding.Subscribe(x => result.Add(x.Value)); From 81b76ad247c3d24e8c0ad2426b5774f6542e2fc8 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 13 Aug 2024 20:54:16 -0700 Subject: [PATCH 2/5] Make sample project AOT compatible --- Directory.Build.props | 5 +++-- global.json | 7 ++++--- samples/TreeDataGridDemo/MainWindow.axaml | 5 +++-- samples/TreeDataGridDemo/MainWindow.axaml.cs | 6 ------ samples/TreeDataGridDemo/TreeDataGridDemo.csproj | 15 ++++++++------- .../ViewModels/WikipediaPageViewModel.cs | 15 ++++++++++----- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6508ac29..afe97827 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,13 +5,14 @@ enable true nullable - net6.0 - 9 + 11 false false + true 11.0.0 + 11.1.3 diff --git a/global.json b/global.json index e6e67e4e..da113e4c 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,7 @@ { "sdk": { - "version": "7.0.101", - "rollForward": "latestFeature" + "version": "8.0.0", + "rollForward": "latestFeature", + "allowPrerelease": false } -} +} \ No newline at end of file diff --git a/samples/TreeDataGridDemo/MainWindow.axaml b/samples/TreeDataGridDemo/MainWindow.axaml index c3f192f7..bf055791 100644 --- a/samples/TreeDataGridDemo/MainWindow.axaml +++ b/samples/TreeDataGridDemo/MainWindow.axaml @@ -6,7 +6,8 @@ xmlns:vm="using:TreeDataGridDemo.ViewModels" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="TreeDataGridDemo.MainWindow" - Title="TreeDataGridDemo"> + Title="TreeDataGridDemo" + x:DataType="vm:MainWindowViewModel"> @@ -125,7 +126,7 @@ - + diff --git a/samples/TreeDataGridDemo/MainWindow.axaml.cs b/samples/TreeDataGridDemo/MainWindow.axaml.cs index 883cac22..db69602a 100644 --- a/samples/TreeDataGridDemo/MainWindow.axaml.cs +++ b/samples/TreeDataGridDemo/MainWindow.axaml.cs @@ -20,7 +20,6 @@ public partial class MainWindow : Window public MainWindow() { InitializeComponent(); - this.AttachDevTools(); DataContext = new MainWindowViewModel(); _tabs = this.FindControl("tabs"); @@ -75,11 +74,6 @@ public void AddCountryClick(object sender, RoutedEventArgs e) countries.TryGetRow(index)?.Focus(); } - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - private void MainWindow_Activated(object? sender, EventArgs e) { Program.Stopwatch!.Stop(); diff --git a/samples/TreeDataGridDemo/TreeDataGridDemo.csproj b/samples/TreeDataGridDemo/TreeDataGridDemo.csproj index 055ae9ac..1c145ba6 100644 --- a/samples/TreeDataGridDemo/TreeDataGridDemo.csproj +++ b/samples/TreeDataGridDemo/TreeDataGridDemo.csproj @@ -1,8 +1,9 @@  - net6.0 + net8.0 False WinExe + true @@ -12,12 +13,12 @@ - - - - - - + + + + + + diff --git a/samples/TreeDataGridDemo/ViewModels/WikipediaPageViewModel.cs b/samples/TreeDataGridDemo/ViewModels/WikipediaPageViewModel.cs index f895169b..96b032bf 100644 --- a/samples/TreeDataGridDemo/ViewModels/WikipediaPageViewModel.cs +++ b/samples/TreeDataGridDemo/ViewModels/WikipediaPageViewModel.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Net.Http; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; using Avalonia.Collections; using Avalonia.Controls; @@ -11,7 +12,7 @@ namespace TreeDataGridDemo.ViewModels { - internal class WikipediaPageViewModel + internal partial class WikipediaPageViewModel { private readonly AvaloniaList _data = new(); @@ -47,15 +48,19 @@ private async Task LoadContent() var m = DateTimeOffset.Now.Month; var uri = $"https://api.wikimedia.org/feed/v1/wikipedia/en/onthisday/all/{m}/{d}"; var s = await client.GetStringAsync(uri); - var data = JsonSerializer.Deserialize(s, new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true, - }); + var data = (OnThisDay)JsonSerializer.Deserialize(s, typeof(OnThisDay), SerializationContext.Default)!; if (data?.Selected is not null) _data.AddRange(data.Selected.SelectMany(x => x.Pages!)); } catch { } } + + [JsonSourceGenerationOptions(PropertyNameCaseInsensitive = true)] + [JsonSerializable(typeof(OnThisDay))] + internal partial class SerializationContext : JsonSerializerContext + { + + } } } From 9457b72d79bbf189d11644fcfcb7d01cec8b5753 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 13 Aug 2024 20:54:30 -0700 Subject: [PATCH 3/5] Enable AOT/trimming warnings on TreeDataGrid project --- .../Avalonia.Controls.TreeDataGrid.csproj | 18 ++++++++++++++++-- .../Models/TreeDataGrid/AnonymousRow.cs | 4 ++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj b/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj index da0c3965..ed04c023 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj +++ b/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj @@ -1,8 +1,7 @@  - net5.0 + net6.0;net8.0 True - 10 Avalonia.Controls @@ -13,4 +12,19 @@ + + + + false + true + false + true + true + + + + + true + + diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousRow.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousRow.cs index 6829da91..66d9ca39 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousRow.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousRow.cs @@ -15,10 +15,10 @@ namespace Avalonia.Controls.Models.TreeDataGrid internal class AnonymousRow : IRow, IModelIndexableRow { private int _modelIndex; - [AllowNull] private TModel _model; + private TModel? _model; public object? Header => _modelIndex; - public TModel Model => _model; + public TModel Model => _model!; public int ModelIndex => _modelIndex; public IndexPath ModelIndexPath => _modelIndex; From 1bfe02b944d6c975598e542d4bc0b7aea336d8e2 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 13 Aug 2024 21:08:38 -0700 Subject: [PATCH 4/5] Replace ReactiveUI with CommunityToolkit to make it even more trimmable --- .../TreeDataGridDemo/Models/DragDropItem.cs | 8 ++-- .../Models/FileTreeNodeModel.cs | 16 ++++---- samples/TreeDataGridDemo/Program.cs | 2 - .../TreeDataGridDemo/TreeDataGridDemo.csproj | 2 +- .../ViewModels/CountriesPageViewModel.cs | 6 +-- .../ViewModels/DragDropPageViewModel.cs | 4 +- .../ViewModels/FilesPageViewModel.cs | 37 +++++++++++-------- 7 files changed, 40 insertions(+), 35 deletions(-) diff --git a/samples/TreeDataGridDemo/Models/DragDropItem.cs b/samples/TreeDataGridDemo/Models/DragDropItem.cs index 73f51de3..2a4821ca 100644 --- a/samples/TreeDataGridDemo/Models/DragDropItem.cs +++ b/samples/TreeDataGridDemo/Models/DragDropItem.cs @@ -1,11 +1,11 @@ using System; using System.Collections.ObjectModel; using System.Linq; -using ReactiveUI; +using CommunityToolkit.Mvvm.ComponentModel; namespace TreeDataGridDemo.Models { - public class DragDropItem : ReactiveObject + public class DragDropItem : ObservableObject { private static Random _random = new Random(0); private ObservableCollection? _children; @@ -18,13 +18,13 @@ public class DragDropItem : ReactiveObject public bool AllowDrag { get => _allowDrag; - set => this.RaiseAndSetIfChanged(ref _allowDrag, value); + set => SetProperty(ref _allowDrag, value); } public bool AllowDrop { get => _allowDrop; - set => this.RaiseAndSetIfChanged(ref _allowDrop, value); + set => SetProperty(ref _allowDrop, value); } public ObservableCollection Children => _children ??= CreateRandomItems(); diff --git a/samples/TreeDataGridDemo/Models/FileTreeNodeModel.cs b/samples/TreeDataGridDemo/Models/FileTreeNodeModel.cs index 3e1b7358..f9ebdb80 100644 --- a/samples/TreeDataGridDemo/Models/FileTreeNodeModel.cs +++ b/samples/TreeDataGridDemo/Models/FileTreeNodeModel.cs @@ -4,11 +4,11 @@ using System.ComponentModel; using System.IO; using Avalonia.Threading; -using ReactiveUI; +using CommunityToolkit.Mvvm.ComponentModel; namespace TreeDataGridDemo.Models { - public class FileTreeNodeModel : ReactiveObject, IEditableObject + public class FileTreeNodeModel : ObservableObject, IEditableObject { private string _path; private string _name; @@ -42,37 +42,37 @@ public FileTreeNodeModel( public string Path { get => _path; - private set => this.RaiseAndSetIfChanged(ref _path, value); + private set => SetProperty(ref _path, value); } public string Name { get => _name; - private set => this.RaiseAndSetIfChanged(ref _name, value); + private set => SetProperty(ref _name, value); } public long? Size { get => _size; - private set => this.RaiseAndSetIfChanged(ref _size, value); + private set => SetProperty(ref _size, value); } public DateTimeOffset? Modified { get => _modified; - private set => this.RaiseAndSetIfChanged(ref _modified, value); + private set => SetProperty(ref _modified, value); } public bool HasChildren { get => _hasChildren; - private set => this.RaiseAndSetIfChanged(ref _hasChildren, value); + private set => SetProperty(ref _hasChildren, value); } public bool IsExpanded { get => _isExpanded; - set => this.RaiseAndSetIfChanged(ref _isExpanded, value); + set => SetProperty(ref _isExpanded, value); } public bool IsChecked { get; set; } diff --git a/samples/TreeDataGridDemo/Program.cs b/samples/TreeDataGridDemo/Program.cs index 25a5d08d..12206e6e 100644 --- a/samples/TreeDataGridDemo/Program.cs +++ b/samples/TreeDataGridDemo/Program.cs @@ -1,6 +1,5 @@ using System.Diagnostics; using Avalonia; -using Avalonia.ReactiveUI; namespace TreeDataGridDemo { @@ -21,7 +20,6 @@ public static void Main(string[] args) public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure() .UsePlatformDetect() - .UseReactiveUI() .LogToTrace(); } } diff --git a/samples/TreeDataGridDemo/TreeDataGridDemo.csproj b/samples/TreeDataGridDemo/TreeDataGridDemo.csproj index 1c145ba6..4221764e 100644 --- a/samples/TreeDataGridDemo/TreeDataGridDemo.csproj +++ b/samples/TreeDataGridDemo/TreeDataGridDemo.csproj @@ -18,7 +18,7 @@ - + diff --git a/samples/TreeDataGridDemo/ViewModels/CountriesPageViewModel.cs b/samples/TreeDataGridDemo/ViewModels/CountriesPageViewModel.cs index 2be1344c..f52bf373 100644 --- a/samples/TreeDataGridDemo/ViewModels/CountriesPageViewModel.cs +++ b/samples/TreeDataGridDemo/ViewModels/CountriesPageViewModel.cs @@ -3,12 +3,12 @@ using Avalonia.Controls; using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Controls.Selection; -using ReactiveUI; +using CommunityToolkit.Mvvm.ComponentModel; using TreeDataGridDemo.Models; namespace TreeDataGridDemo.ViewModels { - internal class CountriesPageViewModel : ReactiveObject + internal class CountriesPageViewModel : ObservableObject { private readonly ObservableCollection _data; private bool _cellSelection; @@ -50,7 +50,7 @@ public bool CellSelection Source.Selection = new TreeDataGridCellSelectionModel(Source) { SingleSelect = false }; else Source.Selection = new TreeDataGridRowSelectionModel(Source) { SingleSelect = false }; - this.RaisePropertyChanged(); + OnPropertyChanged(); } } } diff --git a/samples/TreeDataGridDemo/ViewModels/DragDropPageViewModel.cs b/samples/TreeDataGridDemo/ViewModels/DragDropPageViewModel.cs index e75eb1c4..88731fb4 100644 --- a/samples/TreeDataGridDemo/ViewModels/DragDropPageViewModel.cs +++ b/samples/TreeDataGridDemo/ViewModels/DragDropPageViewModel.cs @@ -1,12 +1,12 @@ using System.Collections.ObjectModel; using Avalonia.Controls; using Avalonia.Controls.Models.TreeDataGrid; -using ReactiveUI; +using CommunityToolkit.Mvvm.ComponentModel; using TreeDataGridDemo.Models; namespace TreeDataGridDemo.ViewModels { - internal class DragDropPageViewModel : ReactiveObject + internal class DragDropPageViewModel : ObservableObject { private ObservableCollection _data; diff --git a/samples/TreeDataGridDemo/ViewModels/FilesPageViewModel.cs b/samples/TreeDataGridDemo/ViewModels/FilesPageViewModel.cs index f26e75fa..58b3d2aa 100644 --- a/samples/TreeDataGridDemo/ViewModels/FilesPageViewModel.cs +++ b/samples/TreeDataGridDemo/ViewModels/FilesPageViewModel.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO; using System.Linq; -using System.Reactive.Linq; using System.Runtime.InteropServices; using Avalonia.Controls; using Avalonia.Controls.Models.TreeDataGrid; @@ -11,12 +10,12 @@ using Avalonia.Data.Converters; using Avalonia.Media.Imaging; using Avalonia.Platform; -using ReactiveUI; +using CommunityToolkit.Mvvm.ComponentModel; using TreeDataGridDemo.Models; namespace TreeDataGridDemo.ViewModels { - public class FilesPageViewModel : ReactiveObject + public class FilesPageViewModel : ObservableObject { private static IconConverter? s_iconConverter; private readonly HierarchicalTreeDataGridSource? _treeSource; @@ -42,16 +41,24 @@ public FilesPageViewModel() _source = _treeSource = CreateTreeSource(); - this.WhenAnyValue(x => x.SelectedDrive) - .Subscribe(x => + UpdateRoot(); + PropertyChanged += (sender, args) => + { + if (args.PropertyName == nameof(SelectedDrive)) { - _root = new FileTreeNodeModel(_selectedDrive, isDirectory: true, isRoot: true); + UpdateRoot(); + } + }; - if (_treeSource is not null) - _treeSource.Items = new[] { _root }; - else if (_flatSource is not null) - _flatSource.Items = _root.Children; - }); + void UpdateRoot() + { + _root = new FileTreeNodeModel(SelectedDrive, isDirectory: true, isRoot: true); + + if (_treeSource is not null) + _treeSource.Items = new[] { _root }; + else if (_flatSource is not null) + _flatSource.Items = _root.Children; + } } public bool CellSelection @@ -66,7 +73,7 @@ public bool CellSelection Source.Selection = new TreeDataGridCellSelectionModel(Source) { SingleSelect = false }; else Source.Selection = new TreeDataGridRowSelectionModel(Source) { SingleSelect = false }; - this.RaisePropertyChanged(); + OnPropertyChanged(); } } } @@ -86,7 +93,7 @@ public bool FlatList public string SelectedDrive { get => _selectedDrive; - set => this.RaiseAndSetIfChanged(ref _selectedDrive, value); + set => SetProperty(ref _selectedDrive, value); } public string? SelectedPath @@ -98,7 +105,7 @@ public string? SelectedPath public ITreeDataGridSource Source { get => _source; - private set => this.RaiseAndSetIfChanged(ref _source, value); + private set => SetProperty(ref _source, value); } public static IMultiValueConverter FileIconConverter @@ -292,7 +299,7 @@ private ITreeDataGridRowSelectionModel GetRowSelection(ITreeD private void SelectionChanged(object? sender, TreeSelectionModelSelectionChangedEventArgs e) { var selectedPath = GetRowSelection(Source).SelectedItem?.Path; - this.RaiseAndSetIfChanged(ref _selectedPath, selectedPath, nameof(SelectedPath)); + SetProperty(ref _selectedPath, selectedPath, nameof(SelectedPath)); foreach (var i in e.DeselectedItems) System.Diagnostics.Trace.WriteLine($"Deselected '{i?.Path}'"); From 8d7fbd48920e574072499044ef5f8847c4e14346 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 13 Aug 2024 21:10:00 -0700 Subject: [PATCH 5/5] Return net5.0 target --- .../Avalonia.Controls.TreeDataGrid.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj b/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj index ed04c023..85d98d0a 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj +++ b/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj @@ -1,6 +1,6 @@  - net6.0;net8.0 + net5.0;net6.0;net8.0 True Avalonia.Controls