如何在WPF DataGrid单元格按数据类型显示图片/文本或绑定图片到Tooltip
WPF DataGrid同一列混合显示文本与图片及动态Tooltip实现
我有一个Dictionary<string, object>类型的数据集合,值的类型为string或System.Drawing.Bitmap,将其绑定到WPF的DataGrid后,Bitmap类型的值会显示为System.Drawing.Bitmap字符串,需要实现两个需求:
- 同一列根据值的类型,自动显示文本或图片
- 单元格的Tooltip根据内容动态显示对应的图片(如果值是Bitmap)
以下是具体实现方案:
步骤1:实现Bitmap到WPF ImageSource的转换器
WPF的Image控件无法直接绑定System.Drawing.Bitmap,需先将其转换为WPF的ImageSource类型,实现IValueConverter接口:
using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Data; using System.Windows.Media.Imaging; namespace WpfApp1 { public class BitmapToImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value is Bitmap bitmap) { var bitmapImage = new BitmapImage(); using (var stream = new System.IO.MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); stream.Position = 0; bitmapImage.BeginInit(); bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.StreamSource = stream; bitmapImage.EndInit(); } return bitmapImage; } return value; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
步骤2:自定义DataGrid列模板,实现混合显示
关闭DataGrid的自动列生成,手动定义列,通过DataTemplate触发器根据值类型切换显示内容,同时配置动态Tooltip:
XAML完整代码
<Window x:Class="WpfApp1.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:src="clr-namespace:WpfApp1" xmlns:sd="clr-namespace:System.Drawing;assembly=System.Drawing" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Window.Resources> <src:MyView x:Key="myView"/> <src:BitmapToImageSourceConverter x:Key="BitmapConverter"/> <src:BitmapVisibilityConverter x:Key="BitmapVisibilityConverter"/> <!-- 文本显示模板 --> <DataTemplate x:Key="TextTemplate"> <TextBlock Text="{Binding Value}"/> </DataTemplate> <!-- 图片显示模板 --> <DataTemplate x:Key="ImageTemplate"> <Image Source="{Binding Value, Converter={StaticResource BitmapConverter}}" Width="50" Height="50"/> </DataTemplate> </Window.Resources> <Grid> <StackPanel> <DataGrid HorizontalAlignment="Stretch" AutoGenerateColumns="False" VerticalAlignment="Stretch" ItemsSource="{Binding Source={StaticResource myView}, Path=Data}"> <!-- 键列 --> <DataGridTextColumn Header="名称" Binding="{Binding Key}" Width="150"/> <!-- 值列:混合显示文本/图片 --> <DataGridTemplateColumn Header="内容"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <ContentControl x:Name="ContentContainer" Content="{Binding Value}" ContentTemplate="{StaticResource TextTemplate}"/> <DataTemplate.Triggers> <DataTrigger Binding="{Binding Value}" Value="{x:Type sd:Bitmap}"> <Setter TargetName="ContentContainer" Property="ContentTemplate" Value="{StaticResource ImageTemplate}"/> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <!-- 动态Tooltip:仅当值为Bitmap时显示图片 --> <DataGridTemplateColumn.CellStyle> <Style TargetType="DataGridCell"> <Setter Property="ToolTip"> <Setter.Value> <ToolTip> <Image Source="{Binding Value, Converter={StaticResource BitmapConverter}}" Visibility="{Binding Value, Converter={StaticResource BitmapVisibilityConverter}}"/> </ToolTip> </Setter.Value> </Setter> </Style> </DataGridTemplateColumn.CellStyle> </DataGridTemplateColumn> </DataGrid> </StackPanel> </Grid> </Window>
补充:Tooltip可见性转换器
如果需要仅当值为Bitmap时显示Tooltip,添加以下转换器:
using System; using System.Drawing; using System.Windows; using System.Windows.Data; namespace WpfApp1 { public class BitmapVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value is Bitmap ? Visibility.Visible : Visibility.Collapsed; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
步骤3:修正ViewModel路径问题
ViewModel中Bitmap的路径需转义或使用@符号避免转义:
public class MyView : INotifyPropertyChanged { public MyView() { Data = new Dictionary<string, object>(); Data["name 1"] = "value 1"; // 使用@避免路径转义,或写成"C:\\test.bmp" Data["name 2"] = new Bitmap(@"C:\test.bmp"); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Data))); } public event PropertyChangedEventHandler PropertyChanged; public IDictionary<string, object> Data { get; set; } }
内容的提问来源于stack exchange,提问作者feature_engineer
相关产品推荐
相关产品推荐

