[英]Cell selection hides behind image DataGridViewImageCell
我正在使用 Winform DataGridView 來顯示圖像。 但是當圖像填滿單元格時,我看不到藍色選擇或數量非常少。 請參見:
When an cell is selected, I expect make cell whole transparent blue, not just sides or sides which isn't occupied by image. 像:
目前我嘗試在繪畫事件中自己塗上藍色,但更新太頻繁導致軟件掛起。
我還修改了圖像,使其在選擇更改事件中看起來偏藍,但它再次減慢了軟件速度。
有解決辦法嗎? 任何解決方法或什么? 在不影響性能的情況下?
編輯:這是關於我如何在 datagridview 上顯示圖像的源代碼:
int colms = 4; // total no. of columns in our datagridview
//this create 4 image columns in datagridview
for (int c = 0; c < colms; c++)
{
var imgColm = new DataGridViewImageColumn();
imgColm.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
imgColm.ImageLayout = DataGridViewImageCellLayout.Zoom;
grid.Columns.Add(imgColm);
}
int colm = 0;
int row = 0;
//this get all images and display on datagridview
foreach (var img in Directory.GetFiles(@"C:\Users\Administrator\Desktop\images"))
{
if (colm >= colms)
{
row++;
colm = 0;
grid.Rows.Add();
}
((DataGridViewImageCell)grid.Rows[row].Cells[colm]).Value = Thumb.GetThumbnail(img, ThumbSize.LowRes);
colm++;
}
目前單元格繪畫我只使用一種解決方法,即在選定的單元格上繪制邊框。 但是當數據很大並且其次也利用未選擇的單元格時它很慢。
這里有兩個例子來測試你自己關於所選單元格的性能和填充樣式。 由於您的代碼片段沒有顯示在什么上下文中調用代碼,尤其是創建圖像列部分,並且為了避免重復不必要的例程,請使用網格設計器添加 4 列DataGridViewImageColumn
類型並從那里設置自動大小和布局屬性.
正常模式
在 Form 的 ctor 中,使用Reflection
啟用網格的DoubleBuffered
屬性以減少閃爍。 emptyImage
bitmap 是空單元格的 null 值。
public partial class SomeForm : Form
{
private Bitmap emptyImage;
public SomeForm()
{
dgv.GetType()
.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(dgv, true);
emptyImage = new Bitmap(1, 1);
foreach (var col in dgv.Columns.OfType<DataGridViewImageColumn>())
col.DefaultCellStyle.NullValue = emptyImage;
}
覆蓋OnLoad
方法以填充網格或為此調用方法。
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
var imgFolder = @"Your-Image-Folder-Path";
LoadImages(imgFolder);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
emptyImage.Dispose();
}
private void LoadImages(string path)
{
string[] allFiles = Directory.GetFiles(path);
for (int i = 0; i < allFiles.Length; i += 4)
{
var files = allFiles.Skip(i).Take(4);
dgv.Rows.Add(
files.Select(f =>
{
using (var img = Image.FromFile(f, true))
return Thumb.GetThumbnail(img, ThumbSize.LowRes);
}).ToArray());
}
}
請注意,您的Thumb.GetThumbnail
方法返回一個新圖像,因此您需要處理原始圖像。
實施CellPainting
事件以繪制除DataGridViewPaintParts.SelectionBackground
之外的所有內容,並使用半透明顏色填充選定的單元格。
private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
e.Paint(e.ClipBounds, e.PaintParts & ~DataGridViewPaintParts.SelectionBackground);
if (e.RowIndex >= 0 &&
e.Value != null && e.Value != emptyImage &&
(e.State & DataGridViewElementStates.Selected) > 0)
{
using (var br = new SolidBrush(Color.FromArgb(100, SystemColors.Highlight)))
e.Graphics.FillRectangle(br, e.CellBounds);
}
e.Handled = true;
}
}
虛擬模式
你需要在這里有數據存儲來緩存你需要顯示的圖像。 可見行的每個單元格的圖像。 為此,創建了Cache
class 來管理相關功能,包括:
SetMaxRows
方法。Dictionary<int, Image>
中加載、創建和緩存當前可見行圖像,其中鍵是單元格編號。CellValueNeeded
事件時傳遞請求的圖像。public partial class SomeForm : Form
{
private readonly Cache cache;
public SomeForm()
{
dgv.GetType()
.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(dgv, true);
dgv.VirtualMode = true;
var imgFolder = @"Your-Image-Folder-Path";
cache = new Cache(imgFolder, dgv.ColumnCount);
dgv.RowCount = cache.GetRowCount();
SetMaxRows();
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
cache.Dispose();
}
private void dgv_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) =>
e.Value = cache.GetImage(e.RowIndex, e.ColumnIndex);
private void dgv_Resize(object sender, EventArgs e) => SetMaxRows();
// Change dgv.RowTemplate.Height as needed...
private void SetMaxRows() =>
cache.MaxRows = (int)Math
.Ceiling((double)dgv.ClientRectangle.Height / dgv.RowTemplate.Height);
private class Cache : IDisposable
{
private readonly Dictionary<int, Image> dict;
private readonly Bitmap nullImage;
private int currentRowIndex = -1;
private Cache()
{
dict = new Dictionary<int, Image>();
nullImage = new Bitmap(1, 1);
}
public Cache(string path, int columnCount) : this()
{
ImageFolder = path;
ColumnCount = columnCount;
}
public string ImageFolder { get; set; }
public int ColumnCount { get; set; }
public int MaxRows { get; set; }
public Bitmap NullImage => nullImage;
public Image GetImage(int rowIndex, int columnIndex)
{
var ri = rowIndex - (rowIndex % MaxRows);
if (ri != currentRowIndex)
{
foreach (var img in dict.Values) img?.Dispose();
currentRowIndex = ri;
dict.Clear();
}
var i = (rowIndex * ColumnCount) + columnIndex;
Image res = nullImage;
if (!dict.ContainsKey(i))
{
var file = Directory.EnumerateFiles(ImageFolder)
.Skip(i).FirstOrDefault();
if (file != null)
{
using (var img = Image.FromFile(file, true))
dict[i] = res = Thumb.GetThumbnail(img, ThumbSize.LowRes);
}
}
else
{
res = dict[i];
}
return res;
}
public int GetRowCount()
{
var count = Directory.EnumerateFiles(ImageFolder).Count();
return (int)Math.Ceiling((double)count / ColumnCount);
}
public void Dispose()
{
foreach (var img in dict.Values) img?.Dispose();
nullImage.Dispose();
}
}
最后, CellPainting
事件幾乎保持不變,只是您從cache
實例中獲取了 null 圖像。
private void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
e.Paint(e.ClipBounds, e.PaintParts & ~DataGridViewPaintParts.SelectionBackground);
if (e.RowIndex >= 0 &&
e.Value != null && e.Value != cache.NullImage &&
(e.State & DataGridViewElementStates.Selected) > 0)
{
using (var br = new SolidBrush(Color.FromArgb(100, SystemColors.Highlight)))
e.Graphics.FillRectangle(br, e.CellBounds);
}
e.Handled = true;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.