using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using JD.Rosetta.Module.ViewModel;
using JetBrains.Annotations;
using Ubisoft.Collections;
namespace JD.Rosetta.Module.Controls
{
///
/// Interaction logic for CheckBoxList.xaml
/// Feed it a collection of ItemCheckableViewModel
///
public partial class CheckBoxList : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public CheckBoxList()
{
InitializeComponent();
Loaded += CheckBoxList_Loaded;
}
private void CheckBoxList_Loaded(object sender, RoutedEventArgs e)
{
AreAllBoxesCheckedOrUnchecked = AreAllBoxesCheckedAtStart;
Loaded -= CheckBoxList_Loaded; // Avoid having the event called more than once, which unchecks previously checked boxes while loading
}
#region Dependency properties
public static readonly DependencyProperty CheckOrUncheckAllBoxesTextProperty = DependencyProperty.Register("CheckOrUncheckAllBoxesText",
typeof(string),
typeof(CheckBoxList),
new PropertyMetadata(string.Empty));
public string CheckOrUncheckAllBoxesText
{
get => (string) GetValue(CheckOrUncheckAllBoxesTextProperty);
set => SetValue(CheckOrUncheckAllBoxesTextProperty, value);
}
public static readonly DependencyProperty ItemStatesProperty = DependencyProperty.Register("ItemStates",
typeof(IEnumerable),
typeof(CheckBoxList),
new FrameworkPropertyMetadata(null));
public IEnumerable ItemStates
{
get => (IEnumerable) GetValue(ItemStatesProperty);
set => SetValue(ItemStatesProperty, value);
}
public static readonly DependencyProperty AreAllBoxesCheckedAtStartProperty = DependencyProperty.Register("AreAllBoxesCheckedAtStart",
typeof(bool),
typeof(CheckBoxList),
new PropertyMetadata(false));
public bool AreAllBoxesCheckedAtStart
{
get => (bool) GetValue(AreAllBoxesCheckedAtStartProperty);
set => SetValue(AreAllBoxesCheckedAtStartProperty, value);
}
#endregion
#region Checkboxes update logic
private bool? _areAllBoxesCheckedOrUnchecked;
public bool? AreAllBoxesCheckedOrUnchecked
{
get
{
if (ItemStates != null)
{
if (ItemStates.All(s => s.IsChecked))
_areAllBoxesCheckedOrUnchecked = true;
else if (ItemStates.All(s => !s.IsChecked))
_areAllBoxesCheckedOrUnchecked = false;
else
_areAllBoxesCheckedOrUnchecked = null;
}
return _areAllBoxesCheckedOrUnchecked;
}
set
{
if (value == null)
{
value = false;
}
RefreshCheckBoxes(value);
OnPropertyChanged();
}
}
private void ItemCheckBox_OnCheckedChanged(object sender, RoutedEventArgs e)
{
OnPropertyChanged(nameof(AreAllBoxesCheckedOrUnchecked));
}
private void RefreshCheckBoxes(bool? checkOrUncheckAllBoxes)
{
if (checkOrUncheckAllBoxes != null)
ItemStates.ForEach(l => l.IsChecked = (bool)checkOrUncheckAllBoxes);
}
#endregion
#region UI layout logic
public double MaxListHeight
{
get => GlobalStackPanel.ActualHeight - CheckOrUncheckAllBoxStackPanel.ActualHeight - GlobalStackPanel.Margin.Top - GlobalStackPanel.Margin.Bottom
- CheckOrUncheckAllBoxStackPanel.Margin.Top - CheckOrUncheckAllBoxStackPanel.Margin.Bottom + 10; // Adding 10 seems to help for whatever reason
}
private void GlobalStackPanel_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.HeightChanged)
OnPropertyChanged(nameof(MaxListHeight));
}
private void CheckOrUncheckAllBoxStackPanel_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.HeightChanged)
OnPropertyChanged(nameof(MaxListHeight));
}
#endregion
#region INotifyPropertyChanged implementation
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}