| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Reactive;
 
- using System.Reactive.Disposables;
 
- using System.Reactive.Linq;
 
- using System.Text;
 
- using Avalonia.Data;
 
- using Xunit;
 
- namespace Avalonia.Base.UnitTests
 
- {
 
-     public class AvaloniaObjectTests_BatchUpdate
 
-     {
 
-         [Fact]
 
-         public void SetValue_Should_Not_Raise_Property_Changes_During_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var raised = new List<string>();
 
-             target.GetObservable(TestClass.FooProperty).Skip(1).Subscribe(x => raised.Add(x));
 
-             target.BeginBatchUpdate();
 
-             target.SetValue(TestClass.FooProperty, "foo", BindingPriority.LocalValue);
 
-             Assert.Empty(raised);
 
-         }
 
-         [Fact]
 
-         public void Binding_Should_Not_Raise_Property_Changes_During_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var observable = new TestObservable<string>("foo");
 
-             var raised = new List<string>();
 
-             target.GetObservable(TestClass.FooProperty).Skip(1).Subscribe(x => raised.Add(x));
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable, BindingPriority.LocalValue);
 
-             Assert.Empty(raised);
 
-         }
 
-         [Fact]
 
-         public void Binding_Completion_Should_Not_Raise_Property_Changes_During_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var observable = new TestObservable<string>("foo");
 
-             var raised = new List<string>();
 
-             target.Bind(TestClass.FooProperty, observable, BindingPriority.LocalValue);
 
-             target.GetObservable(TestClass.FooProperty).Skip(1).Subscribe(x => raised.Add(x));
 
-             target.BeginBatchUpdate();
 
-             observable.OnCompleted();
 
-             Assert.Empty(raised);
 
-         }
 
-         [Fact]
 
-         public void SetValue_Change_Should_Be_Raised_After_Batch_Update_1()
 
-         {
 
-             var target = new TestClass();
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.SetValue(TestClass.FooProperty, "foo", BindingPriority.LocalValue);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(1, raised.Count);
 
-             Assert.Equal("foo", target.Foo);
 
-             Assert.Null(raised[0].OldValue);
 
-             Assert.Equal("foo", raised[0].NewValue);
 
-         }
 
-         [Fact]
 
-         public void SetValue_Change_Should_Be_Raised_After_Batch_Update_2()
 
-         {
 
-             var target = new TestClass();
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.SetValue(TestClass.FooProperty, "foo", BindingPriority.LocalValue);
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.SetValue(TestClass.FooProperty, "bar", BindingPriority.LocalValue);
 
-             target.SetValue(TestClass.FooProperty, "baz", BindingPriority.LocalValue);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(1, raised.Count);
 
-             Assert.Equal("baz", target.Foo);
 
-         }
 
-         [Fact]
 
-         public void SetValue_Changes_Should_Be_Raised_In_Correct_Order_After_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.SetValue(TestClass.FooProperty, "foo", BindingPriority.LocalValue);
 
-             target.SetValue(TestClass.BarProperty, "bar", BindingPriority.LocalValue);
 
-             target.SetValue(TestClass.FooProperty, "baz", BindingPriority.LocalValue);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(2, raised.Count);
 
-             Assert.Equal(TestClass.BarProperty, raised[0].Property);
 
-             Assert.Equal(TestClass.FooProperty, raised[1].Property);
 
-             Assert.Equal("baz", target.Foo);
 
-             Assert.Equal("bar", target.Bar);
 
-         }
 
-         [Fact]
 
-         public void SetValue_And_Binding_Changes_Should_Be_Raised_In_Correct_Order_After_Batch_Update_1()
 
-         {
 
-             var target = new TestClass();
 
-             var observable = new TestObservable<string>("baz");
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.SetValue(TestClass.FooProperty, "foo", BindingPriority.LocalValue);
 
-             target.SetValue(TestClass.BarProperty, "bar", BindingPriority.LocalValue);
 
-             target.Bind(TestClass.FooProperty, observable, BindingPriority.LocalValue);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(2, raised.Count);
 
-             Assert.Equal(TestClass.BarProperty, raised[0].Property);
 
-             Assert.Equal(TestClass.FooProperty, raised[1].Property);
 
-             Assert.Equal("baz", target.Foo);
 
-             Assert.Equal("bar", target.Bar);
 
-         }
 
