WPF ListBox DataTemplate context menu save as pictures, inert the snapshots into pdf

Install-Package iTextSharp;

 

 

 

//xaml
<Window x:Class="WpfApp82.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"
        WindowState="Maximized"
        xmlns:local="clr-namespace:WpfApp82"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="ColumnDefinition">
            <Setter Property="Width" Value="Auto"/>
        </Style>
        <DataTemplate x:Key="BookTemplate">
            <Grid Width="{Binding DataContext.GridWidth,RelativeSource={RelativeSource AncestorType=Window}}"
          Height="{Binding DataContext.GridHeight,RelativeSource={RelativeSource AncestorType=Window}}">
                <Grid.Background>
                    <ImageBrush ImageSource="{Binding ImgSource}"/>
                </Grid.Background>
                <Grid.Resources>
                    <Style TargetType="TextBlock">
                        <Setter Property="FontSize" Value="30"/>
                        <Setter Property="HorizontalAlignment" Value="Center"/>
                        <Setter Property="VerticalAlignment" Value="Center"/>
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="FontSize" Value="50"/>
                                <Setter Property="Foreground" Value="Red"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Grid.Resources>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <TextBlock Text="{Binding Id}" Grid.Column="0"/>
                <TextBlock Text="{Binding Name}" Grid.Column="1"/>
                <TextBlock Text="{Binding Author}" Grid.Column="2"/>
                <TextBlock Text="{Binding Comment}" Grid.Column="3"/>
                <TextBlock Text="{Binding Content}" Grid.Column="4"/>
                <TextBlock Text="{Binding Title}" Grid.Column="5"/>
                <TextBlock Text="{Binding Topic}" Grid.Column="6"/>
                <TextBlock Text="{Binding Description}" Grid.Column="7"/>
                <TextBlock Text="{Binding ISBN}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="8"/>
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding BooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                 ItemTemplate="{StaticResource BookTemplate}"
                 VirtualizingPanel.IsVirtualizing="True"
                 VirtualizingPanel.VirtualizationMode="Recycling"
                 ScrollViewer.IsDeferredScrollingEnabled="True">          
            <ListBox.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Export As Pictures"
                              Command="{Binding ExportAsPicturesCommand}"
                              CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu},Path=PlacementTarget}"/>
                    <MenuItem Header="Save Pictures In PDF"
                              IsEnabled="{Binding IsSavePicturesInPDFEnabled,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                              Command="{Binding SavePicturesInPDFCommand}"/>
                </ContextMenu>
            </ListBox.ContextMenu>
        </ListBox>
    </Grid>
</Window>



//cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
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 Path = System.IO.Path;
using iTextSharp.text;
using iTextSharp.text.pdf;
using Image = iTextSharp.text.Image;


