WPF datagrid show ImageBrush via DataGridTemplateColumn

FredGrit發表於2024-10-25
<DataGridTemplateColumn Header="Image">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Border Width="{Binding ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}},
                Converter={StaticResource lengthConverter}}"
                    Height="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}},
                Converter={StaticResource lengthConverter}}">
                <Border.Background>
                    <ImageBrush ImageSource="{Binding ImgSource}" Stretch="Uniform"/>                                   
                </Border.Background>
                <TextBlock Text="{Binding Id}" 
                           FontSize="100" 
                           Foreground="Red"                                           
                           Width="250"
                           Height="150" 
                           HorizontalAlignment="Right"
                           VerticalAlignment="Bottom"
                            />
            </Border>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>



private ImageSource GetImgSourceViaImgUrl(string imgUrlValue)
{
    try
    {
        if (!File.Exists(imgUrlValue))
        {
            return null;
        }
        BitmapImage bmi = new BitmapImage();
        bmi.BeginInit();
        bmi.UriSource = new Uri(imgUrlValue, UriKind.RelativeOrAbsolute);
        bmi.EndInit();
        if (bmi.CanFreeze)
        {
            bmi.Freeze();
        }
        return bmi;
    }
    catch (Exception ex)
    {
        MessageBox.Show($"{imgUrlValue}\n{ ex.Message}");
        return null;
    }           
}

//xaml
<Window x:Class="WpfApp22.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:behavior="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:local="clr-namespace:WpfApp22"
        mc:Ignorable="d"
        WindowState="Maximized"
        Title="{Binding SelectedItem.Id,ElementName=dg}" 
        Height="450" Width="800">
    <behavior:Interaction.Triggers>
        <behavior:EventTrigger EventName="KeyDown">
            <behavior:CallMethodAction MethodName="Window_KeyDown" TargetObject="{Binding}"/>
        </behavior:EventTrigger>
    </behavior:Interaction.Triggers>
    <Window.Resources>
        <local:LengthConverter x:Key="lengthConverter"/>
    </Window.Resources>
    <!--<Window.DataContext>
        <local:BookVM/>
    </Window.DataContext>-->
    <Grid>
        <DataGrid x:Name="dg" 
                  ItemsSource="{Binding BooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                  SelectedItem="{Binding SelectedBk,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                  AutoGenerateColumns="False"
                  CanUserAddRows="False"
                  VirtualizingPanel.IsVirtualizing="True"
                  VirtualizingPanel.IsContainerVirtualizable="True"
                  VirtualizingPanel.VirtualizationMode="Recycling"
                  VirtualizingPanel.CacheLength="1"
                  VirtualizingPanel.CacheLengthUnit="Item" >
            <DataGrid.Columns>
                <!--<DataGridTextColumn Header="Id" Binding="{Binding Id}"/>-->
                <!--<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                <DataGridTextColumn Header="ISBN" Binding="{Binding ISBN}"/>-->
                <!--<DataGridTemplateColumn Header="ImgUrl">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image Source="{Binding ImgUrl}" Width="200" Height="500"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>-->
                <DataGridTemplateColumn Header="Image">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Border Width="{Binding ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}},
                                Converter={StaticResource lengthConverter}}"
                                    Height="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}},
                                Converter={StaticResource lengthConverter}}">
                                <Border.Background>
                                    <ImageBrush ImageSource="{Binding ImgSource}" Stretch="Uniform"/>                                   
                                </Border.Background>
                                <TextBlock Text="{Binding Id}" 
                                           FontSize="100" 
                                           Foreground="Red"                                           
                                           Width="250"
                                           Height="150" 
                                           HorizontalAlignment="Right"
                                           VerticalAlignment="Bottom"
                                            />
                            </Border>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>



//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 System.Globalization;
using System.Windows.Threading;

namespace WpfApp22
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = new BookVM(dg);
            this.DataContext = vm;
        }

        private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            MessageBox.Show(e.Exception.Message);
        }
    }

    public class BookVM:INotifyPropertyChanged
    {
        private DataGrid dg { get; set; }
        public BookVM(DataGrid dgValue)
        {
            dg = dgValue;
            InitData();
            InitSystemTimers();
        }

        private void InitSystemTimers()
        {
            System.Timers.Timer tmr = new System.Timers.Timer();
            tmr.Elapsed += Tmr_Elapsed;
            tmr.Interval = 100;
            tmr.Start();
        }

        private void Tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if(isPaused)
            {
                return;
            }
            if(++SelectedIdx>=BooksCollection.Count)
            {
               SelectedIdx = 0;
            }
        }

        private void InitData()
        {
            imgsList = new List<string>(Directory.GetFiles(@"../../Images"));
            if(imgsList!=null && imgsList.Any())
            {
                imgsCount= imgsList.Count;
                BooksCollection = new ObservableCollection<Book>();
                for(int i=0;i<10000;i++)
                {
                    BooksCollection.Add(new Book()
                    {
                        Id = i + 1,
                        Name = $"Name_{i + 1}",
                        ISBN = $"ISBN_{Guid.NewGuid().ToString("N")}",
                        ImgUrl = $"{imgsList[i % imgsCount]}",
                        ImgSource = GetImgSourceViaImgUrl(imgsList[i % imgsCount]),
                    });
                }
            }
        }

        private ImageSource GetImgSourceViaImgUrl(string imgUrlValue)
        {
            try
            {
                if (!File.Exists(imgUrlValue))
                {
                    return null;
                }
                BitmapImage bmi = new BitmapImage();
                bmi.BeginInit();
                bmi.UriSource = new Uri(imgUrlValue, UriKind.RelativeOrAbsolute);
                bmi.EndInit();
                if (bmi.CanFreeze)
                {
                    bmi.Freeze();
                }
                return bmi;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"{imgUrlValue}\n{ ex.Message}");
                return null;
            }           
        }


        public void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Space)
            {
                isPaused = !isPaused;
            }           
        }

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

        private bool isPaused = false;

        private Book selectedBk;
        public Book SelectedBk
        {
            get
            {
                return selectedBk;
            }
            set
            {
                if(value!= selectedBk)
                {
                    selectedBk = value;
                    OnPropertyChanged(nameof(SelectedBk));
                    System.Diagnostics.Debug.WriteLine(SelectedBk.ImgUrl);
                    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        if (dg != null)
                        {
                            dg.ScrollIntoView(SelectedBk);
                        }
                    }));
                }
            }
        }

        private int selectedIdx;
        public int SelectedIdx
        {
            get
            {
                return selectedIdx;
            }
            set
            {
                if(value!=selectedIdx)
                { 
                    selectedIdx = value;
                    OnPropertyChanged(nameof(SelectedIdx));
                    if(dg!=null)
                    {  
                        SelectedBk=dg.Items[selectedIdx] as Book;
                        if(SelectedBk!=null)
                        {
                            dg.ScrollIntoView(SelectedBk);
                        }
                    }
                }
            }
        }

        private List<string> imgsList { get; set; }

        private int imgsCount { get; set; }

        private ObservableCollection<Book> booksCollection;
        public ObservableCollection<Book> BooksCollection
        {
            get
            {
                return booksCollection;
            }

            set
            {
                if(value != booksCollection)
                {
                    booksCollection = value;
                    OnPropertyChanged(nameof(BooksCollection));
                }
            }
        }
    }

    public class LengthConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            double d = 0;
            if(double.TryParse(value?.ToString(), out d))
            {
                return d;
            }
            return d;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class Book
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string ISBN { get; set; }

        public string ImgUrl { get; set; }

        public ImageSource ImgSource { get; set; }
    }
}

相關文章