-         [Fact]
 
-         public void SetValue_And_Binding_Changes_Should_Be_Raised_In_Correct_Order_After_Batch_Update_2()
 
-         {
 
-             var target = new TestClass();
 
-             var observable = new TestObservable<string>("foo");
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable, BindingPriority.LocalValue);
 
-             target.SetValue(TestClass.BarProperty, "bar", BindingPriority.LocalValue);
 
-             target.SetValue(TestClass.FooProperty, "baz", BindingPriority.LocalValue);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(2, raised.Count);
 
-             Assert.Equal(TestClass.BarProperty, raised[0].Property);
 
-             Assert.Equal(TestClass.FooProperty, raised[1].Property);
 
-             Assert.Equal("baz", target.Foo);
 
-             Assert.Equal("bar", target.Bar);
 
-         }
 
-         [Fact]
 
-         public void SetValue_And_Binding_Changes_Should_Be_Raised_In_Correct_Order_After_Batch_Update_3()
 
-         {
 
-             var target = new TestClass();
 
-             var observable1 = new TestObservable<string>("foo");
 
-             var observable2 = new TestObservable<string>("qux");
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable2, BindingPriority.LocalValue);
 
-             target.Bind(TestClass.FooProperty, observable1, BindingPriority.LocalValue);
 
-             target.SetValue(TestClass.BarProperty, "bar", BindingPriority.LocalValue);
 
-             target.SetValue(TestClass.FooProperty, "baz", BindingPriority.LocalValue);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(2, raised.Count);
 
-             Assert.Equal(TestClass.BarProperty, raised[0].Property);
 
-             Assert.Equal(TestClass.FooProperty, raised[1].Property);
 
-             Assert.Equal("baz", target.Foo);
 
-             Assert.Equal("bar", target.Bar);
 
-         }
 
-         [Fact]
 
-         public void Binding_Change_Should_Be_Raised_After_Batch_Update_1()
 
-         {
 
-             var target = new TestClass();
 
-             var observable = new TestObservable<string>("foo");
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable, BindingPriority.LocalValue);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(1, raised.Count);
 
-             Assert.Equal("foo", target.Foo);
 
-             Assert.Null(raised[0].OldValue);
 
-             Assert.Equal("foo", raised[0].NewValue);
 
-         }
 
-         [Fact]
 
-         public void Binding_Change_Should_Be_Raised_After_Batch_Update_2()
 
-         {
 
-             var target = new TestClass();
 
-             var observable1 = new TestObservable<string>("bar");
 
-             var observable2 = new TestObservable<string>("baz");
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.SetValue(TestClass.FooProperty, "foo", BindingPriority.LocalValue);
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable1, BindingPriority.LocalValue);
 
-             target.Bind(TestClass.FooProperty, observable2, BindingPriority.LocalValue);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(1, raised.Count);
 
-             Assert.Equal("baz", target.Foo);
 
-             Assert.Equal("foo", raised[0].OldValue);
 
-             Assert.Equal("baz", raised[0].NewValue);
 
-         }
 
-         [Fact]
 
-         public void Binding_Completion_Should_Be_Raised_After_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var observable = new TestObservable<string>("foo");
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.Bind(TestClass.FooProperty, observable, BindingPriority.LocalValue);
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             observable.OnCompleted();
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(1, raised.Count);
 
-             Assert.Null(target.Foo);
 
-             Assert.Equal("foo", raised[0].OldValue);
 
-             Assert.Null(raised[0].NewValue);
 
-             Assert.Equal(BindingPriority.Unset, raised[0].Priority);
 
-         }
 
-         [Fact]
 
-         public void ClearValue_Change_Should_Be_Raised_After_Batch_Update_1()
 
-         {
 
-             var target = new TestClass();
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.Foo = "foo";
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.ClearValue(TestClass.FooProperty);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(1, raised.Count);
 
-             Assert.Null(target.Foo);
 
-             Assert.Equal("foo", raised[0].OldValue);
 
-             Assert.Null(raised[0].NewValue);
 
-             Assert.Equal(BindingPriority.Unset, raised[0].Priority);
 
-         }
 
