星期五, 8月 19, 2016

[C#] DataGridView 和 ReadOnly 屬性

使用 DataGridView 都只針對 Columns 設定 ReadOnly,後來發現原來 Rows 和 Cells 也可以設定 ReadOnly,寫個小範例練習

Project:就都寫在一個 Form 內

[C#] DataGridView 和 ReadOnly 屬性-1

Form Layout:橘框內是對 DataGridView ReadOnly 選項設定的功能,FlowlayoutPanel 內的 CheckBox 則是利用 Code 動態產生

[C#] DataGridView 和 ReadOnly 屬性-2


C# Code 功能簡易說明:
  • DataGridView 的 Columns、Rows 或 Cells 為 ReadOnly 的話,就把背景顏色設為紅色
  • 點選欄或列的 ComboBox 會勾選 FlowLayoutPanel 內的 CheckBox 並把對應的 DataGridView 欄或列設為 ReadOnly
  • 點選 ComboBox,假如對應的 CheckBox 都已經勾選,就會變成全部取消
  • 勾選 FlowLayoutPanel 內的 CheckBox,會設定對應 DataGridView 的 Cells ReadOnly 屬性
namespace DGVReadOnly
{
    public partial class Form1 : Form
    {
        private Color DefaultBGColor = Control.DefaultBackColor;

        private void Form1_Load(object sender, EventArgs e)
        {
            cboInit();
            cbInit();
            DGVInit();
        }

        private void cboInit()
        {
            for (int i = 1; i <= 5; i++)
            {
                cboColumns.Items.Add(i);
                cboRows.Items.Add(i);
            }
            cboColumns.SelectionChangeCommitted += CboColumns_SelectionChangeCommitted;
            cboRows.SelectionChangeCommitted += CboRows_SelectionChangeCommitted;
        }

        private void cbInit()
        {
            flowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
            flowLayoutPanel1.WrapContents = true;
            flowLayoutPanel1.AutoScroll = true;

            int ColumnCount = 0, RowCount = 0;
            for (int i = 1; i <= 25; i++)
            {
                CheckBox cb = new CheckBox();
                cb.AutoSize = true;
                cb.Name = "cb" + i;
                cb.Text = $"第 {ColumnCount + 1} 欄 - 第 {RowCount + 1} 列";
                cb.Tag = $"{ColumnCount}-{RowCount}";
                cb.CheckedChanged += Cb_CheckedChanged; ;

                RowCount++;
                if (i % 5 == 0)
                {
                    flowLayoutPanel1.SetFlowBreak(cb, true);
                    ColumnCount++;
                    RowCount = 0;
                }

                flowLayoutPanel1.Controls.Add(cb);
            }
        }

        private void DGVInit()
        {
            dataGridView1.AllowUserToAddRows = false;
            for (int i = 1; i <= 5; i++)
            {
                DataGridViewTextBoxColumn Col = new DataGridViewTextBoxColumn();
                dataGridView1.Columns.Add(Col);
                DataGridViewRow Row = new DataGridViewRow();
                dataGridView1.Rows.Add(Row);
            }
        }

        private void CboRows_SelectionChangeCommitted(object sender, EventArgs e)
        {
            string Row = cboRows.SelectedItem.ToString();
            int RowIndex = Text2Index(Row);
            IEnumerable<CheckBox> result = flowLayoutPanel1.Controls.OfType<CheckBox>()
                .Where(cb => TagParse2RowIndex(cb.Tag.ToString()) == RowIndex);

            bool readOnly = CheckBox5Judge(result);
            SetCheckBox(result, readOnly);

            dataGridView1.Rows[RowIndex].ReadOnly = readOnly;
            dataGridView1.Rows[RowIndex].DefaultCellStyle.BackColor = ReadOnlyBGColor(readOnly);
        }

        private void CboColumns_SelectionChangeCommitted(object sender, EventArgs e)
        {
            string Col = cboColumns.SelectedItem.ToString();
            int ColIndex = Text2Index(Col);

            IEnumerable<CheckBox> result = flowLayoutPanel1.Controls.OfType<CheckBox>()
                .Where(cb => TagParse2ColIndex(cb.Tag.ToString()) == ColIndex);

            bool readOnly = CheckBox5Judge(result);
            SetCheckBox(result, readOnly);

            dataGridView1.Columns[ColIndex].ReadOnly = readOnly;
            dataGridView1.Columns[ColIndex].DefaultCellStyle.BackColor = ReadOnlyBGColor(readOnly);
        }

        private void SetCheckBox(IEnumerable<CheckBox> Target, bool Checked)
        {
            foreach (CheckBox cb in Target)
                cb.Checked = Checked;
        }

        /// <summary>
        /// 點選 ComboBox ,選擇對應資料時,假如 CheckBox 內都已經選擇,就取消 ReadOnly
        /// </summary>
        /// <param name="Target">待判斷的 CheckBox</param>
        /// <returns>是否為 ReadOnly</returns>
        private bool CheckBox5Judge(IEnumerable<CheckBox> Target)
        {
            bool result = false;

            if (Target.Where(cb => cb.Checked == true).Count() != 5)
                result = true;

            return result;
        }

        /// <summary>
        /// 把 ComboBox 選擇的欄列資料,轉為對應 CheckBox、DataGridView 的 Index
        /// </summary>
        /// <param name="Text">ComBox 選擇資料</param>
        /// <returns>CheckBox、DataGridView 的 Index</returns>
        private int Text2Index(string Text)
        {
            return Convert.ToInt16(Text) - 1;
        }

        private Color ReadOnlyBGColor(bool readOnly)
        { 
            if (readOnly == true)
                return Color.Red;
            else
                return DefaultBGColor;
        }

        private void Cb_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox cb = sender as CheckBox;
            string Tag = cb.Tag.ToString();
            bool Checked = cb.Checked;

            int
                ColIndex = TagParse2ColIndex(Tag),
                RowIndex = TagParse2RowIndex(Tag);

            dataGridView1.Rows[RowIndex].Cells[ColIndex].ReadOnly = Checked;
            dataGridView1.Rows[RowIndex].Cells[ColIndex].Style.BackColor = ReadOnlyBGColor(Checked);
        } 

        private int TagParse2ColIndex(string tag)
        {
            return Convert.ToInt16(tag.Substring(0, 1));
        }

        private int TagParse2RowIndex(string tag)
        {
            return Convert.ToInt16(tag.Substring(2, 1));
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            SetCheckBox(
                flowLayoutPanel1.Controls.OfType<CheckBox>(),
                false);

            foreach (DataGridViewRow Row in dataGridView1.Rows)
            {
                Row.ReadOnly = false;
                Row.DefaultCellStyle.BackColor = DefaultBGColor;
            }
        }
    }
}
[C#] DataGridView 和 ReadOnly 屬性-3

沒有留言:

張貼留言