WPF MVVM behavior CallMethodAction InvokeCommandAction

1.Install  Microsoft.Xaml.Behaviors.Wpf

 

2.

xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors"

  <behavior:Interaction.Triggers>
      <behavior:EventTrigger EventName="KeyDown">
          <behavior:CallMethodAction MethodName="Window_KeyDown" TargetObject="{Binding}"/>
      </behavior:EventTrigger>
      <behavior:EventTrigger EventName="MouseDown">
          <behavior:InvokeCommandAction Command="{Binding MouseClickCommand}"
                                         CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>
      </behavior:EventTrigger>
  </behavior:Interaction.Triggers>

 

MouseClickCommand = new DelCmd(MouseClickCommandExecuted);

 private void MouseClickCommandExecuted(object obj)
 {
     if(Keyboard.Modifiers!=ModifierKeys.Shift)
     {
         return;
     }
     var win = obj as MainWindow;
     if(win!=null)
     {
         var pt = Mouse.GetPosition(win); 
         MessageBox.Show($"{pt.X},{pt.Y}", "Clicked Location", MessageBoxButton.OK);
     }
 }


 public void Window_KeyDown(object sender, KeyEventArgs e)
 {
     if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.C)
     {
         var msgResult = MessageBox.Show("Are you sure to exit?", "Exit", MessageBoxButton.YesNo,
             MessageBoxImage.Question, MessageBoxResult.Yes);
         if (msgResult == MessageBoxResult.Yes)
         {
             Application.Current.Shutdown();
         }
     }
 }

 

 

 

 

 

 

 

 

 

 

 

 

 

//XAML
<Window x:Class="WpfApp436.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:WpfApp436"
        xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors"
        mc:Ignorable="d" 
        WindowState="Maximized"
        Title="MainWindow" Height="450" Width="800">
    <behavior:Interaction.Triggers>
        <behavior:EventTrigger EventName="KeyDown">
            <behavior:CallMethodAction MethodName="Window_KeyDown" TargetObject="{Binding}"/>
        </behavior:EventTrigger>
        <behavior:EventTrigger EventName="MouseDown">
            <behavior:InvokeCommandAction Command="{Binding MouseClickCommand}"
                                           CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>
        </behavior:EventTrigger>
    </behavior:Interaction.Triggers>
    <Window.DataContext>
        <local:BookVM/>
    </Window.DataContext>
    <Grid>
        <DataGrid x:Name="dg"
                   ItemsSource="{Binding BooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                   SelectionMode="Extended"
                   SelectedItem="{Binding SelectedBook,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                   VirtualizingPanel.IsContainerVirtualizable="True"
                   VirtualizingPanel.IsVirtualizing="True"
                   VirtualizingPanel.VirtualizationMode="Recycling"
                   AutoGenerateColumns="False"
                   CanUserAddRows="False">
            <DataGrid.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Export All"
                              Command="{Binding ExportAllCommand}"
                              CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu},Path=PlacementTarget}"/>
                    <Separator/>
                    <MenuItem Header="Export Selected"
                              Command="{Binding ExportSelectedCommand}"
                              CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu},Path=PlacementTarget}"/>
                </ContextMenu>
            </DataGrid.ContextMenu>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
                <DataGridTemplateColumn Header="Image">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image Source="{Binding ImgUrl}"
                     Width="{Binding ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"
                     Height="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"
                     RenderOptions.BitmapScalingMode="HighQuality"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="ISBN" Binding="{Binding ISBN}"/>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                <DataGridTextColumn Header="Title" Binding="{Binding Title}"/>
                <DataGridTextColumn Header="Topic" Binding="{Binding Topic}"/>              
            </DataGrid.Columns>
        </DataGrid>      
    </Grid>
</Window>


//xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
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.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using Newtonsoft.Json;
using Microsoft.Win32;

