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 +