using System; using System.Collections; using System.Linq; using System.Threading.Tasks; using System.Windows.Input; using InABox.Core; using InABox.Mobile.Shared; using Syncfusion.Data.Extensions; using Syncfusion.SfDataGrid.XForms; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace InABox.Mobile { public enum MobileGridSelectionMode { None, Single, Multiple } public class PullToRefreshCommand : ICommand { private readonly MobileGrid _grid; public bool CanExecute(object parameter) { return _grid.PullToRefresh; } public void Execute(object parameter) { _grid.RequestRefresh(); } public event EventHandler CanExecuteChanged; public PullToRefreshCommand(MobileGrid grid) { _grid = grid; } } public class MobileGridSelectionArgs : EventArgs { public object[] Selection { get; private set; } public MobileGridSelectionArgs(object[] selection) { Selection = selection; } } public delegate void MobileGridSelectionChanged(object sender, MobileGridSelectionArgs args); public class MobileGridRefreshRequestArgs : EventArgs { } public delegate void MobileGridRefreshRequested(object sender, MobileGridRefreshRequestArgs args); [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MobileGrid { public MobileGridColumns Columns { get; private set; } public object ItemsSource { get => Grid.ItemsSource; set { Grid.ItemsSource = value; UpdateSummaryRow(); } } public object[] SelectedItems => Grid.SelectedItems.ToArray(); private bool _canSearch = true; public bool CanSearch { get => _canSearch; set { _canSearch = value; CheckSearchVisibility(); } } public static readonly BindableProperty PullToRefreshProperty = BindableProperty.Create( nameof(PullToRefresh), typeof(bool), typeof(MobileGrid)); public bool PullToRefresh { get => (bool)GetValue(PullToRefreshProperty); set { SetValue(PullToRefreshProperty, value); UpdateSummaryRow(); } } public static readonly BindableProperty LastUpdatedProperty = BindableProperty.Create( nameof(LastUpdated), typeof(DateTime), typeof(MobileGrid)); public DateTime LastUpdated { get => (DateTime)GetValue(LastUpdatedProperty); set { SetValue(LastUpdatedProperty,value); UpdateSummaryRow(); } } public static readonly BindableProperty ShowRecordCountProperty = BindableProperty.Create( nameof(ShowRecordCount), typeof(bool), typeof(MobileGrid), false); public bool ShowRecordCount { get => (bool)GetValue(ShowRecordCountProperty); set { SetValue(ShowRecordCountProperty,value); UpdateSummaryRow(); } } private void UpdateSummaryRow() { _lastupdate.IsVisible = !LastUpdated.IsEmpty(); _lastupdate.Text = $"{DateTimeToAgeConverter.FormatTime(LastUpdated)}"; _pulltorefresh.IsVisible = PullToRefresh; _numrecords.Text = $"{(ItemsSource as IEnumerable)?.ToList().Count() ?? 0} records"; _numrecords.IsVisible = ShowRecordCount && (ItemsSource is IEnumerable); _refreshgrid.IsVisible = _lastupdate.IsVisible || _pulltorefresh.IsVisible || _numrecords.IsVisible; } public MobileGridSelectionMode SelectionMode { get => Grid.SelectionMode == Syncfusion.SfDataGrid.XForms.SelectionMode.Multiple ? MobileGridSelectionMode.Multiple : Grid.SelectionMode == Syncfusion.SfDataGrid.XForms.SelectionMode.Single ? MobileGridSelectionMode.Single : MobileGridSelectionMode.None; set => Grid.SelectionMode = value == MobileGridSelectionMode.Multiple ? Syncfusion.SfDataGrid.XForms.SelectionMode.Multiple : value == MobileGridSelectionMode.Single ? Syncfusion.SfDataGrid.XForms.SelectionMode.SingleDeselect : Syncfusion.SfDataGrid.XForms.SelectionMode.None; } public event MobileGridSelectionChanged SelectionChanged; public event MobileGridRefreshRequested RefreshRequested; internal void RequestRefresh() { var src = ItemsSource; ItemsSource = null; RefreshRequested?.Invoke(this, new MobileGridRefreshRequestArgs()); ItemsSource = src; } private String _searchText = ""; bool DoSearch(object data) { if (String.IsNullOrWhiteSpace(_searchText)) return true; foreach (var col in Grid.Columns) { var property = data.GetType().GetProperty(col.MappingName); if (property != null && property.PropertyType != typeof(ImageSource)) { var value = property.GetValue(data); var sValue = String.IsNullOrWhiteSpace(col.Format) ? value?.ToString() ?? "" : String.Format($"{{0:{col.Format}}}", value); if (sValue.ToUpper().Contains(_searchText)) return true; } } return false; } public double RowHeight { get => Grid.RowHeight; set => Grid.RowHeight = value; } public void ClearSelection() { Grid.SelectedItem = null; Grid.SelectedItems.Clear(); } public MobileGrid() { InitializeComponent(); Columns = new MobileGridColumns(Grid); Columns.Changed += (sender, args) => CheckSearchVisibility(); SelectionMode = MobileGridSelectionMode.Single; CanSearch = true; Grid.PullToRefreshCommand = new PullToRefreshCommand(this); Grid.QueryCellStyle += (sender, args) => { args.Style.FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)); }; } private void Search_OnTextChanged(object sender, MobileSearchBarTextChangedArgs args) { _searchText = args.Text?.ToUpper() ?? ""; Grid.View.Filter = DoSearch; Grid.View.RefreshFilter(true); UpdateSummaryRow(); } private void Grid_OnGridViewCreated(object sender, GridViewCreatedEventArgs e) { CheckSearchVisibility(); } private void CheckSearchVisibility() { var searchables = Grid.Columns.Any(x=>(x is GridImageColumn) == false); Search.IsVisible = searchables && CanSearch; // if (Grid.View != null) // { // if (Search.IsVisible) // Grid.View.Filter = DoSearch; // else // Grid.View.Filter = null; // } } private void Grid_OnSelectionChanged(object sender, GridSelectionChangedEventArgs e) { //SelectionChanged?.Invoke(this, new MobileGridSelectionArgs(Grid.SelectedItems.ToArray())); } private void Grid_OnGridTapped(object sender, GridTappedEventArgs e) { if (SelectionMode == MobileGridSelectionMode.Multiple) return; var column = Columns[e.RowColumnIndex.ColumnIndex]; if (column.Tapped != null) column.Tapped?.Invoke(column, e.RowData); else SelectionChanged?.Invoke(this, new MobileGridSelectionArgs(new [] { e.RowData })); } // private void SfPullToRefresh_OnRefreshing(object sender, EventArgs e) // { // pullToRefresh.IsRefreshing = true; // var _items = ItemsSource; // ItemsSource = null; // RefreshRequested?.Invoke(this, new MobileGridRefreshRequestArgs()); // pullToRefresh.IsRefreshing = false; // ItemsSource = _items; // } } }