namespace WpfApp436
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.Default;
        }
    }

    public class BookVM : INotifyPropertyChanged
    {
        public BookVM()
        {
            InitData();
            InitCommands();
        }

        private void InitCommands()
        {
            ExportAllCommand = new DelCmd(ExportAllCommandExecuted);
            ExportSelectedCommand = new DelCmd(ExportSelectedCommandExecuted);
            MouseClickCommand = new DelCmd(MouseClickCommandExecuted);
        }

        private void MouseClickCommandExecuted(object obj)
        {
            if(Keyboard.Modifiers!=ModifierKeys.Shift)
            {
                return;
            }
            var win = obj as MainWindow;
            if(win!=null)
            {
                var pt = Mouse.GetPosition(win); 
                MessageBox.Show($"{pt.X},{pt.Y}", "Clicked Location", MessageBoxButton.OK);
            }
        } 

        private void ExportSelectedCommandExecuted(object obj)
        {
            var dataGrid = obj as DataGrid;
            if (dataGrid != null)
            {
                var itemsList = dataGrid.SelectedItems.Cast<Book>()?.ToList();
                SaveFileDialog dialog = new SaveFileDialog();
                dialog.Filter = "Json Files|*.json|All Files|*.*";
                dialog.FileName = $"Selected{DateTime.Now.ToString("yyyyMMddHHmmssffff")}_{Guid.NewGuid().ToString("N")}.json";
                if (dialog.ShowDialog() == true)
                {
                    SaveDataToFile(dialog.FileName, itemsList);
                }
            }
        }

        private void ExportAllCommandExecuted(object obj)
        {
            var dataGrid = obj as DataGrid;
            if (dataGrid != null)
            {
                var itemsList = dataGrid.Items.Cast<Book>()?.ToList();
                SaveFileDialog dialog = new SaveFileDialog();
                dialog.Filter = "Json Files|*.json|All Files|*.*";
                dialog.FileName = $"All{DateTime.Now.ToString("yyyyMMddHHmmssffff")}_{Guid.NewGuid().ToString("N")}.json";
                if (dialog.ShowDialog() == true)
                {
                    SaveDataToFile(dialog.FileName, itemsList);
                }
            }
        }

        private void SaveDataToFile(string jsonFileName, List<Book> booksList = null)
        {
            if (booksList == null && !booksList.Any())
            {
                return;
            }

            string jsonStr = JsonConvert.SerializeObject(booksList, Formatting.Indented);
            using (StreamWriter jsonWriter = new StreamWriter(jsonFileName, false, Encoding.UTF8))
            {
                jsonWriter.WriteLine(jsonStr);
            }
            MessageBox.Show($"Saved in {jsonFileName}", "Save Json File", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        public void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.C)
            {
                var msgResult = MessageBox.Show("Are you sure to exit?", "Exit", MessageBoxButton.YesNo,
                    MessageBoxImage.Question, MessageBoxResult.Yes);
                if (msgResult == MessageBoxResult.Yes)
                {
                    Application.Current.Shutdown();
                }
            }
        }

        private void InitData()
        {
            var imgsList = new List<string>(Directory.GetFiles(@"../../Images"));
            int imgsCount = imgsList.Count;
            BooksCollection = new ObservableCollection<Book>();
            for (int i = 0; i < 100000; i++)
            {
                BooksCollection.Add(new Book()
                {
                    Id = i + 1,
                    ISBN = $"ISBN_{i + 1}",
                    Name = $"Name_{i + 1}",
                    Title = $"Title_{i + 1}",
                    Topic = $"Topic_{i + 1}",
                    ImgUrl = imgsList[i % imgsCount]
                });
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propName));
            }
        }

        private ObservableCollection<Book> booksCollection;
        public ObservableCollection<Book> BooksCollection
        {
            get
            {
                return booksCollection;
            }
            set
            {
                if (value != booksCollection)
                {
                    booksCollection = value;
                    OnPropertyChanged(nameof(BooksCollection));
                }
            }
        }

        public DelCmd ExportAllCommand { get; set; }

        public DelCmd ExportSelectedCommand { get; set; }

        public DelCmd MouseClickCommand { get; set; }
    }

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

        private Action<object> execute;
        private Predicate<object> canExecute;

        public DelCmd(Action<object> executeValue, Predicate<object> canExecuteValue)
        {
            execute = executeValue;
            canExecute = canExecuteValue;
        }

        public DelCmd(Action<object> executeValue) : this(executeValue, null)
        {
        }

        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 ISBN { get; set; }

        public string Name { get; set; }

        public string Title { get; set; }

        public string Topic { get; set; }

        public string ImgUrl { get; set; }
    }
}

 

posted @ 2024-10-02 20:53  FredGrit  阅读(18)  评论(1编辑  收藏  举报