如何根据数据类型设置WPF DataGrid单元格样式以显示Bitmap
解决WPF DataGrid根据单元格数据类型切换显示控件的问题
核心问题分析
你遇到的问题根源在于:AutoGenerateColumns默认会为所有列生成DataGridTextColumn,这类列会将所有数据转为字符串显示。即使修改CellStyle,如果没有针对不同数据类型指定对应的显示模板,Bitmap等非字符串类型依然无法正确渲染。
解决方案步骤
我们可以通过为DataGridCell设置ContentTemplate,结合数据类型匹配的DataTemplate,实现不同数据类型自动切换显示控件。同时需要一个转换器将System.Drawing.Bitmap转为WPF的ImageSource。
1. 编写Bitmap转ImageSource转换器
在代码后台添加以下转换器类,用于将WinForms的Bitmap转换为WPF可识别的ImageSource:
using System; using System.Drawing; using System.Globalization; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Data; using System.Windows.Media.Imaging; namespace YourNamespace { public class BitmapToImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is Bitmap bitmap) { var hBitmap = bitmap.GetHbitmap(); try { return Imaging.CreateBitmapSourceFromHBitmap( hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } finally { DeleteObject(hBitmap); } } return DependencyProperty.UnsetValue; } [DllImport("gdi32.dll")] private static extern bool DeleteObject(IntPtr hObject); public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
2. 修改DataGrid的XAML代码
更新DataGrid的Style,重点修改CellStyle,为单元格内容添加类型匹配的DataTemplate:
<Window.Resources> <local:BitmapToImageSourceConverter x:Key="BitmapToImageSourceConverter"/> </Window.Resources> <DataGrid> <DataGrid.Style> <Style TargetType="DataGrid"> <Setter Property="AlternationCount" Value="2"/> <Setter Property="AutoGenerateColumns" Value="True"/> <Setter Property="CellStyle"> <Setter.Value> <Style TargetType="DataGridCell"> <!-- 设置单元格内容模板,根据数据类型切换控件 --> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <ContentControl Content="{Binding}"> <ContentControl.Resources> <!-- Bitmap类型显示Image控件 --> <DataTemplate DataType="{x:Type Drawing:Bitmap}"> <Image Source="{Binding Converter={StaticResource BitmapToImageSourceConverter}}" Stretch="Uniform" MaxHeight="50" MaxWidth="100"/> </DataTemplate> <!-- 字符串类型显示TextBlock --> <DataTemplate DataType="{x:Type sys:String}"> <TextBlock Text="{Binding}" VerticalAlignment="Center"/> </DataTemplate> <!-- 可扩展其他数据类型的模板,比如数字、日期等 --> </ContentControl.Resources> </ContentControl> </DataTemplate> </Setter.Value> </Setter> <Setter Property="Background" Value="Transparent"/> <Style.Triggers> <Trigger Property="ItemsControl.AlternationIndex" Value="1"> <Setter Property="Background" Value="#e0e0e0"/> </Trigger> </Style.Triggers> </Style> </Setter.Value> </Setter> <Setter Property="HeadersVisibility" Value="Column"/> <Setter Property="IsReadOnly" Value="True"/> <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=DataContext.Data}"/> </Style> </DataGrid.Style> </DataGrid>
注意:需要在XAML根节点添加以下命名空间引用:
xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:Drawing="clr-namespace:System.Drawing;assembly=System.Drawing" xmlns:local="clr-namespace:YourNamespace"
关键说明
- 不再重写
DataGridCell的Template,而是通过ContentTemplate控制内容渲染,避免破坏默认的单元格布局逻辑。 - 使用
ContentControl加载内容,并通过资源中的DataTemplate自动匹配数据类型,无需手动判断。 - 转换器必须正确释放GDI资源(调用
DeleteObject),避免内存泄漏。
内容的提问来源于stack exchange,提问作者Smorkster
相关产品推荐
相关产品推荐

