| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 | using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Globalization;using System.Linq;using System.Threading.Tasks;using Syncfusion.Data.Extensions;using Xamarin.Essentials;using Xamarin.Forms;using Xamarin.Forms.Xaml;using XF.Material.Forms;namespace InABox.Mobile{    public class ToolGridLayoutChangedEventArgs : EventArgs    {        public int RowCount { get; private set; }        public int ColCount { get; private set; }        public ToolGridLayoutChangedEventArgs(int rowcount, int colcount)        {            RowCount = rowcount;            ColCount = colcount;        }    }    public delegate void ToolGridLayoutChangedEvent(object sender, ToolGridLayoutChangedEventArgs args);        public class ToolGridViewModel : BindableObject    {        public CoreObservableCollection<IMobileToolItem> Items { get; private set; }        public CoreObservableCollection<IMobileToolItem> VisibleItems { get; private set; }                public int Columns { get; set; }        private bool _disableUpdate = false;                public void BeginUpdate()             => _disableUpdate = true;        public void EndUpdate()        {            _disableUpdate = false;            Refresh();        }        public ToolGridViewModel()        {            Columns = Device.Idiom == TargetIdiom.Tablet ? 6 : 4;            VisibleItems = new CoreObservableCollection<IMobileToolItem>();            Items = new CoreObservableCollection<IMobileToolItem>();            Items.CollectionChanged += (sender, args) =>            {                if (args.OldItems != null)                {                    foreach (var item in args.OldItems?.OfType<MobileToolItem>())                        item.VisibleChanged -= ItemChanged;                }                if (args.NewItems != null)                {                    foreach (var item in args.NewItems.OfType<MobileToolItem>())                        item.VisibleChanged += ItemChanged;                }                Refresh();            };        }        private void ItemChanged(object sender, EventArgs e)             => Refresh();        public void Refresh()        {            if (_disableUpdate)                return;                        VisibleItems.Clear();            VisibleItems.AddRange(Items.Where(x => x.IsVisible).ToArray());            int iRow = 0;            int iCol = 0;            bool bDirty = false;            foreach (var item in VisibleItems)            {                bDirty = iRow != item.Row || iCol != item.Column;                item.Row = iRow;                item.Column = iCol;                iCol++;                if (iCol == Columns)                {                    iRow++;                    iCol = 0;                }            }            if (bDirty)                LayoutChanged?.Invoke(this,new ToolGridLayoutChangedEventArgs(iRow,Columns));        }        public Color BackgroundColor { get; set; }        public event ToolGridLayoutChangedEvent LayoutChanged;    }        [XamlCompilation(XamlCompilationOptions.Compile)]    public partial class MobileToolGrid    {        public IList<IMobileToolItem> Items => _viewModel.Items;                public event EventHandler BeforeTap;        public event EventHandler AfterTap;        private ToolGridViewModel _viewModel = new();                public void BeginUpdate()        {            _viewModel?.BeginUpdate();        }        public void EndUpdate()        {            _viewModel.EndUpdate();        }                public MobileToolGrid()        {            _viewModel.LayoutChanged += _viewModel_OnLayoutChanged;            BeginUpdate();            InitializeComponent();            EndUpdate();        }        public void Refresh()        {            _viewModel.Refresh();        }        private readonly BindableProperty BorderColorProperty = BindableProperty.Create(            nameof(BorderColor),            typeof(Color),            typeof(MobileToolGrid),            Material.Color.SecondaryVariant        );                public Color BorderColor        {            get => (Color)GetValue(BorderColorProperty);            set => SetValue(BorderColorProperty, value);        }        private bool debounce = false;        private async void ToolItem_Tapped(object sender, EventArgs e)        {            if (debounce)                return;            debounce = true;            BeforeTap?.Invoke(this, EventArgs.Empty);            try            {                                if ((sender is Frame frame) && (frame.BindingContext is MobileToolItem item) && item.IsEnabled)                {                    frame.Scale = 0.5;                    await frame.ScaleTo(1, 150);                    item.DoTap();                }                            }            catch (Exception err)            {                MobileLogging.Log(err,"MobileToolGrid");            }            AfterTap?.Invoke(this, EventArgs.Empty);            debounce = false;        }        private void _viewModel_OnLayoutChanged(object sender, ToolGridLayoutChangedEventArgs args)        {            _flexgrid.RowDefinitions.Clear();            for (int i=0; i< args.RowCount; i++)                _flexgrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto});                        _flexgrid.ColumnDefinitions.Clear();            for (int i=0; i< args.ColCount; i++)                _flexgrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star});            BindableLayout.SetItemsSource(_flexgrid, null);            BindableLayout.SetItemsSource(_flexgrid, _viewModel.VisibleItems);        }            }}
 |