繁体   English   中英

如何在 WinForm DataGridView 中为一行着色并隐藏用于设置颜色的列?

[英]How do I color a row in a WinForm DataGridView and Hide the Column being used to set the color?

我有一个正确填充的 datagridview 和 colors 基于通知列的行。

示例网格

我正在使用dataGridView1_CellFormatting事件为行着色。

但是,当我发出隐藏列的命令时,我也会失去颜色。

dataGridView1.Columns["Notify"].Width = 0;

想使用颜色为其他列节省网格中的空间。 将宽度设置为 0,即第二列仍然显示该列的一部分。

当我添加dataGridView1.Columns["Notify"].Visible = false; 我失去了格式:

在此处输入图像描述

 private void PopulateLogs()
        {
            

            var logs = logManager.GetLogRecordsByDay(selectedDay);
            dataGridView1.DataSource = logs;

            dataGridView1.AllowUserToAddRows = false;
            dataGridView1.AllowUserToDeleteRows = false;
            dataGridView1.AllowUserToResizeRows = false;
            dataGridView1.Columns["Id"].Visible = false;
            dataGridView1.Columns["Notify"].Visible = false;
            dataGridView1.Columns["LogDateTime"].DefaultCellStyle.Format = "HH:mm";
            dataGridView1.Columns["LogDateTime"].Width = 20;
            dataGridView1.Columns["LogEntry"].Width = 100;
            dataGridView1.Columns["Analyst"].Width = 15;
            dataGridView1.AllowUserToAddRows = false;
        }
 private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {

            if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Notify")
            {
                if (e.Value != null)
                {
                    string stringValue = (string)e.Value;
                    stringValue = stringValue.ToLower();
                    if ((stringValue.IndexOf("1") > -1))
                    {
                       this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.MistyRose;
                    }

                }
            }
             
        }

这是对我有用的解决方案。 谢谢吉米

private void gvLogs_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{

    if (gvLogs["Notify", e.RowIndex].Value.ToString().Equals("1"))
    {
        this.gvLogs.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.MistyRose;
    }
 }

在现代编程中,人们倾向于将数据(=模型)与数据的显示方式(=视图)分开。

通过这种方式,他们可以更改数据的显示方式,而无需更改 model。 您无需表格即可对 model 进行单元测试,并且无需更改显示即可更改 model。

您正在显示一系列日志项。 特定显示日志项的颜色取决于日志项属性之一的值。

class DislayedLogItem
{
    public int Id {get; set;}
    public string Notify {get; set;}
    public DateTime LogTime {get; set;}
    ...
}

显然有一些关于值的东西让你想要改变行的背景颜色。 您没有告诉我们有什么特别之处,但是您需要一种方法,例如:

// this displayed log item is special if property Notify contains the character '1'
public bool IsSpecial => this.Notify.Contains('1');

分开这一点的好处是,如果您稍后决定显示的日志项是特殊的,因为它的日期早于 2000 年,那么这是唯一需要更改的地方。

同样,您需要一个背景属性:

private Color SpecialColor = Color.MystyRose;

再说一遍:这是为改变而设计的:如果你想要不同的颜色,只需要改变一个地方。

您可能已经使用了 Visual Studio 设计器来添加列。 每列显示您要显示的属性之一。 构造函数中的概率:

InitializeComponent();

columnId.DataPropertyName = nameof(DisplayedLogItem.Id);
columnLogTime.DataPropertyName = nameof(DisplayedLogItem.Log)
columnAnalyst.DataPropertyName = nameof(DisplayedLogItem.Analyst);

没有要显示通知的列。 无论如何,您不想显示此列。

但是你想要的是,每当要添加“特殊”行时,你想给它一个特殊的背景色。

为此,您需要事件DataGridView.RowPrePaint

private void OnRowPrepaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
    DataGridViewRow row = e.Row;
    DisplayedLogItem logItem = (DisplayedLogItem)row.DataBoundItem;
    if (logItem.IsSpecial)
       row.BackColor = this.SpecialColor;
}

也许你可以在添加一行时执行此操作:DataGridView.RowsAdded 事件。

显示所有 DisplayedLogItem

您需要一个过程来获取需要显示的日志项目。 出问题的scope:

public IEnumerable<DisplayedLogItem> FetchLogItemsToDisplay()
{
    ...
}

以下足以显示日志

this.dataGridView1.DataSource = this.FetchLogItemsToDisplay().ToList();

这足以显示数据。 但是,如果您想在添加/删除/更新行时收到通知,则需要一个 BindingList:

private BindingList<DisplayedLogItem> DisplayedLogItems
{
    get => (BindingList<DisplayedLogItem>)this.dataGridView1.DataSource;
    set => this.dataGridView.DataSource = value;
}

例如在加载后显示:

void Form_Loaded(object sender, ...
{
    this.DisplayedLogItems = new BindingList<DisplayedLogItem>(
        this.FetchLogItemsToDisplay().ToList());
}

现在,每当操作员添加/删除/编辑一行时,都会在 DisplayedLogItems 中更新。 因此,如果操作员指示他已完成数据编辑,例如通过单击 Ok 按钮:

void ButtonOk_Clicked(object sender, ...)
{
    ICollection<DisplayedLogItem> editedLogItems = this.DisplayedLogItems;
    // find out which items are added / removed / changed and process them:
    this.ProcessEditedLogItems(editedLogItems);
}

如果您需要处理选定的行,以下内容可能很有用:

DisplayedLogItem CurrentLogItem => (DisplayedLogItem)this.dataGridView1.SelectedRow;

IEnumerable<DisplayedLogItem> SelectedLogItems => this.dataGridView1.SelectedRows
    .Cast<DataGridViewRow>()
    .Select(row => row.DataBoundItem)
    .Cast<DisplayedLogItem>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM