130 lines
4.2 KiB
C#
130 lines
4.2 KiB
C#
using System.ComponentModel;
|
|
using System.Linq;
|
|
using Microsoft.UI.Xaml;
|
|
using Microsoft.UI.Xaml.Controls;
|
|
using Wino.Controls;
|
|
using Wino.Helpers;
|
|
using Wino.Mail.ViewModels.Data;
|
|
|
|
namespace Wino.Mail.WinUI.Controls.ListView;
|
|
|
|
public partial class WinoThreadMailItemViewModelListViewItem : ListViewItem
|
|
{
|
|
public bool IsThreadExpanded
|
|
{
|
|
get { return (bool)GetValue(IsThreadExpandedProperty); }
|
|
set { SetValue(IsThreadExpandedProperty, value); }
|
|
}
|
|
|
|
public static readonly DependencyProperty IsThreadExpandedProperty = DependencyProperty.Register(nameof(IsThreadExpanded), typeof(bool), typeof(WinoThreadMailItemViewModelListViewItem), new PropertyMetadata(false, new PropertyChangedCallback(OnIsThreadExpandedChanged)));
|
|
|
|
private readonly long _selectionChangeCallbackToken;
|
|
public WinoThreadMailItemViewModelListViewItem()
|
|
{
|
|
DefaultStyleKey = typeof(WinoThreadMailItemViewModelListViewItem);
|
|
|
|
_selectionChangeCallbackToken = RegisterPropertyChangedCallback(IsSelectedProperty, OnIsSelectedChanged);
|
|
}
|
|
|
|
public void Cleanup()
|
|
{
|
|
if (Content is ThreadMailItemViewModel mailItem)
|
|
{
|
|
UnregisterSelectionCallback(mailItem);
|
|
|
|
UnregisterPropertyChangedCallback(IsSelectedProperty, _selectionChangeCallbackToken);
|
|
}
|
|
}
|
|
|
|
private static void OnIsThreadExpandedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs dp)
|
|
{
|
|
// 1. Reflect expansion changes to WinoExpander.
|
|
// 2. Automatically select first item on expansion, if none selected.
|
|
// 3. Unselect all items on collapse.
|
|
|
|
var control = sender as WinoThreadMailItemViewModelListViewItem;
|
|
|
|
var innerControl = control?.GetWinoListViewControl();
|
|
var expander = control?.GetExpander();
|
|
|
|
if (innerControl == null || control == null || expander == null) return;
|
|
|
|
|
|
// 2
|
|
if (control.IsThreadExpanded && innerControl.SelectedItems.Count == 0 && innerControl.Items.Count > 0)
|
|
{
|
|
innerControl.SelectedItems.Clear();
|
|
|
|
// Make item selected, container might not be realized yet, so set on the model.
|
|
// It'll appear selected when container is realized.
|
|
|
|
var firstItem = innerControl.Items.FirstOrDefault() as MailItemViewModel;
|
|
|
|
firstItem?.IsSelected = true;
|
|
}
|
|
|
|
// 1
|
|
expander.IsExpanded = control.IsThreadExpanded;
|
|
|
|
// 3
|
|
if (!control.IsSelected) innerControl?.SelectedItems.Clear();
|
|
}
|
|
|
|
protected override void OnContentChanged(object oldContent, object newContent)
|
|
{
|
|
base.OnContentChanged(oldContent, newContent);
|
|
|
|
if (oldContent is ThreadMailItemViewModel oldMailItem)
|
|
{
|
|
UnregisterSelectionCallback(oldMailItem);
|
|
}
|
|
|
|
if (newContent is ThreadMailItemViewModel newMailItem)
|
|
{
|
|
IsSelected = newMailItem.IsSelected;
|
|
RegisterSelectionCallback(newMailItem);
|
|
}
|
|
}
|
|
|
|
private void OnIsSelectedChanged(DependencyObject sender, DependencyProperty dp)
|
|
{
|
|
IsThreadExpanded = IsSelected;
|
|
}
|
|
|
|
public void UnregisterSelectionCallback(ThreadMailItemViewModel mailItem)
|
|
{
|
|
mailItem.PropertyChanged -= MailPropChanged;
|
|
}
|
|
|
|
private void MailPropChanged(object? sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (sender is not ThreadMailItemViewModel mailItem) return;
|
|
|
|
if (e.PropertyName == nameof(ThreadMailItemViewModel.IsThreadExpanded))
|
|
{
|
|
ApplySelectionForContainer(mailItem);
|
|
}
|
|
}
|
|
|
|
private void RegisterSelectionCallback(ThreadMailItemViewModel mailItem)
|
|
{
|
|
mailItem.PropertyChanged += MailPropChanged;
|
|
}
|
|
|
|
private void ApplySelectionForContainer(ThreadMailItemViewModel mailItem)
|
|
{
|
|
if (IsThreadExpanded != mailItem.IsThreadExpanded) IsThreadExpanded = mailItem.IsThreadExpanded;
|
|
}
|
|
|
|
public WinoListView? GetWinoListViewControl()
|
|
{
|
|
var expander = GetExpander();
|
|
|
|
if (expander?.Content is WinoListView control) return control;
|
|
|
|
return null;
|
|
}
|
|
|
|
public WinoExpander? GetExpander() => WinoVisualTreeHelper.FindDescendants<WinoExpander>(this).FirstOrDefault();
|
|
}
|