-         [Fact]
 
-         public void Bindings_Should_Be_Subscribed_Before_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var observable1 = new TestObservable<string>("foo");
 
-             var observable2 = new TestObservable<string>("bar");
 
-             target.Bind(TestClass.FooProperty, observable1, BindingPriority.LocalValue);
 
-             target.Bind(TestClass.FooProperty, observable2, BindingPriority.LocalValue);
 
-             Assert.Equal(1, observable1.SubscribeCount);
 
-             Assert.Equal(1, observable2.SubscribeCount);
 
-         }
 
-         [Fact]
 
-         public void Non_Active_Binding_Should_Not_Be_Subscribed_Before_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var observable1 = new TestObservable<string>("foo");
 
-             var observable2 = new TestObservable<string>("bar");
 
-             target.Bind(TestClass.FooProperty, observable1, BindingPriority.LocalValue);
 
-             target.Bind(TestClass.FooProperty, observable2, BindingPriority.Style);
 
-             Assert.Equal(1, observable1.SubscribeCount);
 
-             Assert.Equal(0, observable2.SubscribeCount);
 
-         }
 
-         [Fact]
 
-         public void LocalValue_Bindings_Should_Be_Subscribed_During_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var observable1 = new TestObservable<string>("foo");
 
-             var observable2 = new TestObservable<string>("bar");
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             // We need to subscribe to LocalValue bindings even if we've got a batch operation
 
-             // in progress because otherwise we don't know whether the binding or a subsequent
 
-             // SetValue with local priority will win. Notifications however shouldn't be sent.
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable1, BindingPriority.LocalValue);
 
-             target.Bind(TestClass.FooProperty, observable2, BindingPriority.LocalValue);
 
-             Assert.Equal(1, observable1.SubscribeCount);
 
-             Assert.Equal(1, observable2.SubscribeCount);
 
-             Assert.Empty(raised);
 
-         }
 
-         [Fact]
 
-         public void Style_Bindings_Should_Not_Be_Subscribed_During_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var observable1 = new TestObservable<string>("foo");
 
-             var observable2 = new TestObservable<string>("bar");
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable1, BindingPriority.Style);
 
-             target.Bind(TestClass.FooProperty, observable2, BindingPriority.StyleTrigger);
 
-             Assert.Equal(0, observable1.SubscribeCount);
 
-             Assert.Equal(0, observable2.SubscribeCount);
 
-         }
 
-         [Fact]
 
-         public void Active_Style_Binding_Should_Be_Subscribed_After_Batch_Uppdate_1()
 
-         {
 
-             var target = new TestClass();
 
-             var observable1 = new TestObservable<string>("foo");
 
-             var observable2 = new TestObservable<string>("bar");
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable1, BindingPriority.Style);
 
-             target.Bind(TestClass.FooProperty, observable2, BindingPriority.Style);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(0, observable1.SubscribeCount);
 
-             Assert.Equal(1, observable2.SubscribeCount);
 
-         }
 
-         [Fact]
 
-         public void Active_Style_Binding_Should_Be_Subscribed_After_Batch_Uppdate_2()
 
-         {
 
-             var target = new TestClass();
 
-             var observable1 = new TestObservable<string>("foo");
 
-             var observable2 = new TestObservable<string>("bar");
 
-             target.BeginBatchUpdate();
 
-             target.Bind(TestClass.FooProperty, observable1, BindingPriority.StyleTrigger);
 
-             target.Bind(TestClass.FooProperty, observable2, BindingPriority.Style);
 
-             target.EndBatchUpdate();
 
-             Assert.Equal(1, observable1.SubscribeCount);
 
-             Assert.Equal(0, observable2.SubscribeCount);
 
-         }
 
-         [Fact]
 
-         public void Change_Can_Be_Triggered_By_Ending_Batch_Update_1()
 
-         {
 
-             var target = new TestClass();
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.Foo = "foo";
 
-             target.PropertyChanged += (s, e) =>
 
-             {
 
-                 if (e.Property == TestClass.FooProperty && (string)e.NewValue == "foo")
 
-                     target.Bar = "bar";
 
-             };
 
-             target.EndBatchUpdate();
 
-             Assert.Equal("foo", target.Foo);
 
-             Assert.Equal("bar", target.Bar);
 
-             Assert.Equal(2, raised.Count);
 
-             Assert.Equal(TestClass.FooProperty, raised[0].Property);
 
-             Assert.Equal(TestClass.BarProperty, raised[1].Property);
 
-         }
 
