color whole row instead of single cell

笑着哭i 提交于 2019-12-01 11:30:51

问题


Ive been trying to change the background color of a row in the Compact Framework DataGrid and have found little success since the DataGrid on .NET CF is limited compared to its Windows Forms counterpart. My only bit of success in achieving my goal is I have now been able to change the background color of a single cell depending on its values. I couldnt manipulate the code I got from Googling since I am not that good in C#. However, this is the code that I have:

namespace GridColor
{
    public delegate void CheckCellEventHandler(object sender, DataGridEnableEventArgs e);

    public class DataGridEnableEventArgs : EventArgs
    {
        private int _column;
        private int _row;
        private bool _meetsCriteria;

        public DataGridEnableEventArgs(int row, int col, bool val)
        {
            _row = row;
            _column = col;
            _meetsCriteria = val;
        }

        public int Column
        {
            get { return _column; }
            set { _column = value; }
        }

        public int Row
        {
            get { return _row; }
            set { _row = value; }
        }

        public bool MeetsCriteria
        {
            get { return _meetsCriteria; }
            set { _meetsCriteria = value; }
        }

    }

    public partial class ColumnStyle : DataGridTextBoxColumn
    {
        //public event CheckCellEventHandler CheckCellEquals;
        public event CheckCellEventHandler CheckCellContains;

        private int _col;

        public ColumnStyle(int column)
        {
            _col = column;
        }

        protected override void Paint(Graphics g, Rectangle Bounds, CurrencyManager Source, int RowNum, Brush BackBrush, Brush ForeBrush, bool AlignToRight)
        {
            bool enabled = true;

            if (CheckCellContains != null)
            {
                DataGridEnableEventArgs e = new DataGridEnableEventArgs(RowNum, _col, enabled);
                CheckCellContains(this, e);
                if (e.MeetsCriteria)
                    //g.DrawRectangle(new Pen(Color.Red, 2), Bounds.Y + 1, Bounds.Width - 2, Bounds.Height - 2);
                    BackBrush = new SolidBrush(Color.PaleGreen);
            }

            base.Paint(g, Bounds, Source, RowNum, BackBrush, ForeBrush, AlignToRight);

        }
    }

}

Now for my form, I have this:

namespace GridColor
    {
        public partial class Form1 : Form
        {
            DataSet ds;
            SqlDataAdapter da;
            private List<string> compareValues = new List<string>();

            public Form1()
            {
                InitializeComponent();
                try
                {
                    addGridStyle(ref dataGrid1);
                    compareValues.Add("OK");
                    compareValues.Add("Filling");
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: " + ex.ToString());
                }
            }

            private void addGridStyle(ref DataGrid dg)
            {
                DataGridTableStyle dtStyle = new DataGridTableStyle();
                dtStyle.MappingName = "Test";

                string connString = "Data Source=192.168.2.16,1433;Initial Catalog=TestDB;User ID=sa;Password=ABC12abc;";
                SqlConnection conn = new SqlConnection(connString);
                conn.Open();
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = conn;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "SELECT * FROM Test";
                ds = new DataSet();
                da = new SqlDataAdapter(cmd);
                da.Fill(ds, "Test");

                for (int i = 0; i < ds.Tables["Test"].Columns.Count; i++)
                {
                    ColumnStyle myStyle = new ColumnStyle(i);
                    myStyle.MappingName = ds.Tables["Test"].Columns[i].ToString();
                    if (i == 1)
                    {
                        if (ds.Tables["Test"].Columns[i].DataType == System.Type.GetType("System.String"))
                            myStyle.CheckCellContains += new CheckCellEventHandler(myStyle_CheckCellContains);
                    }
                    dtStyle.GridColumnStyles.Add(myStyle);
                }

                dg.TableStyles.Add(dtStyle);
            }

            public void myStyle_CheckCellContains(object sender, DataGridEnableEventArgs e)
            {
                try
                {
                    if (compareValues.Contains((string)dataGrid1[e.Row, e.Column]))
                        e.MeetsCriteria = true;
                    else
                        e.MeetsCriteria = false;
                }
                catch (Exception ex)
                {
                    e.MeetsCriteria = false;
                }
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                dataGrid1.DataSource = ds.Tables["Test"];
            }
        }
    }

