Refactor ProductDisplay
This commit is contained in:
parent
d336848ed0
commit
1ce5fedc8c
@ -54,7 +54,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitialDisplay(List<LibraryBook> dbBooks, Views.ProductsGrid.ProductsDisplay2 productsGrid)
|
public void InitialDisplay(List<LibraryBook> dbBooks, Views.ProductsDisplay2 productsGrid)
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
xmlns:vm="clr-namespace:LibationWinForms.AvaloniaUI.ViewModels"
|
xmlns:vm="clr-namespace:LibationWinForms.AvaloniaUI.ViewModels"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:views="clr-namespace:LibationWinForms.AvaloniaUI.Views"
|
xmlns:views="clr-namespace:LibationWinForms.AvaloniaUI.Views"
|
||||||
xmlns:prgid="clr-namespace:LibationWinForms.AvaloniaUI.Views.ProductsGrid"
|
|
||||||
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
|
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
|
||||||
mc:Ignorable="d" d:DesignWidth="1850" d:DesignHeight="700"
|
mc:Ignorable="d" d:DesignWidth="1850" d:DesignHeight="700"
|
||||||
x:Class="LibationWinForms.AvaloniaUI.Views.MainWindow"
|
x:Class="LibationWinForms.AvaloniaUI.Views.MainWindow"
|
||||||
@ -172,7 +171,7 @@
|
|||||||
</SplitView.Pane>
|
</SplitView.Pane>
|
||||||
|
|
||||||
<!-- Product Display Grid -->
|
<!-- Product Display Grid -->
|
||||||
<prgid:ProductsDisplay2
|
<views:ProductsDisplay2
|
||||||
DataContext="{Binding ProductsDisplay}"
|
DataContext="{Binding ProductsDisplay}"
|
||||||
LiberateClicked="ProductsDisplay_LiberateClicked"
|
LiberateClicked="ProductsDisplay_LiberateClicked"
|
||||||
Name="productsDisplay" />
|
Name="productsDisplay" />
|
||||||
|
|||||||
@ -3,7 +3,6 @@ using Avalonia;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using System;
|
using System;
|
||||||
using LibationWinForms.AvaloniaUI.Views.ProductsGrid;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using LibationWinForms.AvaloniaUI.ViewModels;
|
using LibationWinForms.AvaloniaUI.ViewModels;
|
||||||
using LibationFileManager;
|
using LibationFileManager;
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
xmlns:views="clr-namespace:LibationWinForms.AvaloniaUI.Views"
|
xmlns:views="clr-namespace:LibationWinForms.AvaloniaUI.Views"
|
||||||
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
|
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
|
||||||
mc:Ignorable="d" d:DesignWidth="1560" d:DesignHeight="400"
|
mc:Ignorable="d" d:DesignWidth="1560" d:DesignHeight="400"
|
||||||
x:Class="LibationWinForms.AvaloniaUI.Views.ProductsGrid.ProductsDisplay2">
|
x:Class="LibationWinForms.AvaloniaUI.Views.ProductsDisplay2">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|
||||||
@ -0,0 +1,263 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using DataLayer;
|
||||||
|
using FileLiberator;
|
||||||
|
using LibationFileManager;
|
||||||
|
using LibationWinForms.AvaloniaUI.ViewModels;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace LibationWinForms.AvaloniaUI.Views
|
||||||
|
{
|
||||||
|
public partial class ProductsDisplay2 : UserControl
|
||||||
|
{
|
||||||
|
public event EventHandler<LibraryBook> LiberateClicked;
|
||||||
|
|
||||||
|
private ProductsDisplayViewModel _viewModel => DataContext as ProductsDisplayViewModel;
|
||||||
|
private GridView.ImageDisplay imageDisplay;
|
||||||
|
|
||||||
|
public ProductsDisplay2()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
Configure_ColumnCustomization();
|
||||||
|
|
||||||
|
foreach (var column in productsGrid.Columns)
|
||||||
|
{
|
||||||
|
column.CustomSortComparer = new RowComparer(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProductsGrid_Sorting(object sender, DataGridColumnEventArgs e)
|
||||||
|
{
|
||||||
|
_viewModel.Sort(e.Column);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveColumn_PropertyChanged(object sender, Avalonia.AvaloniaPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is DataGridColumn col && e.Property.Name == nameof(DataGridColumn.IsVisible))
|
||||||
|
{
|
||||||
|
col.DisplayIndex = 0;
|
||||||
|
col.CanUserReorder = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
|
||||||
|
productsGrid = this.FindControl<DataGrid>(nameof(productsGrid));
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Column Customizations
|
||||||
|
|
||||||
|
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(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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Button Click Handlers
|
||||||
|
|
||||||
|
public void LiberateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
var button = args.Source as Button;
|
||||||
|
|
||||||
|
if (button.DataContext is SeriesEntrys2 sEntry)
|
||||||
|
{
|
||||||
|
_viewModel.ToggleSeriesExpanded(sEntry);
|
||||||
|
|
||||||
|
//Expanding and collapsing reset the list, which will cause focus to shift
|
||||||
|
//to the topright cell. Reset focus onto the clicked button's cell.
|
||||||
|
((sender as Control).Parent.Parent as DataGridCell)?.Focus();
|
||||||
|
}
|
||||||
|
else if (button.DataContext is LibraryBookEntry2 lbEntry)
|
||||||
|
{
|
||||||
|
LiberateClicked?.Invoke(this, lbEntry.LibraryBook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cover_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
if (sender is not Image tblock || tblock.DataContext is not GridEntry2 gEntry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var picDef = new PictureDefinition(gEntry.LibraryBook.Book.PictureLarge ?? gEntry.LibraryBook.Book.PictureId, PictureSize.Native);
|
||||||
|
|
||||||
|
void PictureCached(object sender, PictureCachedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Definition.PictureId == picDef.PictureId)
|
||||||
|
imageDisplay.CoverPicture = e.Picture;
|
||||||
|
|
||||||
|
PictureStorage.PictureCached -= PictureCached;
|
||||||
|
}
|
||||||
|
|
||||||
|
PictureStorage.PictureCached += PictureCached;
|
||||||
|
(bool isDefault, byte[] initialImageBts) = PictureStorage.GetPicture(picDef);
|
||||||
|
|
||||||
|
var windowTitle = $"{gEntry.Title} - Cover";
|
||||||
|
|
||||||
|
if (imageDisplay is null || imageDisplay.IsDisposed || !imageDisplay.Visible)
|
||||||
|
{
|
||||||
|
imageDisplay = new GridView.ImageDisplay();
|
||||||
|
imageDisplay.RestoreSizeAndLocation(Configuration.Instance);
|
||||||
|
imageDisplay.FormClosed += (_, _) => imageDisplay.SaveSizeAndLocation(Configuration.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
imageDisplay.BookSaveDirectory = AudibleFileStorage.Audio.GetDestinationDirectory(gEntry.LibraryBook);
|
||||||
|
imageDisplay.PictureFileName = System.IO.Path.GetFileName(AudibleFileStorage.Audio.GetBooksDirectoryFilename(gEntry.LibraryBook, ".jpg"));
|
||||||
|
imageDisplay.Text = windowTitle;
|
||||||
|
imageDisplay.CoverPicture = initialImageBts;
|
||||||
|
if (!isDefault)
|
||||||
|
PictureStorage.PictureCached -= PictureCached;
|
||||||
|
|
||||||
|
if (!imageDisplay.Visible)
|
||||||
|
imageDisplay.Show(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Description_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
if (sender is TextBlock tblock && tblock.DataContext is GridEntry2 gEntry)
|
||||||
|
{
|
||||||
|
var pt = tblock.Parent.PointToScreen(tblock.Parent.Bounds.TopRight);
|
||||||
|
var displayWindow = new GridView.DescriptionDisplay
|
||||||
|
{
|
||||||
|
SpawnLocation = new System.Drawing.Point(pt.X, pt.Y),
|
||||||
|
DescriptionText = gEntry.LongDescription,
|
||||||
|
BorderThickness = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
void CloseWindow(object o, DataGridRowEventArgs e)
|
||||||
|
{
|
||||||
|
displayWindow.Close();
|
||||||
|
}
|
||||||
|
productsGrid.LoadingRow += CloseWindow;
|
||||||
|
displayWindow.FormClosed += (_, _) =>
|
||||||
|
{
|
||||||
|
productsGrid.LoadingRow -= CloseWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
displayWindow.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTagsButtonClick(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
var button = args.Source as Button;
|
||||||
|
|
||||||
|
if (button.DataContext is LibraryBookEntry2 lbEntry)
|
||||||
|
{
|
||||||
|
var bookDetailsForm = new LibationWinForms.Dialogs.BookDetailsDialog(lbEntry.LibraryBook);
|
||||||
|
if (bookDetailsForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
||||||
|
lbEntry.Commit(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,111 +0,0 @@
|
|||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using FileLiberator;
|
|
||||||
using LibationFileManager;
|
|
||||||
using LibationWinForms.AvaloniaUI.ViewModels;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
|
|
||||||
{
|
|
||||||
public partial class ProductsDisplay2
|
|
||||||
{
|
|
||||||
private GridView.ImageDisplay imageDisplay;
|
|
||||||
private void Configure_Buttons() { }
|
|
||||||
|
|
||||||
public void LiberateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
|
||||||
{
|
|
||||||
var button = args.Source as Button;
|
|
||||||
|
|
||||||
if (button.DataContext is SeriesEntrys2 sEntry)
|
|
||||||
{
|
|
||||||
_viewModel.ToggleSeriesExpanded(sEntry);
|
|
||||||
|
|
||||||
//Expanding and collapsing reset the list, which will cause focus to shift
|
|
||||||
//to the topright cell. Reset focus onto the clicked button's cell.
|
|
||||||
((sender as Control).Parent.Parent as DataGridCell)?.Focus();
|
|
||||||
}
|
|
||||||
else if (button.DataContext is LibraryBookEntry2 lbEntry)
|
|
||||||
{
|
|
||||||
LiberateClicked?.Invoke(this, lbEntry.LibraryBook);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Cover_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
|
||||||
{
|
|
||||||
if (sender is not Image tblock || tblock.DataContext is not GridEntry2 gEntry)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var picDef = new PictureDefinition(gEntry.LibraryBook.Book.PictureLarge ?? gEntry.LibraryBook.Book.PictureId, PictureSize.Native);
|
|
||||||
|
|
||||||
void PictureCached(object sender, PictureCachedEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.Definition.PictureId == picDef.PictureId)
|
|
||||||
imageDisplay.CoverPicture = e.Picture;
|
|
||||||
|
|
||||||
PictureStorage.PictureCached -= PictureCached;
|
|
||||||
}
|
|
||||||
|
|
||||||
PictureStorage.PictureCached += PictureCached;
|
|
||||||
(bool isDefault, byte[] initialImageBts) = PictureStorage.GetPicture(picDef);
|
|
||||||
|
|
||||||
var windowTitle = $"{gEntry.Title} - Cover";
|
|
||||||
|
|
||||||
if (imageDisplay is null || imageDisplay.IsDisposed || !imageDisplay.Visible)
|
|
||||||
{
|
|
||||||
imageDisplay = new GridView.ImageDisplay();
|
|
||||||
imageDisplay.RestoreSizeAndLocation(Configuration.Instance);
|
|
||||||
imageDisplay.FormClosed += (_, _) => imageDisplay.SaveSizeAndLocation(Configuration.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
imageDisplay.BookSaveDirectory = AudibleFileStorage.Audio.GetDestinationDirectory(gEntry.LibraryBook);
|
|
||||||
imageDisplay.PictureFileName = System.IO.Path.GetFileName(AudibleFileStorage.Audio.GetBooksDirectoryFilename(gEntry.LibraryBook, ".jpg"));
|
|
||||||
imageDisplay.Text = windowTitle;
|
|
||||||
imageDisplay.CoverPicture = initialImageBts;
|
|
||||||
if (!isDefault)
|
|
||||||
PictureStorage.PictureCached -= PictureCached;
|
|
||||||
|
|
||||||
if (!imageDisplay.Visible)
|
|
||||||
imageDisplay.Show(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Description_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
|
||||||
{
|
|
||||||
if (sender is TextBlock tblock && tblock.DataContext is GridEntry2 gEntry)
|
|
||||||
{
|
|
||||||
var pt = tblock.Parent.PointToScreen(tblock.Parent.Bounds.TopRight);
|
|
||||||
var displayWindow = new GridView.DescriptionDisplay
|
|
||||||
{
|
|
||||||
SpawnLocation = new System.Drawing.Point(pt.X, pt.Y),
|
|
||||||
DescriptionText = gEntry.LongDescription,
|
|
||||||
BorderThickness = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
void CloseWindow(object o, DataGridRowEventArgs e)
|
|
||||||
{
|
|
||||||
displayWindow.Close();
|
|
||||||
}
|
|
||||||
productsGrid.LoadingRow += CloseWindow;
|
|
||||||
displayWindow.FormClosed += (_, _) =>
|
|
||||||
{
|
|
||||||
productsGrid.LoadingRow -= CloseWindow;
|
|
||||||
};
|
|
||||||
|
|
||||||
displayWindow.Show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnTagsButtonClick(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
|
||||||
{
|
|
||||||
var button = args.Source as Button;
|
|
||||||
|
|
||||||
if (button.DataContext is LibraryBookEntry2 lbEntry)
|
|
||||||
{
|
|
||||||
var bookDetailsForm = new LibationWinForms.Dialogs.BookDetailsDialog(lbEntry.LibraryBook);
|
|
||||||
if (bookDetailsForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
|
||||||
lbEntry.Commit(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,120 +0,0 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
using LibationFileManager;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
|
|
||||||
{
|
|
||||||
public partial class ProductsDisplay2
|
|
||||||
{
|
|
||||||
private 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using DataLayer;
|
|
||||||
using LibationWinForms.AvaloniaUI.ViewModels;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
|
|
||||||
{
|
|
||||||
public partial class ProductsDisplay2 : UserControl
|
|
||||||
{
|
|
||||||
public event EventHandler<LibraryBook> LiberateClicked;
|
|
||||||
|
|
||||||
private ProductsDisplayViewModel _viewModel => DataContext as ProductsDisplayViewModel;
|
|
||||||
|
|
||||||
public ProductsDisplay2()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
Configure_Buttons();
|
|
||||||
Configure_ColumnCustomization();
|
|
||||||
|
|
||||||
foreach (var column in productsGrid.Columns)
|
|
||||||
{
|
|
||||||
column.CustomSortComparer = new RowComparer(column);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProductsGrid_Sorting(object sender, DataGridColumnEventArgs e)
|
|
||||||
{
|
|
||||||
_viewModel.Sort(e.Column);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RemoveColumn_PropertyChanged(object sender, Avalonia.AvaloniaPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (sender is DataGridColumn col && e.Property.Name == nameof(DataGridColumn.IsVisible))
|
|
||||||
{
|
|
||||||
col.DisplayIndex = 0;
|
|
||||||
col.CanUserReorder = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
AvaloniaXamlLoader.Load(this);
|
|
||||||
|
|
||||||
productsGrid = this.FindControl<DataGrid>(nameof(productsGrid));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user