-         [Fact]
 
-         public void Change_Can_Be_Triggered_By_Ending_Batch_Update_2()
 
-         {
 
-             var target = new TestClass();
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.Foo = "foo";
 
-             target.Bar = "baz";
 
-             target.PropertyChanged += (s, e) =>
 
-             {
 
-                 if (e.Property == TestClass.FooProperty && (string)e.NewValue == "foo")
 
-                     target.Bar = "bar";
 
-             };
 
-             target.EndBatchUpdate();
 
-             Assert.Equal("foo", target.Foo);
 
-             Assert.Equal("bar", target.Bar);
 
-             Assert.Equal(2, raised.Count);
 
-         }
 
-         [Fact]
 
-         public void Batch_Update_Can_Be_Triggered_By_Ending_Batch_Update()
 
-         {
 
-             var target = new TestClass();
 
-             var raised = new List<AvaloniaPropertyChangedEventArgs>();
 
-             target.PropertyChanged += (s, e) => raised.Add(e);
 
-             target.BeginBatchUpdate();
 
-             target.Foo = "foo";
 
-             target.Bar = "baz";
 
-             // Simulates the following scenario:
 
-             // - A control is added to the logical tree
 
-             // - A batch update is started to apply styles
 
-             // - Ending the batch update triggers something which removes the control from the logical tree
 
-             // - A new batch update is started to detach styles
 
-             target.PropertyChanged += (s, e) =>
 
-             {
 
-                 if (e.Property == TestClass.FooProperty && (string)e.NewValue == "foo")
 
-                 {
 
-                     target.BeginBatchUpdate();
 
-                     target.ClearValue(TestClass.FooProperty);
 
-                     target.ClearValue(TestClass.BarProperty);
 
-                     target.EndBatchUpdate();
 
-                 }
 
-             };
 
-             target.EndBatchUpdate();
 
-             Assert.Null(target.Foo);
 
-             Assert.Null(target.Bar);
 
-             Assert.Equal(2, raised.Count);
 
-             Assert.Equal(TestClass.FooProperty, raised[0].Property);
 
-             Assert.Null(raised[0].OldValue);
 
-             Assert.Equal("foo", raised[0].NewValue);
 
-             Assert.Equal(TestClass.FooProperty, raised[1].Property);
 
-             Assert.Equal("foo", raised[1].OldValue);
 
-             Assert.Null(raised[1].NewValue);
 
-         }
 
-         public class TestClass : AvaloniaObject
 
-         {
 
-             public static readonly StyledProperty<string> FooProperty =
 
-                 AvaloniaProperty.Register<TestClass, string>(nameof(Foo));
 
-             public static readonly StyledProperty<string> BarProperty =
 
-                 AvaloniaProperty.Register<TestClass, string>(nameof(Bar));
 
-             public string Foo
 
-             {
 
-                 get => GetValue(FooProperty);
 
-                 set => SetValue(FooProperty, value);
 
-             }
 
-             public string Bar
 
-             {
 
-                 get => GetValue(BarProperty);
 
-                 set => SetValue(BarProperty, value);
 
-             }
 
-         }
 
-         public class TestObservable<T> : ObservableBase<BindingValue<T>>
 
-         {
 
-             private readonly T _value;
 
-             private IObserver<BindingValue<T>> _observer;
 
-             public TestObservable(T value) => _value = value;
 
-             public int SubscribeCount { get; private set; }
 
-             public void OnCompleted() => _observer.OnCompleted();
 
-             public void OnError(Exception e) => _observer.OnError(e);
 
-             protected override IDisposable SubscribeCore(IObserver<BindingValue<T>> observer)
 
-             {
 
-                 ++SubscribeCount;
 
-                 _observer = observer;
 
-                 observer.OnNext(_value);
 
-                 return Disposable.Empty;
 
-             }
 
-         }
 
-     }
 
- }
 
 
  |