123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- using InABox.Core;
- using InABox.WPF;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Media;
- namespace InABox.DynamicGrid;
- public abstract class CheckBoxDynamicGridColumnFilter : IDynamicGridColumnFilter
- {
- protected HashSet<object?>? SelectedFilters = null;
- private FilterItem[] _items = [];
- private FilterItem _selectAll;
- public event Action<IDynamicGridColumnFilter>? FilterChanged;
- public CheckBoxDynamicGridColumnFilter()
- {
- _selectAll = new(new(), "Select All", this);
- }
- #region Abstract Interface
- protected abstract FilterItem[] GetData();
- public abstract bool FilterRow(CoreRow row);
- #endregion
- protected class FilterItem(object? value, string display, CheckBoxDynamicGridColumnFilter parent) : INotifyPropertyChanged
- {
- private object? _value = value;
- public object? Value
- {
- get => _value;
- set
- {
- _value = value;
- OnPropertyChanged();
- }
- }
- private string _display = display;
- public string Display
- {
- get => _display;
- set
- {
- _display = value;
- OnPropertyChanged();
- }
- }
- public bool IsChecked
- {
- get => this == parent._selectAll
- ? (parent.SelectedFilters is null)
- : (parent.SelectedFilters is null || parent.SelectedFilters.Contains(Value));
- }
- public event PropertyChangedEventHandler? PropertyChanged;
- private void OnPropertyChanged([CallerMemberName] string propertyName = "")
- {
- PropertyChanged?.Invoke(this, new(propertyName));
- }
- public void UpdateChecked()
- {
- OnPropertyChanged(nameof(IsChecked));
- }
- }
- public FrameworkElement CreateControl()
- {
- var grid = new Grid();
- grid.AddRow(GridUnitType.Auto);
- grid.AddRow(GridUnitType.Star);
- var searchBox = new TextBox
- {
- Background = Colors.LightYellow.ToBrush(),
- Margin = new(0.0, 0.0, 0.0, 5.0),
- Padding = new(5.0),
- VerticalContentAlignment = VerticalAlignment.Center
- };
- new TextBoxPlaceholderBehaviour { Text = "Search..." }.Attach(searchBox);
- _items = GetData();
- var itemList = new ListBox
- {
- Margin = new(0.0, 0.0, 0.0, 0.0)
- };
- itemList.ItemTemplate = TemplateGenerator.CreateDataTemplate(() =>
- {
- var box = new CheckBox();
- box.Height = 25;
- box.VerticalAlignment = VerticalAlignment.Center;
- box.VerticalContentAlignment = VerticalAlignment.Center;
- box.HorizontalAlignment = HorizontalAlignment.Stretch;
- box.Bind<FilterItem, string?>(
- CheckBox.ContentProperty, x => x.Display,
- mode: BindingMode.OneWay);
- box.Bind<FilterItem, bool>(
- CheckBox.IsCheckedProperty, x => x.IsChecked,
- mode: BindingMode.OneWay);
- box.Bind<FilterItem, object?>(CheckBox.TagProperty, x => x);
- box.Checked += Box_Checked;
- box.Unchecked += Box_Unchecked;
- return box;
- });
- itemList.HorizontalContentAlignment = HorizontalAlignment.Stretch;
- itemList.VerticalContentAlignment = VerticalAlignment.Center;
- itemList.ItemsSource = CoreUtils.One(_selectAll).Concat(_items);
- searchBox.TextChanged += (o, e) =>
- {
- itemList.ItemsSource = CoreUtils.One(_selectAll)
- .Concat(_items.Where(x => x.Display.Contains(searchBox.Text, StringComparison.CurrentCultureIgnoreCase)));
- };
- grid.AddChild(searchBox, 0, 0);
- grid.AddChild(itemList, 1, 0);
- return grid;
- }
- private bool _updating = false;
- private void Box_Unchecked(object sender, RoutedEventArgs e)
- {
- if (_updating || sender is not CheckBox box || box.Tag is not FilterItem tag) return;
- if(box.Tag == _selectAll)
- {
- if(SelectedFilters is null || SelectedFilters.Count > 0)
- {
- SelectedFilters = new();
- _updating = true;
- foreach(var item in _items)
- {
- item.UpdateChecked();
- }
- _selectAll.UpdateChecked();
- _updating = false;
- FilterChanged?.Invoke(this);
- }
- }
- else
- {
- if(SelectedFilters is null)
- {
- SelectedFilters = _items.Select(x => x.Value).ToHashSet();
- SelectedFilters.Remove(tag.Value);
- _updating = true;
- tag.UpdateChecked();
- _selectAll.UpdateChecked();
- _updating = false;
- FilterChanged?.Invoke(this);
- }
- else if(SelectedFilters.Remove(tag.Value))
- {
- _updating = true;
- tag.UpdateChecked();
- _selectAll.UpdateChecked();
- _updating = false;
- FilterChanged?.Invoke(this);
- }
- }
- }
- private void Box_Checked(object sender, RoutedEventArgs e)
- {
- if (_updating || sender is not CheckBox box || box.Tag is not FilterItem tag) return;
- if(tag == _selectAll)
- {
- if(SelectedFilters is not null)
- {
- SelectedFilters = null;
- _updating = true;
- foreach(var item in _items)
- {
- item.UpdateChecked();
- }
- _selectAll.UpdateChecked();
- _updating = false;
- FilterChanged?.Invoke(this);
- }
- }
- else
- {
- if(SelectedFilters is not null && SelectedFilters.Add(tag.Value))
- {
- _updating = true;
- tag.UpdateChecked();
- _updating = false;
- FilterChanged?.Invoke(this);
- }
- }
- }
- public void ClearFilter()
- {
- if(SelectedFilters is null)
- {
- return;
- }
- SelectedFilters = null;
- _updating = true;
- foreach(var item in _items)
- {
- item.UpdateChecked();
- }
- _selectAll.UpdateChecked();
- _updating = false;
- FilterChanged?.Invoke(this);
- }
- public bool IsFiltered()
- {
- return SelectedFilters is not null;
- }
- }
- public class FuncCheckBoxDynamicGridColumnFilter(
- Func<CoreRow, Predicate<object?>, bool> filter,
- Func<IEnumerable<Tuple<string, object?>>> data) : CheckBoxDynamicGridColumnFilter
- {
- protected override FilterItem[] GetData()
- {
- return data().Select(x => new FilterItem(x.Item2, x.Item1, this)).ToArray();
- }
- public override bool FilterRow(CoreRow row)
- {
- return filter(row, x => SelectedFilters is null || SelectedFilters.Contains(x));
- }
- }
- public class StaticColumnFilter<T>(
- Func<CoreRow, T> rowData,
- Tuple<string, T>[] data) : CheckBoxDynamicGridColumnFilter
- {
- protected override FilterItem[] GetData()
- {
- return data.ToArray(x => new FilterItem(x.Item2, x.Item1, this));
- }
- public override bool FilterRow(CoreRow row)
- {
- return SelectedFilters is null || SelectedFilters.Contains(rowData(row));
- }
- }
- public class DynamicColumnFilter<T>(
- Func<CoreRow, T> rowData,
- Func<DynamicColumnFilter<T>, IEnumerable<Tuple<string, T>>> data) : CheckBoxDynamicGridColumnFilter
- {
- protected override FilterItem[] GetData()
- {
- return data(this).Select(x => new FilterItem(x.Item2, x.Item1, this)).ToArray();
- }
- public override bool FilterRow(CoreRow row)
- {
- return SelectedFilters is null || SelectedFilters.Contains(rowData(row));
- }
- }
|