WPF listbox ContextMenu MenuItem Command and CommandParameter binding in MVVM,cast System.Windows.Controls.SelectedItemCollection to list

//xaml
<ListBox.ContextMenu>
    <ContextMenu>
        <MenuItem Header="ExportAll" 
                  Command="{Binding  ExportCmd}"
                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContextMenu}},Path=PlacementTarget}"/>
        <MenuItem Header="ExportSelected"
                  Command="{Binding ExportSelectedCmd}"
                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContextMenu}},Path=PlacementTarget.SelectedItems}"/>
    </ContextMenu>
</ListBox.ContextMenu>


//mvvm.cs
 private DelCommand exportCmd;
 public DelCommand ExportCmd
 {
     get
     {
         if (exportCmd == null)
         {
             exportCmd = new DelCommand(ExportCmdExecuted);
         }
         return exportCmd;
     }
 }

 private void ExportCmdExecuted(object obj)
 {
     var lbx = obj as ListBox;
     if(lbx!=null)
     {

     }
 }

 private DelCommand exportSelectedCmd;        

 public DelCommand ExportSelectedCmd
 {
     get
     {
         if (exportSelectedCmd == null)
         {
             exportSelectedCmd = new DelCommand(ExportSelectedCmdExecuted);
         }
         return exportSelectedCmd;
     }
 }

 private void ExportSelectedCmdExecuted(object obj)
 {
     var items = ((System.Collections.IList)obj).Cast<Book>()?.ToList();
 }

 

 

 

 

 

 

 

 

 

 

 

 

//xaml
<Window x:Class="WpfApp227.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp227"
        WindowState="Maximized"
        Title="{Binding SelectedIdx,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
    <Grid>
        <ListBox x:Name="lbx"
                 ItemsSource="{Binding BooksList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                 SelectedIndex="{Binding SelectedIdx,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                 SelectedItem="{Binding SelectedBook,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"                 
                 SelectionMode="Extended">
            <ListBox.Resources>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="FontSize" Value="50"/>
                    <Setter Property="HorizontalAlignment" Value="Center"/>
                    <Setter Property="VerticalAlignment" Value="Center"/>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="FontSize" Value="50"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>

                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="FontSize" Value="50"/>
                    <Setter Property="Foreground" Value="Red"/>
                    <Setter Property="FontWeight" Value="Normal"/>
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontSize" Value="100"/>
                            <Setter Property="FontWeight" Value="ExtraBold"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.Resources>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid Height="{Binding DataContext.GridHeight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,
                        RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"
                          Width="{Binding DataContext.GridWidth,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,
                        RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"
                          VerticalAlignment="Stretch"
                          HorizontalAlignment="Stretch">
                        <Grid.Background>
                            <ImageBrush ImageSource="{Binding ImgSource}" Stretch="Uniform"/>
                        </Grid.Background>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Id}" Grid.Row="0" Grid.Column="0"/>
                        <TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1"/>
                        <TextBlock Text="{Binding ISBN}" Grid.Row="1" Grid.Column="0"/>
                        <TextBlock Text="{Binding Title}" Grid.Row="1" Grid.Column="1"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="ExportAll" 
                              Command="{Binding  ExportCmd}"
                              CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContextMenu}},Path=PlacementTarget}"/>
                    <MenuItem Header="ExportSelected"
                              Command="{Binding ExportSelectedCmd}"
                              CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContextMenu}},Path=PlacementTarget.SelectedItems}"/>
                </ContextMenu>
            </ListBox.ContextMenu>
        </ListBox>
    </Grid>
</Window>



//cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp227
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    { 
        private FrameworkElement fe;
        public MainWindow()
        {
            InitializeComponent();
            var vm = new MainVM(this);
            this.DataContext = vm;
        }       
    }

    public class MainVM: INotifyPropertyChanged
    {
        private Window win;
        private FrameworkElement fe;
        public MainVM(Window winValue)
        {
            win = winValue;
            if(win!=null)
            {
                win.Loaded += Win_Loaded;
                win.SizeChanged += Win_SizeChanged;
            }
        }

        private void Win_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            InitGridWidthHeight();
        }

        private void Win_Loaded(object sender, RoutedEventArgs e)
        {
            InitGridWidthHeight();
            InitBooksList();
        }

        private void InitGridWidthHeight()
        {
            var tempFe = win.Content as FrameworkElement;
            if (tempFe != null)
            {
                fe = tempFe;
                GridWidth = fe.ActualWidth;
                GridHeight = fe.ActualHeight / 2;
            }
        }

        private void InitBooksList()
        {
            BooksList = new ObservableCollection<Book>();
            var imgs = Directory.GetFiles(@"../../Images");
            int imgsCount = imgs.Count();
            for (int i = 0; i < 1000; i++)
            {
                BooksList.Add(new Book()
                {
                    Id = i + 1,
                    Name = $"Name_{i + 1}",
                    Title = $"Title+{i + 1}",
                    ISBN = $"ISBN_{i + 1}",
                    ImgSource = GetImgSourceViaUrl(imgs[i % imgsCount])
                });
            }
        }

        private ImageSource GetImgSourceViaUrl(string imgUrl)
        {
            if (!File.Exists(imgUrl))
            {
                return null;
            }
            BitmapImage bmi = new BitmapImage();
            bmi.BeginInit();
            bmi.UriSource = new Uri(imgUrl, UriKind.RelativeOrAbsolute);
            bmi.EndInit();
            if (bmi.CanFreeze)
            {
                bmi.Freeze();
            }
            return bmi;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "")
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler?.Invoke(this, new PropertyChangedEventArgs(propName));
            }
        }


        private ObservableCollection<Book> booksList;
        public ObservableCollection<Book> BooksList
        {
            get
            {
                return booksList;
            }
            set
            {
                if (booksList != value)
                {
                    booksList = value;
                    OnPropertyChanged();
                }
            }
        }

        private double gridHeight;
        public double GridHeight
        {
            get
            {
                return gridHeight;
            }
            set
            {
                if (value != gridHeight)
                {
                    gridHeight = value;
                    OnPropertyChanged();
                }
            }
        }

        private double gridWidth;
        public double GridWidth
        {
            get
            {
                return gridWidth;
            }
            set
            {
                if (value != gridWidth)
                {
                    gridWidth = value;
                    OnPropertyChanged();
                }
            }
        }

        private Book selectedBook;
        public Book SelectedBook
        {
            get
            {
                return selectedBook;
            }
            set
            {
                if (value != selectedBook)
                {
                    selectedBook = value;
                    OnPropertyChanged();
                }
            }
        }

        private int selectedIdx;
        public int SelectedIdx
        {
            get
            {
                return selectedIdx;
            }
            set
            {
                if (value != selectedIdx)
                {
                    selectedIdx = value;
                    OnPropertyChanged();
                }
            }
        }

        private DelCommand exportCmd;
        public DelCommand ExportCmd
        {
            get
            {
                if (exportCmd == null)
                {
                    exportCmd = new DelCommand(ExportCmdExecuted);
                }
                return exportCmd;
            }
        }

        private void ExportCmdExecuted(object obj)
        {
            var lbx = obj as ListBox;
            if(lbx!=null)
            {

            }
        }

        private DelCommand exportSelectedCmd;        

        public DelCommand ExportSelectedCmd
        {
            get
            {
                if (exportSelectedCmd == null)
                {
                    exportSelectedCmd = new DelCommand(ExportSelectedCmdExecuted);
                }
                return exportSelectedCmd;
            }
        }

        private void ExportSelectedCmdExecuted(object obj)
        {
            var items = ((System.Collections.IList)obj).Cast<Book>()?.ToList();
        }
    }

    public class DelCommand : ICommand
    {
        private Action<object> execute;
        private Predicate<object> canExecute;
        public DelCommand(Action<object> executeValue, Predicate<object> canExecuteValue = null)
        {
            execute = executeValue;
            canExecute = canExecuteValue;
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                CommandManager.RequerySuggested -= value;
            }
        }

        public bool CanExecute(object parameter)
        {
            if (canExecute == null)
            {
                return true;
            }
            return canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            execute(parameter);
        }
    }

    public class Book
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string ISBN { get; set; }
        public string Title { get; set; }
        public ImageSource ImgSource { get; set; }
    }
}

 

posted @ 2025-05-03 20:19  FredGrit  阅读(11)  评论(0)    收藏  举报