namespace WpfApp82
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        MainVM vm;
        public MainWindow()
        {
            InitializeComponent();
            vm=new MainVM();
            this.DataContext=vm;
            this.SizeChanged+=MainWindow_SizeChanged;
        }

        private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var fe = this.Content as FrameworkElement;
            if (fe != null)
            {
                vm.GridWidth= fe.ActualWidth;
                vm.GridHeight= fe.ActualHeight/2;
            }
        }
    }

    public class MainVM : INotifyPropertyChanged
    {
        string pictureDir = "";
        public MainVM()
        {
            InitData();
            InitCommands();
        }

        private void InitCommands()
        {
            ExportAsPicturesCommand=new DelCommand(async(obj)=> await ExportAsPicturesCommandExecuted(obj));
            SavePicturesInPDFCommand=new DelCommand(SavePicturesInPDFCommandExecuted);
        }

        private void SavePicturesInPDFCommandExecuted(object? obj)
        {
            if(!Directory.Exists(pictureDir))
            {
                return;
            }
            var imgs = Directory.GetFiles(pictureDir).OrderBy(x => new FileInfo(x).CreationTime).ToList();
            if(imgs==null || !imgs.Any())
            {
                return;
            }

            string pdfFile = Path.Combine(pictureDir, $"{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.pdf");

            using(FileStream fileStream=new FileStream(pdfFile,FileMode.Create))
            {
                using (Document doc = new Document(PageSize.A1))
                {
                    using(PdfWriter pdfWriter=PdfWriter.GetInstance(doc,fileStream))
                    {
                        doc.Open();
                        foreach (var imgFile in imgs)
                        {
                            Image img = Image.GetInstance(imgFile);
                            img.ScaleToFit(doc.PageSize.Width-doc.LeftMargin-doc.RightMargin,
                                doc.PageSize.Height-doc.TopMargin-doc.BottomMargin);
                            img.Alignment=Element.ALIGN_CENTER;
                            doc.Add(img);
                        }
                        doc.Close();
                    }                    
                }
            }
            IsSavePicturesInPDFEnabled=false;
            MessageBox.Show($"Save as {pdfFile}");
        }

        private async Task ExportAsPicturesCommandExecuted(object? obj)
        {
            await SaveListBoxItemsAsJPGS(obj);
            IsSavePicturesInPDFEnabled=true;
        }

        private async Task<bool> SaveListBoxItemsAsJPGS(object? obj)
        {
            var lbx = obj as ListBox;
            if (lbx==null)
            {
                return false;
            }

            pictureDir = $"LBXItem_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}";
            if (!Directory.Exists(pictureDir))
            {
                Directory.CreateDirectory(pictureDir);
            }

            var items = lbx.Items;
            int idx = 0;
            foreach (var item in items)
            {
                lbx.ScrollIntoView(item);
                lbx.UpdateLayout();
                var lbxItem = lbx.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;
                if (lbxItem==null)
                {
                    return false;
                }

                string lbxItemJpgFile = $"{Path.Combine(pictureDir, $"LBXItem_{++idx}.jpg")}";
                await SaveListBoxItemAsPicture(lbxItem, lbxItemJpgFile);
            }

            MessageBox.Show($"Saved in {pictureDir}");
            return true;
        }

        private async Task SaveListBoxItemAsPicture(ListBoxItem lbxItem, string jpgFile)
        {
            await Task.Run(async () =>
            {
                var dpi = VisualTreeHelper.GetDpi(lbxItem);
                Application.Current?.Dispatcher.InvokeAsync(() =>
                {
                    RenderTargetBitmap rtb = new RenderTargetBitmap((int)(GridWidth*dpi.DpiScaleX),
                    (int)(GridHeight*dpi.DpiScaleY),
                    dpi.PixelsPerInchX,
                    dpi.PixelsPerInchY,
                    PixelFormats.Pbgra32);
                    rtb.Render(lbxItem);
                    using (FileStream fileStream = new FileStream(jpgFile, FileMode.Create))
                    {
                        JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                        encoder.Frames.Add(BitmapFrame.Create(rtb));
                        encoder.Save(fileStream);
                        Debug.WriteLine(jpgFile);
                    }
                });                
            });            
        }

        private T GetVisualChild<T>(DependencyObject parent) where T : DependencyObject
        {
            if(parent==null)
            {
                return null;
            }
            for(int i=0;i<VisualTreeHelper.GetChildrenCount(parent);i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                if(child != null && child is T result)
                {
                    return result;
                }

                var descendantResult = GetVisualChild<T>(child);
                if(descendantResult!=null)
                {
                    return descendantResult;
                }
            }
            return null;
        }

        private async Task InitData()
        {
            var dir = @"../../../Images";
            if (Directory.Exists(dir))
            {
                var imgs = Directory.GetFiles(dir);
                if (imgs==null || !imgs.Any())
                {
                    return;
                }

                int imgsCount = imgs.Count();

                await Task.Run(() =>
                {
                    List<Book> booksList = new List<Book>();
                    BooksCollection=new ObservableCollection<Book>();
                    for (int i = 1; i<1001; i++)
                    {
                        booksList.Add(new Book()
                        {
                            Id=i,
                            Name=$"Name_{i}",
                            Author=$"Author_{i}",
                            Comment=$"Comment_{i}",
                            Content=$"Content_{i}",
                            Description=$"Description_{i}",
                            Title=$"Title_{i}",
                            Topic=$"Topic_{i}",
                            ISBN=$"ISBN_{i}_{Guid.NewGuid().ToString("N")}",
                            ImgSource=GetImgSourceViaUrl(imgs[i%imgsCount])
                        });

                        if (i<=200 && i%100==0)
                        {
                            PopulateBooksCollection(booksList);
                        }
                        else
                        {
                            PopulateBooksCollection(booksList);
                        }
                    }
                });
                MessageBox.Show("Initialization finished!");
            }
        }

        private void PopulateBooksCollection(List<Book> booksList)
        {
            var tempList = booksList.ToList();
            booksList.Clear();
            Application.Current?.Dispatcher.InvokeAsync(() =>
            {
                foreach (var item in tempList)
                {
                    BooksCollection.Add(item);
                }
            });
        }

        private ImageSource GetImgSourceViaUrl(string imgUrl)
        {
            BitmapImage bmi = new BitmapImage();
            if (!File.Exists(imgUrl))
            {
                return bmi;
            }

            bmi.BeginInit();
            bmi.UriSource=new Uri(imgUrl, UriKind.RelativeOrAbsolute);
            bmi.EndInit();
            if (bmi.CanFreeze)
            {
                bmi.Freeze();
            }
            return bmi;
        }

        #region Properties

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

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

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

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

        private bool isSavePicturesInPDFEnabled = false;
        public bool IsSavePicturesInPDFEnabled
        {
            get
            {
                return isSavePicturesInPDFEnabled;
            }
            set
            {
                if(value!=isSavePicturesInPDFEnabled)
                {
                    isSavePicturesInPDFEnabled = value;
                    OnPropertyChanged();
                }
            }
        }

        #endregion

        public ICommand ExportAsPicturesCommand { get; set; }

        public ICommand SavePicturesInPDFCommand { get; set; }
    }


    public class Book
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Author { get; set; }
        public string Description { get; set; }
        public string Title { get; set; }
        public string Topic { get; set; }
        public string Comment { get; set; }
        public string Content { get; set; }
        public string ISBN { get; set; }
        public ImageSource ImgSource { get; set; }
    }


    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)
        {
            return canExecute==null ? true : canExecute(parameter);
        }

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

 

 

 

image

 

 

 

 

 

 

 

image

 

posted @ 2025-09-12 11:35  FredGrit  阅读(3)  评论(0)    收藏  举报