You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:56:36