From 08ae754ea34678222260a1a5eedb3ed3deb69faf Mon Sep 17 00:00:00 2001
From: NaBian <836904362@qq.com>
Date: Mon, 2 Mar 2020 23:27:22 +0800
Subject: [PATCH] add ManualObservableCollection
---
.../Controls/NotifyIconDemoCtl.xaml | 34 ++--
.../UserControl/Controls/SideMenuDemoCtl.xaml | 12 +-
.../UserControl/Main/LeftMainContent.xaml | 12 +-
.../ManualObservableCollection!1.cs | 191 ++++++++++++++++++
.../HandyControl_Shared.projitems | 1 +
5 files changed, 218 insertions(+), 32 deletions(-)
create mode 100644 src/Shared/HandyControl_Shared/Collections/ManualObservableCollection!1.cs
diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/NotifyIconDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/NotifyIconDemoCtl.xaml
index 173073e2..36c6aeac 100644
--- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/NotifyIconDemoCtl.xaml
+++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/NotifyIconDemoCtl.xaml
@@ -3,8 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:langs="clr-namespace:HandyControlDemo.Properties.Langs"
xmlns:hc="https://handyorg.github.io/handycontrol"
- xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
- xmlns:command="http://www.galasoft.ch/mvvmlight"
xmlns:data="clr-namespace:HandyControlDemo.Data"
DataContext="{Binding NotifyIconDemo,Source={StaticResource Locator}}"
Background="{DynamicResource RegionBrush}">
@@ -47,14 +45,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -68,14 +66,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/SideMenuDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/SideMenuDemoCtl.xaml
index 2b2ae21d..2672b5a2 100644
--- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/SideMenuDemoCtl.xaml
+++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/SideMenuDemoCtl.xaml
@@ -2,18 +2,16 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="https://handyorg.github.io/handycontrol"
- xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
- xmlns:command="http://www.galasoft.ch/mvvmlight"
DataContext="{Binding SideMenuDemo,Source={StaticResource Locator}}"
Background="{DynamicResource RegionBrush}">
-
-
-
-
-
+
+
+
+
+
diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml
index 909f10d9..775e9bc3 100644
--- a/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml
+++ b/src/Shared/HandyControlDemo_Shared/UserControl/Main/LeftMainContent.xaml
@@ -1,6 +1,4 @@
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Collections/ManualObservableCollection!1.cs b/src/Shared/HandyControl_Shared/Collections/ManualObservableCollection!1.cs
new file mode 100644
index 00000000..39abfc7e
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Collections/ManualObservableCollection!1.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+
+namespace HandyControl.Collections
+{
+ [Serializable]
+ public class ManualObservableCollection : Collection, INotifyCollectionChanged, INotifyPropertyChanged
+ {
+ private SimpleMonitor _monitor = new SimpleMonitor();
+
+ private const string CountString = "Count";
+
+ private const string IndexerName = "Item[]";
+
+ private bool _canNotify = true;
+
+ public bool CanNotify
+ {
+ get => _canNotify;
+ set
+ {
+ _canNotify = value;
+
+ if (value)
+ {
+ if (_oldCount != Count)
+ {
+ OnPropertyChanged(CountString);
+ }
+
+ OnPropertyChanged(IndexerName);
+ OnCollectionReset();
+ }
+ else
+ {
+ _oldCount = Count;
+ }
+ }
+ }
+
+ private int _oldCount;
+
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public ManualObservableCollection()
+ {
+
+ }
+
+ // ReSharper disable once AssignNullToNotNullAttribute
+ public ManualObservableCollection(List list) : base(list != null ? new List(list.Count) : list) => CopyFrom(list);
+
+ public ManualObservableCollection(IEnumerable collection)
+ {
+ if (collection == null) throw new ArgumentNullException(nameof(collection));
+ CopyFrom(collection);
+ }
+
+ private void CopyFrom(IEnumerable collection)
+ {
+ var items = Items;
+ if (collection != null)
+ {
+ using var enumerator = collection.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ items.Add(enumerator.Current);
+ }
+ }
+ }
+
+ public void Move(int oldIndex, int newIndex) => MoveItem(oldIndex, newIndex);
+
+ protected override void ClearItems()
+ {
+ CheckReentrancy();
+ base.ClearItems();
+ OnPropertyChanged(CountString);
+ OnPropertyChanged(IndexerName);
+ OnCollectionReset();
+ }
+
+ protected override void RemoveItem(int index)
+ {
+ CheckReentrancy();
+ var removedItem = this[index];
+
+ base.RemoveItem(index);
+
+ OnPropertyChanged(CountString);
+ OnPropertyChanged(IndexerName);
+ OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, index);
+ }
+
+ protected override void InsertItem(int index, T item)
+ {
+ CheckReentrancy();
+ base.InsertItem(index, item);
+
+ OnPropertyChanged(CountString);
+ OnPropertyChanged(IndexerName);
+ OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
+ }
+
+ protected override void SetItem(int index, T item)
+ {
+ CheckReentrancy();
+ var originalItem = this[index];
+ base.SetItem(index, item);
+
+ OnPropertyChanged(IndexerName);
+ OnCollectionChanged(NotifyCollectionChangedAction.Replace, originalItem, item, index);
+ }
+
+ protected virtual void MoveItem(int oldIndex, int newIndex)
+ {
+ CheckReentrancy();
+
+ var removedItem = this[oldIndex];
+
+ base.RemoveItem(oldIndex);
+ base.InsertItem(newIndex, removedItem);
+
+ OnPropertyChanged(IndexerName);
+ OnCollectionChanged(NotifyCollectionChangedAction.Move, removedItem, newIndex, oldIndex);
+ }
+
+ protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
+ {
+ if (!CanNotify || PropertyChanged == null) return;
+
+ PropertyChanged.Invoke(this, e);
+ }
+
+ protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ if (!CanNotify || CollectionChanged == null) return;
+
+ using (BlockReentrancy())
+ {
+ // ReSharper disable once PossibleNullReferenceException
+ CollectionChanged(this, e);
+ }
+ }
+
+ protected IDisposable BlockReentrancy()
+ {
+ _monitor.Enter();
+ return _monitor;
+ }
+
+ protected void CheckReentrancy()
+ {
+ if (_monitor.Busy && CollectionChanged != null && CollectionChanged.GetInvocationList().Length > 1)
+ {
+ throw new InvalidOperationException("ObservableCollectionReentrancyNotAllowed");
+ }
+ }
+
+ private void OnPropertyChanged(string propertyName) =>
+ OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
+
+ private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index) =>
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
+
+ private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index, int oldIndex) =>
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex));
+
+ private void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index) =>
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
+
+ private void OnCollectionReset() =>
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+
+ private class SimpleMonitor : IDisposable
+ {
+ public void Enter() => ++_busyCount;
+
+ public void Dispose() => --_busyCount;
+
+ public bool Busy => _busyCount > 0;
+
+ private int _busyCount;
+ }
+ }
+}
diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
index 8e5bce5f..1bad34b4 100644
--- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
+++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
@@ -9,6 +9,7 @@
HandyControl
+