Преглед изворни кода

Added filter button for product dock

Kenric Nugteren пре 1 година
родитељ
комит
45a7ad4714

+ 6 - 0
prs.desktop/DockPanels/ProductLookupDock.xaml

@@ -5,6 +5,7 @@
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:dynamicGrid="clr-namespace:InABox.DynamicGrid;assembly=InABox.Wpf"
              xmlns:classes="clr-namespace:Comal.Classes;assembly=PRSClasses"
+             xmlns:local="clr-namespace:PRSDesktop"
              mc:Ignorable="d"
              d:DesignHeight="800" d:DesignWidth="500" Background="WhiteSmoke">
     <Grid Margin="5">
@@ -16,6 +17,11 @@
 
         <DockPanel Grid.Row="0">
             <Label DockPanel.Dock="Left" Content="Search" />
+            <local:ProductDockFilterButton DockPanel.Dock="Right"
+                                           Margin="5,0,0,0"
+                                           MaxWidth="100"
+                                           x:Name="FilterButton"
+                                           OnFilterRefresh="FilterButton_OnFilterRefresh"/>
             <TextBox x:Name="Search" DockPanel.Dock="Left" TextChanged="Search_TextChanged" KeyUp="Search_KeyUp"
                      Background="LightYellow" />
         </DockPanel>

+ 313 - 293
prs.desktop/DockPanels/ProductLookupDock.xaml.cs

@@ -10,385 +10,405 @@ using System.Windows.Input;
 using System.Windows.Media.Imaging;
 using Comal.Classes;
 using InABox.Clients;
+using InABox.Configuration;
 using InABox.Core;
 using InABox.Dxf;
+using InABox.Wpf;
 using InABox.WPF;
 using Microsoft.Win32;
 
