Add column customizations

This commit is contained in:
Michael Bucari-Tovo 2022-07-13 18:47:43 -06:00
parent c727286d22
commit e23e267d17
8 changed files with 157 additions and 78 deletions

View File

@ -33,7 +33,7 @@
</MenuItem.Styles>
<MenuItem Name="autoScanLibraryToolStripMenuItem" Click="autoScanLibraryToolStripMenuItem_Click" Header="A_uto Scan Library">
<MenuItem.Icon>
<CheckBox Name="autoScanLibraryToolStripMenuItemCheckbox" BorderThickness="0" IsHitTestVisible="False">Toggle _Me0</CheckBox>
<CheckBox Name="autoScanLibraryToolStripMenuItemCheckbox" BorderThickness="0" IsHitTestVisible="False" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Name="noAccountsYetAddAccountToolStripMenuItem" Click="noAccountsYetAddAccountToolStripMenuItem_Click" Header="No accounts yet. A_dd Account..." />

View File

@ -1,16 +1,12 @@
using ApplicationServices;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using DataLayer;
using LibationWinForms.AvaloniaUI.ViewModels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views
{
@ -20,7 +16,6 @@ namespace LibationWinForms.AvaloniaUI.Views
private ItemsRepeater _repeater;
private ScrollViewer _scroller;
private int _selectedIndex;
private Random _random = new Random(0);
private TrackedQueue2<ProcessBook2> Queue => _viewModel.Items;
@ -101,6 +96,8 @@ namespace LibationWinForms.AvaloniaUI.Views
AvaloniaXamlLoader.Load(this);
}
#region Add Books to Queue
private bool isBookInQueue(LibraryBook libraryBook)
=> Queue.Any(b => b?.LibraryBook?.Book?.AudibleProductId == libraryBook.Book.AudibleProductId);
@ -165,6 +162,8 @@ namespace LibationWinForms.AvaloniaUI.Views
_viewModel.AddToQueue(procs);
}
#endregion
#region Control event handlers
private async void ProcessBookControl2_CancelButtonClicked(ProcessBook2 item)

View File