In what part of my code should I change so that If a cell meets the criteria, its whole row will be colored instead of only it's own cell?


回答1:


Alright I went back and found my code from years ago where I did this on the desktop, before the more advanced DataGridView came out, etc.

First of all there is this tutorial from Microsoft Customizing the Windows Forms DataGrid, which explains how to highlight an entire row.

I looked at my code and I had to add a custom column style for each column, fire an event to the main form which I handled, and then determined the proper color for that record. Then, I set the args.Color property and the DataGridColumn would draw the correct color. So yes, you have to actually have each column be your custom formatable class, then your application logic can handle the event, get the record data and determine the color

** Update: here's a simple example **

public partial class Form1 : Form
{
    FormattableTextBoxColumn firstNameColumn = new FormattableTextBoxColumn();
    FormattableTextBoxColumn lastNameColumn = new FormattableTextBoxColumn();

    public Form1()
    {
        InitializeComponent();

        // add first name col
        firstNameColumn.MappingName = "FirstName";
        dataGridTableStyle1.GridColumnStyles.Add(firstNameColumn);
        firstNameColumn.SetCellFormat += new FormatCellEventHandler(ColumnSetCellFormat);

        // add last name col
        lastNameColumn.MappingName = "LastName";
        lastNameColumn.SetCellFormat += new FormatCellEventHandler(ColumnSetCellFormat);
        dataGridTableStyle1.GridColumnStyles.Add(lastNameColumn);

        // This just sets up a dummy data source, since I don't have a database in this example
        List<PersonTest> peopleList = new List<PersonTest>();
        peopleList.Add(new PersonTest
        {
            FirstName = "Alan",
            LastName = "QQQQQ",
            HighlightPerson = true
        });
        peopleList.Add(new PersonTest
        {
            FirstName = "John",
            LastName = "Smith",
            HighlightPerson = false
        });
        BindingSource peopleDataSource = new BindingSource();
        peopleDataSource.DataSource = peopleList;
        dataGridTableStyle1.MappingName = peopleDataSource.GetListName(null);
        dataGrid1.DataSource = peopleDataSource;
    }

    // I'll cache this brush in the form, just make sure to dispose it (see designer.cs disposing)
    SolidBrush highlightBrush = new SolidBrush(Color.Yellow);

    // here is the event you can handle to determine the color of your row!
    private void ColumnSetCellFormat(object sender, DataGridFormatCellEventArgs e)
    {
        if ((e.Source.List[e.Row] as PersonTest).HighlightPerson)
            e.BackBrush = highlightBrush;
    }

    // example test class
    public class PersonTest
    {
        public String FirstName { get; set; }
        public String LastName { get; set; }
        public bool HighlightPerson { get; set; }
    }
}

And the custom data grid column

public class FormattableTextBoxColumn : DataGridTextBoxColumn
{
    public event FormatCellEventHandler SetCellFormat;

    protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
    {
        DataGridFormatCellEventArgs e = new DataGridFormatCellEventArgs(rowNum, source);
        e.ForeBrush = foreBrush;
        e.BackBrush = backBrush;
        OnSetCellFormat(e);
        base.Paint(g, bounds, source, rowNum, e.BackBrush, e.ForeBrush, alignToRight);
    }

    private void OnSetCellFormat(DataGridFormatCellEventArgs e)
    {
        FormatCellEventHandler handler = SetCellFormat;

        if (handler != null)
            handler(this, e);
    }
}

You'll also need this DataGridCellEventArgs.cs

public delegate void FormatCellEventHandler(object sender, DataGridFormatCellEventArgs e);

public class DataGridFormatCellEventArgs : EventArgs
{
    public int Row;
    public CurrencyManager Source;
    public Brush BackBrush;
    public Brush ForeBrush;

    public DataGridFormatCellEventArgs(int row, CurrencyManager manager)
    {
        this.Row = row;
        this.Source = manager;
    }
}

Here's an example project for you:

DataGridTest.zip




回答2:


I haven't worked with CF, but I thought I would throw this out there... If you can access the cell, wouldn't the row be it's NamingContainer? If so you could drill up to the row and apply a style or add an attribute with a CSS class.



来源:https://stackoverflow.com/questions/12908705/color-whole-row-instead-of-single-cell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!