-namespace PRSDesktop
+namespace PRSDesktop;
+
+public class ProductDockFilterButton : FilterButton<Product>
 {
-    /// <summary>
-    ///     Interaction logic for ProductLookup.xaml
-    /// </summary>
-    public partial class ProductLookupDock : UserControl, IDockPanel
+    public ProductDockFilterButton() : base(
+        new GlobalConfiguration<CoreFilterDefinitions>("ProductDock.Product"),
+        new UserConfiguration<CoreFilterDefinitions>("ProductDock.Product"))
     {
-        private ProductHoldingControl _holdings;
+    }
+}
+
+
+/// <summary>
+///     Interaction logic for ProductLookup.xaml
+/// </summary>
+public partial class ProductLookupDock : UserControl, IDockPanel
+{
+    private ProductHoldingControl? _holdings;
+    private Product[] Products = Array.Empty<Product>();
 
-        public ProductLookupDock()
+    public ProductLookupDock()
+    {
+        InitializeComponent();
+    }
+    
+    public void Setup()
+    {
+        if (!Security.CanView<StockLocation>())
+            return;
+        if (_holdings == null)
         {
-            InitializeComponent();
+            _holdings = new ProductHoldingControl();
+            HoldingsTab.Content = _holdings;
+            HoldingsTab.Visibility = Visibility.Visible;
         }
-        
-        public void Setup()
-        {
-            if (!Security.CanView<StockLocation>())
-                return;
-            if (_holdings == null)
-            {
-                _holdings = new ProductHoldingControl();
-                HoldingsTab.Content = _holdings;
-                HoldingsTab.Visibility = Visibility.Visible;
-            }
 
-            _holdings.Refresh(true, false);
-        }
+        _holdings.Refresh(true, false);
+    }
 
-        public void Refresh()
+    public void Refresh()
+    {
+
+    }
+
+    private Filter<Product>? GetSearchFilter()
+    {
+        var search = Search.Text;
+        if (!string.IsNullOrEmpty(search))
         {
-            
+            return new Filter<Product>(x => x.Code).Contains(Search.Text).Or(x => x.Name).Contains(search);
         }
-        
-        private void Search_TextChanged(object sender, TextChangedEventArgs e)
+        else
         {
+            return null;
         }
+    }
+
+    private void Reload()
+    {
+        var filters = new Filters<Product>();
+        filters.Add(GetSearchFilter());
+        filters.Add(FilterButton.GetFilter());
+        var filter = filters.Combine() ?? new Filter<Product>().None();
 
-        private void Search_KeyUp(object sender, KeyEventArgs e)
+        using (new WaitCursor())
         {
-            if (e.Key == Key.Enter)
+            Products = Client.Query(
+                filter,
+                new Columns<Product>(x => x.ID, x => x.Code, x => x.Name, x => x.Image.ID, x => x.Image.FileName),
+                new SortOrder<Product>(x => x.Code))
+                .ToObjects<Product>().ToArray();
+
+            Items.ItemsSource = Products;
+            if (Products.Any())
             {
-                var search = Search.Text;
-                if (!string.IsNullOrEmpty(search))
-                {
-                    using (new WaitCursor())
-                    {
-                        var products = new Client<Product>().Query(
-                            new Filter<Product>(x => x.Code).Contains(Search.Text).Or(x => x.Name)
-                                .Contains(search), //.And(x => x.Image.ID).IsNotEqualTo(Guid.Empty),
-                            new Columns<Product>(x => x.ID, x => x.Code, x => x.Name, x => x.Image.ID, x => x.Image.FileName),
-                            new SortOrder<Product>(x => x.Code)
-                        );
-
-                        var items = products.Rows.Select(x => x.ToObject<Product>()).ToArray();
-  
-
-                        Items.ItemsSource = items;
-                        if (items.Any())
-                        {
-                            Items.Focus();
-                            Items.SelectedIndex = 0;
-                            var listBoxItem = (ListBoxItem)Items.ItemContainerGenerator.ContainerFromItem(Items.SelectedItem);
-                            if (listBoxItem != null)
-                                listBoxItem.Focus();
-                        }
-
-                        ;
-                    }
-                }
-                else
-                {
-                    Items.ItemsSource = null;
-                    Image.Source = null;
-                }
+                Items.Focus();
+                Items.SelectedIndex = 0;
+                var listBoxItem = (ListBoxItem)Items.ItemContainerGenerator.ContainerFromItem(Items.SelectedItem);
+                listBoxItem?.Focus();
             }
-            else if (e.Key == Key.Down)
+        }
+    }
+
+    private void Search_TextChanged(object sender, TextChangedEventArgs e)
+    {
+    }
+
+    private void Search_KeyUp(object sender, KeyEventArgs e)
+    {
+        if (e.Key == Key.Enter)
+        {
+            Reload();
+        }
+        else if (e.Key == Key.Down)
+        {
+            if (Products.Any())
             {
-                if (Items.ItemsSource != null)
-                {
-                    var items = Items.ItemsSource as Product[];
-                    if (items.Any())
-                    {
-                        Items.Focus();
-                        //Items.SelectedValue = items.First();
-                        Items.SelectedIndex = 0;
-                        var listBoxItem = (ListBoxItem)Items.ItemContainerGenerator.ContainerFromItem(Items.SelectedItem);
-                        listBoxItem.Focus();
-                    }
-                }
+                Items.Focus();
+                //Items.SelectedValue = items.First();
+                Items.SelectedIndex = 0;
+                var listBoxItem = (ListBoxItem)Items.ItemContainerGenerator.ContainerFromItem(Items.SelectedItem);
+                listBoxItem.Focus();
             }
         }
+    }
 
-        private void Items_SelectionChanged(object sender, SelectionChangedEventArgs e)
+    private void Items_SelectionChanged(object sender, SelectionChangedEventArgs e)
+    {
+        Image.Source = null;
+        if (e.AddedItems.Count > 0)
         {
-            Image.Source = null;
-            if (e.AddedItems.Count > 0)
-            {
-                var item = e.AddedItems[0] as Product;
-                if (!item.Image.ID.Equals(Guid.Empty))
-                    new Client<Document>().Query(
-                        new Filter<Document>(x => x.ID).IsEqualTo(item.Image.ID),
-                        new Columns<Document>(x => x.ID, x => x.Data),
-                        null,
-                        (docs, error) =>
+            var item = e.AddedItems[0] as Product;
+            if (!item.Image.ID.Equals(Guid.Empty))
+                new Client<Document>().Query(
+                    new Filter<Document>(x => x.ID).IsEqualTo(item.Image.ID),
+                    new Columns<Document>(x => x.ID, x => x.Data),
+                    null,
+                    (docs, error) =>
+                    {
+                        var row = docs.Rows.FirstOrDefault();
+                        if (row != null)
                         {
-                            var row = docs.Rows.FirstOrDefault();
-                            if (row != null)
-                            {
-                                var id = row.Get<Document, Guid>(x => x.ID);
-                                var ms = new MemoryStream(row.Get<Document, byte[]>(x => x.Data));
-                                var bmp = new Bitmap(ms);
-                                Dispatcher.BeginInvoke(
-                                    new Action<Guid>(o =>
+                            var id = row.Get<Document, Guid>(x => x.ID);
+                            var ms = new MemoryStream(row.Get<Document, byte[]>(x => x.Data));
+                            var bmp = new Bitmap(ms);
+                            Dispatcher.BeginInvoke(
+                                new Action<Guid>(o =>
+                                {
+                                    if (Items.SelectedValue != null)
                                     {
-                                        if (Items.SelectedValue != null)
-                                        {
-                                            var sel = (Product)Items.SelectedValue;
-                                            if (sel.Image.ID == o)
-                                                Image.Source = bmp.AsBitmapImage(false);
-                                        }
-                                    }), id
-                                );
-                            }
+                                        var sel = (Product)Items.SelectedValue;
+                                        if (sel.Image.ID == o)
+                                            Image.Source = bmp.AsBitmapImage(false);
+                                    }
+                                }), id
+                            );
                         }
-                    );
-                else
-                    Image.Source = null;
-                if (Security.CanView<StockLocation>())
-                {
-                    _holdings.Product = item;
-                    _holdings.Refresh(false, true);
-                }
-            }
+                    }
+                );
             else
-            {
                 Image.Source = null;
+            if (Security.CanView<StockLocation>())
+            {
+                _holdings.Product = item;
+                _holdings.Refresh(false, true);
             }
-
-
         }
-
-        private void Items_KeyUp(object sender, KeyEventArgs e)
+        else
         {
+            Image.Source = null;
         }
 
-        private void Items_KeyDown(object sender, KeyEventArgs e)
-        {
-            if (e.Key == Key.Up)
-                if (Items.SelectedIndex == 0)
-                    Search.Focus();
-        }
 
+    }
 
-        private void ImageMenu_Opened(object sender, RoutedEventArgs e)
-        {
-            var pdi = Items.SelectedItem as Product;
-
-            var anyproducts = pdi != null;
-            var validimage = pdi != null && pdi.Image.ID != Guid.Empty;
-            LoadImageFromFile.IsEnabled = anyproducts;
-            SaveImageToFile.IsEnabled = validimage;
-            CopyImageToClipboard.IsEnabled = validimage;
-            PasteImageFromClipboard.IsEnabled = anyproducts && (Clipboard.ContainsData("ProductImage") || Clipboard.ContainsImage());
-            ClearImage.IsEnabled = anyproducts;
-        }
+    private void Items_KeyUp(object sender, KeyEventArgs e)
+    {
+    }
 
-        private string SelectedProducts()
-        {
-            var product = Items.SelectedItem as Product;
-            return product != null ? product.Code : "";
-        }
+    private void Items_KeyDown(object sender, KeyEventArgs e)
+    {
+        if (e.Key == Key.Up)
+            if (Items.SelectedIndex == 0)
+                Search.Focus();
+    }
 
-        private void UpdateProductImages(Guid id, string filename, Bitmap bitmap)
-        {
-            var product = Items.SelectedItem as Product;
-            if (product == null)
-                return;
 
-            var docid = id;
-            if (bitmap != null && docid == Guid.Empty)
+    private void ImageMenu_Opened(object sender, RoutedEventArgs e)
+    {
+        var pdi = Items.SelectedItem as Product;
+
+        var anyproducts = pdi != null;
+        var validimage = pdi != null && pdi.Image.ID != Guid.Empty;
+        LoadImageFromFile.IsEnabled = anyproducts;
+        SaveImageToFile.IsEnabled = validimage;
+        CopyImageToClipboard.IsEnabled = validimage;
+        PasteImageFromClipboard.IsEnabled = anyproducts && (Clipboard.ContainsData("ProductImage") || Clipboard.ContainsImage());
+        ClearImage.IsEnabled = anyproducts;
+    }
+
+    private string SelectedProducts()
+    {
+        var product = Items.SelectedItem as Product;
+        return product != null ? product.Code : "";
+    }
+
+    private void UpdateProductImages(Guid id, string filename, Bitmap? bitmap)
+    {
+        var product = Items.SelectedItem as Product;
+        if (product == null)
+            return;
+
+        var docid = id;
+        if (bitmap != null && docid == Guid.Empty)
+        {
+            byte[] data = null;
+            using (var ms = new MemoryStream())
             {
-                byte[] data = null;
-                using (var ms = new MemoryStream())
-                {
-                    bitmap.Save(ms, ImageFormat.Png);
-                    data = ms.GetBuffer();
-                }
+                bitmap.Save(ms, ImageFormat.Png);
+                data = ms.GetBuffer();
+            }
 
-                var crc = CoreUtils.CalculateCRC(data);
+            var crc = CoreUtils.CalculateCRC(data);
 
-                var doc = new Client<Document>().Query(
-                    new Filter<Document>(x => x.FileName).IsEqualTo(Path.GetFileName(filename)).And(x => x.CRC).IsEqualTo(crc),
-                    new Columns<Document>(x => x.ID)
-                ).Rows.FirstOrDefault()?.ToObject<Document>();
-                if (doc == null)
+            var doc = new Client<Document>().Query(
+                new Filter<Document>(x => x.FileName).IsEqualTo(Path.GetFileName(filename)).And(x => x.CRC).IsEqualTo(crc),
+                new Columns<Document>(x => x.ID)
+            ).Rows.FirstOrDefault()?.ToObject<Document>();
+            if (doc == null)
+            {
+                doc = new Document
                 {
-                    doc = new Document
-                    {
-                        FileName = Path.GetFileName(filename),
-                        CRC = crc,
-                        TimeStamp = DateTime.Now,
-                        Data = data
-                    };
-                    new Client<Document>().Save(doc, "");
-                }
-
-                docid = doc.ID;
+                    FileName = Path.GetFileName(filename),
+                    CRC = crc,
+                    TimeStamp = DateTime.Now,
+                    Data = data
+                };
+                new Client<Document>().Save(doc, "");
             }
 
+            docid = doc.ID;
+        }
 
-            product.Image.ID = CoreUtils.FullGuid;
-            product.CommitChanges();
-            product.Image.ID = docid;
-            product.Image.FileName = Path.GetFileName(filename);
 
-            new Client<Product>().Save(product, "Cleared Product Image", (p, err) => { });
+        product.Image.ID = CoreUtils.FullGuid;
+        product.CommitChanges();
+        product.Image.ID = docid;
+        product.Image.FileName = Path.GetFileName(filename);
 
-            Image.Source = bitmap?.AsBitmapImage();
-        }
+        new Client<Product>().Save(product, "Cleared Product Image", (p, err) => { });
 
-        private Bitmap ConvertDXFFile(string filename)
-        {
-            Bitmap result = null;
+        Image.Source = bitmap?.AsBitmapImage();
+    }
+
+    private Bitmap? ConvertDXFFile(string filename)
+    {
+        Bitmap? result = null;
 
-            using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
+        using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
+        {
+            //String newfile = Path.ChangeExtension(Path.GetFileName(filename), "png");
+            try
             {
-                //String newfile = Path.ChangeExtension(Path.GetFileName(filename), "png");
-                try
-                {
-                    result = DxfUtils.ProcessImage(stream, Path.GetFileNameWithoutExtension(filename));
-                }
-                catch (Exception e)
-                {
-                    MessageBox.Show(e.Message);
-                    result = null;
-                }
+                result = DxfUtils.ProcessImage(stream, Path.GetFileNameWithoutExtension(filename));
+            }
+            catch (Exception e)
+            {
+                MessageWindow.ShowError("Could not load DXF file", e);
+                result = null;
             }
-
-            return result;
         }
 
-        private void LoadImageFromFile_Click(object sender, RoutedEventArgs e)
-        {
-            var product = Items.SelectedItem as Product;
-            if (product == null)
-                return;
+        return result;
+    }
 
-            var dlg = new OpenFileDialog();
-            dlg.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|DXF Files (*.dxf)|*.dxf";
-            if (dlg.ShowDialog() == true)
-            {
-                var filename = dlg.FileName.ToLower();
+    private void LoadImageFromFile_Click(object sender, RoutedEventArgs e)
+    {
+        var product = Items.SelectedItem as Product;
+        if (product == null)
+            return;
 
-                Progress.Show("Updating Images: " + Path.GetFileName(filename));
+        var dlg = new OpenFileDialog();
+        dlg.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|DXF Files (*.dxf)|*.dxf";
+        if (dlg.ShowDialog() == true)
+        {
+            var filename = dlg.FileName.ToLower();
 
-                Bitmap bmp = null;
-                if (Path.GetExtension(filename).ToLower().Equals(".dxf"))
-                    bmp = ConvertDXFFile(filename);
-                else
-                    bmp = System.Drawing.Image.FromFile(filename) as Bitmap;
+            Progress.Show("Updating Images: " + Path.GetFileName(filename));
 
+            Bitmap? bmp = null;
+            if (Path.GetExtension(filename).ToLower().Equals(".dxf"))
+                bmp = ConvertDXFFile(filename);
+            else
+                bmp = System.Drawing.Image.FromFile(filename) as Bitmap;
 
-                UpdateProductImages(Guid.Empty, filename, bmp);
 
-                Progress.Close();
-                MessageBox.Show(string.Format("Imported [{0}] into [{1}]", Path.GetFileName(dlg.FileName), SelectedProducts()));
-            }
-        }
+            UpdateProductImages(Guid.Empty, filename, bmp);
 
-        private void SaveImageToFile_Click(object sender, RoutedEventArgs e)
-        {
-            var product = Items.SelectedItem as Product;
-            if (product == null)
-                return;
-
-            var bmp = (Image.Source as BitmapImage).AsBitmap();
-            var dlg = new SaveFileDialog();
-            dlg.Filter = "Image Files (*.png)|*.png";
-            dlg.FileName = product.Image.FileName;
-            if (dlg.ShowDialog() == true)
-                bmp.Save(dlg.FileName);
+            Progress.Close();
+            MessageBox.Show(string.Format("Imported [{0}] into [{1}]", Path.GetFileName(dlg.FileName), SelectedProducts()));
         }
+    }
 
-        private void CopyImageToClipboard_Click(object sender, RoutedEventArgs e)
-        {
-            var product = Items.SelectedItem as Product;
-            if (product == null)
-                return;
-
-            var bmp = (Image.Source as BitmapImage).AsBitmap();
-            var data = new Tuple<Guid, string, Bitmap>(
-                product.Image.ID,
-                product.Image.FileName,
-                bmp
-            );
-            Clipboard.SetData("ProductImage", data);
-        }
+    private void SaveImageToFile_Click(object sender, RoutedEventArgs e)
+    {
+        var product = Items.SelectedItem as Product;
+        if (product == null)
+            return;
+
+        var bmp = (Image.Source as BitmapImage).AsBitmap();
+        var dlg = new SaveFileDialog();
+        dlg.Filter = "Image Files (*.png)|*.png";
+        dlg.FileName = product.Image.FileName;
+        if (dlg.ShowDialog() == true)
+            bmp.Save(dlg.FileName);
+    }
 
-        private void PasteImageFromClipboard_Click(object sender, RoutedEventArgs e)
-        {
-            var product = Items.SelectedItem as Product;
-            if (product == null)
-                return;
+    private void CopyImageToClipboard_Click(object sender, RoutedEventArgs e)
+    {
+        var product = Items.SelectedItem as Product;
+        if (product == null)
+            return;
+
+        var bmp = (Image.Source as BitmapImage).AsBitmap();
+        var data = new Tuple<Guid, string, Bitmap>(
+            product.Image.ID,
+            product.Image.FileName,
+            bmp
+        );
+        Clipboard.SetData("ProductImage", data);
+    }
+
+    private void PasteImageFromClipboard_Click(object sender, RoutedEventArgs e)
+    {
+        if (Items.SelectedItem is not Product product)
+            return;
 
-            if (MessageBox.Show("Are you sure you wish to update the image for the selected product?", "Update Image", MessageBoxButton.YesNo,
-                    MessageBoxImage.Question) != MessageBoxResult.Yes)
-                return;
+        if (MessageBox.Show("Are you sure you wish to update the image for the selected product?", "Update Image", MessageBoxButton.YesNo,
+                MessageBoxImage.Question) != MessageBoxResult.Yes)
+            return;
 
-            Progress.Show("Updating Images");
+        Progress.Show("Updating Images");
 
-            var id = Guid.Empty;
-            var filename = "";
-            Bitmap bitmap = null;
+        var id = Guid.Empty;
+        var filename = "";
+        Bitmap? bitmap = null;
 
-            if (Clipboard.ContainsData("ProductImage"))
+        if (Clipboard.ContainsData("ProductImage"))
+        {
+            if(Clipboard.GetData("ProductImage") is Tuple<Guid, string, Bitmap> data)
             {
-                var data = Clipboard.GetData("ProductImage") as Tuple<Guid, string, Bitmap>;
                 id = data.Item1;
                 filename = data.Item2;
                 bitmap = data.Item3;
             }
-            else if (Clipboard.ContainsImage())
-            {
-                var data = Clipboard.GetImage();
-                bitmap = data.AsBitmap2();
-
-                filename = string.Format("clip{0:yyyyMMddhhmmss}.png", DateTime.Now);
-                if (Clipboard.ContainsFileDropList())
-                {
-                    var list = Clipboard.GetFileDropList();
-                    if (list.Count > 0)
-                        filename = Path.ChangeExtension(Path.GetFileName(list[0]), ".png");
-                }
-
-                //filename = String.Format("clip{0:yyyyMMddhhmmss}.png",DateTime.Now);
-                //bitmap.Save(filename);
-                id = Guid.Empty;
-            }
+        }
+        else if (Clipboard.ContainsImage())
+        {
+            var data = Clipboard.GetImage();
+            bitmap = data.AsBitmap2();
 
-            if (bitmap == null)
+            filename = string.Format("clip{0:yyyyMMddhhmmss}.png", DateTime.Now);
+            if (Clipboard.ContainsFileDropList())
             {
-                MessageBox.Show("Unable to paste data from clipboard");
-                return;
+                var list = Clipboard.GetFileDropList();
+                if (list.Count > 0)
+                    filename = Path.ChangeExtension(Path.GetFileName(list[0]), ".png");
             }
 
-            Progress.Show("");
-            UpdateProductImages(id, filename, bitmap);
-            Progress.Close();
+            //filename = String.Format("clip{0:yyyyMMddhhmmss}.png",DateTime.Now);
+            //bitmap.Save(filename);
+            id = Guid.Empty;
+        }
 
-            MessageBox.Show(string.Format("Pasted [{0}] into [{1}]", Path.GetFileName(filename), SelectedProducts()));
+        if (bitmap == null)
+        {
+            MessageBox.Show("Unable to paste data from clipboard");
+            return;
         }
 
+        Progress.Show("");
+        UpdateProductImages(id, filename, bitmap);
+        Progress.Close();
 
-        private void ClearImage_Click(object sender, RoutedEventArgs e)
-        {
-            if (MessageBox.Show("Are you sure you wish to clear the image for the selected product?", "Clear Image", MessageBoxButton.YesNo,
-                    MessageBoxImage.Question) != MessageBoxResult.Yes)
-                return;
+        MessageBox.Show(string.Format("Pasted [{0}] into [{1}]", Path.GetFileName(filename), SelectedProducts()));
+    }
 
-            Progress.Show("Clearing Image");
-            UpdateProductImages(Guid.Empty, "", null);
-            Progress.Close();
 
-            MessageBox.Show(string.Format("Cleared image from [{0}]", string.Join(", ", SelectedProducts())));
-        }
+    private void ClearImage_Click(object sender, RoutedEventArgs e)
+    {
+        if (MessageWindow.ShowYesNo("Are you sure you wish to clear the image for the selected product?", "Clear Image"))
+            return;
 
-        private void Grid_MouseMove(object sender, MouseEventArgs e)
-        {
-            if(sender is not Grid grid || grid.Tag is not Product product || e.LeftButton != MouseButtonState.Pressed)
-            {
-                return;
-            }
+        Progress.Show("Clearing Image");
+        UpdateProductImages(Guid.Empty, "", null);
+        Progress.Close();
 
-            DragDrop.DoDragDrop(grid, product, DragDropEffects.Copy);
+        MessageBox.Show(string.Format("Cleared image from [{0}]", string.Join(", ", SelectedProducts())));
+    }
+
+    private void Grid_MouseMove(object sender, MouseEventArgs e)
+    {
+        if(sender is not Grid grid || grid.Tag is not Product product || e.LeftButton != MouseButtonState.Pressed)
+        {
+            return;
         }
+
+        DragDrop.DoDragDrop(grid, product, DragDropEffects.Copy);
+    }
+
+    private void FilterButton_OnFilterRefresh()
+    {
+        Reload();
     }
 }