@ -1,13 +1,124 @@
using System;
using Avalonia.Controls;
using LibationFileManager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
{
public partial class ProductsDisplay2
{
private void Configure_ColumnCustomization() { }
ContextMenu contextMenuStrip1 = new ContextMenu();
private void Configure_ColumnCustomization()
{
if (Design.IsDesignMode) return;
productsGrid.ColumnDisplayIndexChanged += ProductsGrid_ColumnDisplayIndexChanged;
var config = Configuration.Instance;
var gridColumnsVisibilities = config.GridColumnsVisibilities;
var displayIndices = config.GridColumnsDisplayIndices;
var contextMenu = new ContextMenu();
contextMenu.MenuClosed += ContextMenu_MenuClosed;
contextMenu.ContextMenuOpening += ContextMenu_ContextMenuOpening;
List<Control> menuItems = new();
contextMenu.Items = menuItems;
menuItems.Add(new MenuItem { Header = "Show / Hide Columns" });
menuItems.Add(new MenuItem { Header = "-" });
var HeaderCell_PI = typeof(DataGridColumn).GetProperty("HeaderCell", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
foreach (var column in productsGrid.Columns)
{
var itemName = column.SortMemberPath;
if (itemName == nameof(ViewModels.GridEntry2.Remove))
continue;
menuItems.Add
(
new MenuItem
{
Header = ((string)column.Header).Replace((char)0xa,' '),
Tag = column,
Margin = new Avalonia.Thickness(6 ,0),
Icon = new CheckBox
{
Width = 50,
}
}
);
var headercell = HeaderCell_PI.GetValue(column) as DataGridColumnHeader;
headercell.ContextMenu = contextMenu;
column.IsVisible = gridColumnsVisibilities.GetValueOrDefault(itemName, true);
}
//We must set DisplayIndex properties in ascending order
foreach (var itemName in displayIndices.OrderBy(i => i.Value).Select(i => i.Key))
{
if (!productsGrid.Columns.Any(c => c.SortMemberPath == itemName))
continue;
var column = productsGrid.Columns
.Single(c => c.SortMemberPath == itemName);
column.DisplayIndex = displayIndices.GetValueOrDefault(itemName, productsGrid.Columns.IndexOf(column));
}
//Remove column is always first;
removeGVColumn.DisplayIndex = 0;
removeGVColumn.CanUserReorder = false;
}
private void ContextMenu_ContextMenuOpening(object sender, System.ComponentModel.CancelEventArgs e)
{
var contextMenu = sender as ContextMenu;
foreach (var mi in contextMenu.Items.OfType<MenuItem>())
{
if (mi.Tag is DataGridColumn column)
{
var cbox = mi.Icon as CheckBox;
cbox.IsChecked = column.IsVisible;
}
}
}
private void ContextMenu_MenuClosed(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var contextMenu = sender as ContextMenu;
var config = Configuration.Instance;
var dictionary = config.GridColumnsVisibilities;
foreach (var mi in contextMenu.Items.OfType<MenuItem>())
{
if (mi.Tag is DataGridColumn column)
{
var cbox = mi.Icon as CheckBox;
column.IsVisible = cbox.IsChecked == true;
dictionary[column.SortMemberPath] = cbox.IsChecked == true;
}
}
//If all columns are hidden, register the context menu on the grid so users can unhide.
if (!productsGrid.Columns.Any(c => c.IsVisible))
productsGrid.ContextMenu = contextMenu;
else
productsGrid.ContextMenu = null;
config.GridColumnsVisibilities = dictionary;
}
private void ProductsGrid_ColumnDisplayIndexChanged(object sender, Avalonia.Controls.DataGridColumnEventArgs e)
{
var config = Configuration.Instance;
var dictionary = config.GridColumnsDisplayIndices;
dictionary[e.Column.SortMemberPath] = e.Column.DisplayIndex;
config.GridColumnsDisplayIndices = dictionary;
}
}
}

View File

@ -25,8 +25,8 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count());
//Avalonia displays items in the DataConncetion from an internal copy of
//the bound list, not the actual bound list. so we need to reflect to get
//the current display order and set the GridEntry.ListIndex correctly.
//the bound list, not the actual bound list. So we need to reflect to get
//the current display order and set each GridEntry.ListIndex correctly.
var DataConnection_PI = typeof(DataGrid).GetProperty("DataConnection", BindingFlags.NonPublic | BindingFlags.Instance);
var DataSource_PI = DataConnection_PI.PropertyType.GetProperty("DataSource", BindingFlags.Public | BindingFlags.Instance);
@ -41,7 +41,7 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
};
//Assign the viewmodel after we subscribe to CollectionChanged
//to ensure that out handler executes first.
//so that out handler executes first.
productsGrid.DataContext = _viewModel;
}
else
@ -52,7 +52,6 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
bindingList.Filter = existingFilter;
ReSort();
}
}
catch (Exception ex)
{

View File

@ -14,8 +14,24 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
{
private void Configure_ScanAndRemove() { }
private bool RemoveColumnVisible
{
get => removeGVColumn.IsVisible;
set
{
if (value)
{
foreach (var book in bindingList.AllItems())
book.Remove = false;
}
removeGVColumn.DisplayIndex = 0;
removeGVColumn.CanUserReorder = value;
removeGVColumn.IsVisible = value;
}
}
public void CloseRemoveBooksColumn()
=> removeGVColumn.IsVisible = false;
=> RemoveColumnVisible = false;
public async Task RemoveCheckedBooksAsync()
{
@ -39,6 +55,7 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
RemovableCountChanged?.Invoke(this, GetAllBookEntries().Count(lbe => lbe.Remove is true));
}
public async Task ScanAndRemoveBooksAsync(params Account[] accounts)
{
RemovableCountChanged?.Invoke(this, 0);

View File

@ -1,38 +1,16 @@
using Avalonia.Controls;
using LibationWinForms.AvaloniaUI.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
{
public partial class ProductsDisplay2
{
private DataGridColumn CurrentSortColumn;
private void Configure_Sorting() { }
private void RegisterCustomColumnComparers()
{
removeGVColumn.CustomSortComparer = new RowComparer(removeGVColumn);
liberateGVColumn.CustomSortComparer = new RowComparer(liberateGVColumn);
titleGVColumn.CustomSortComparer = new RowComparer(titleGVColumn);
authorsGVColumn.CustomSortComparer = new RowComparer(authorsGVColumn);
narratorsGVColumn.CustomSortComparer = new RowComparer(narratorsGVColumn);
lengthGVColumn.CustomSortComparer = new RowComparer(lengthGVColumn);
seriesGVColumn.CustomSortComparer = new RowComparer(seriesGVColumn);
descriptionGVColumn.CustomSortComparer = new RowComparer(descriptionGVColumn);
categoryGVColumn.CustomSortComparer = new RowComparer(categoryGVColumn);
productRatingGVColumn.CustomSortComparer = new RowComparer(productRatingGVColumn);
purchaseDateGVColumn.CustomSortComparer = new RowComparer(purchaseDateGVColumn);
myRatingGVColumn.CustomSortComparer = new RowComparer(myRatingGVColumn);
miscGVColumn.CustomSortComparer = new RowComparer(miscGVColumn);
tagAndDetailsGVColumn.CustomSortComparer = new RowComparer(tagAndDetailsGVColumn);
}
private void ReSort()
{
if (CurrentSortColumn is null)
@ -46,11 +24,6 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
}
}
private DataGridColumn CurrentSortColumn;
private void ProductsGrid_Sorting(object sender, DataGridColumnEventArgs e)
{
//Force the comparer to get the current sort order. We can't

View File

@ -7,8 +7,13 @@
mc:Ignorable="d" d:DesignWidth="1560" d:DesignHeight="400"
x:Class="LibationWinForms.AvaloniaUI.Views.ProductsGrid.ProductsDisplay2">
<Grid>
<DataGrid Name="productsGrid" AutoGenerateColumns="False" Items="{Binding GridEntries}" >
<Grid>
<DataGrid
Name="productsGrid"
AutoGenerateColumns="False"
Items="{Binding GridEntries}"
CanUserReorderColumns="True">
<DataGrid.Columns>
@ -26,10 +31,10 @@
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="80" Header="Cover">
<DataGridTemplateColumn CanUserSort="False" Width="80" Header="Cover" SortMemberPath="Cover">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Tapped="Cover_Click" Height="80" Source="{Binding Cover}" />
<Image Tapped="Cover_Click" Height="80" Source="{Binding Cover}" ToolTip.Tip="Click to see full size" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
@ -88,7 +93,7 @@
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border BorderThickness="3" Height="80">
<TextBlock Tapped="Description_Click" VerticalAlignment="Center" TextWrapping="Wrap" Text="{Binding Description}" />
<TextBlock Tapped="Description_Click" VerticalAlignment="Center" TextWrapping="Wrap" ToolTip.Tip="Click to see full description" Text="{Binding Description}" />
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>

View File

@ -33,20 +33,6 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
private GridEntryBindingList2 bindingList => _viewModel.GridEntries;
DataGridColumn removeGVColumn;
DataGridColumn liberateGVColumn;
DataGridColumn coverGVColumn;
DataGridColumn titleGVColumn;
DataGridColumn authorsGVColumn;
DataGridColumn narratorsGVColumn;
DataGridColumn lengthGVColumn;
DataGridColumn seriesGVColumn;
DataGridColumn descriptionGVColumn;
DataGridColumn categoryGVColumn;
DataGridColumn productRatingGVColumn;
DataGridColumn purchaseDateGVColumn;
DataGridColumn myRatingGVColumn;
DataGridColumn miscGVColumn;
DataGridColumn tagAndDetailsGVColumn;
public ProductsDisplay2()
{
@ -59,6 +45,11 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
Configure_ScanAndRemove();
Configure_Sorting();
foreach ( var column in productsGrid.Columns)
{
column.CustomSortComparer = new RowComparer(column);
}
if (Design.IsDesignMode)
{
using var context = DbContexts.GetContext();
@ -78,22 +69,6 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
productsGrid.LoadingRow += ProductsGrid_LoadingRow;
removeGVColumn = productsGrid.Columns[0];
liberateGVColumn = productsGrid.Columns[1];
coverGVColumn = productsGrid.Columns[2];
titleGVColumn = productsGrid.Columns[3];
authorsGVColumn = productsGrid.Columns[4];
narratorsGVColumn = productsGrid.Columns[5];
lengthGVColumn = productsGrid.Columns[6];
seriesGVColumn = productsGrid.Columns[7];
descriptionGVColumn = productsGrid.Columns[8];
categoryGVColumn = productsGrid.Columns[9];
productRatingGVColumn = productsGrid.Columns[10];
purchaseDateGVColumn = productsGrid.Columns[11];
myRatingGVColumn = productsGrid.Columns[12];
miscGVColumn = productsGrid.Columns[13];
tagAndDetailsGVColumn = productsGrid.Columns[14];
RegisterCustomColumnComparers();
}
private static object tagObj = new();