星期三, 11月 16, 2016

[C#] Control.Visible 和 DataBinding

實務上有把控件隱藏起來的設計,使用時發現資料無法回傳 DB,才發現原來原來控件隱藏的時間點很重要
  • 控件加入 Form 隱藏,DataBinding 無法正常作動
  • 控件加入 Form 隱藏,預期效果
測試只發現上述說明,後來才找到這篇 技術論壇討論,說明該情況是因為 Binding.Fomat Event 加入前隱藏的話,Format Event 就不會被觸發。

簡易範例來記錄

Form Layout

[C#] Control.Visible 和 DataBinding-1


namespace BindingSourceVisible
{
    public partial class Form1 : Form
    {
        private BindingSource bs = new BindingSource();
        private DataTable dt = new DataTable();
        private TextBox txtHide = new TextBox();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 建立資料
            dt.Columns.Add("ProductName", typeof(string));
            dt.Rows.Add("Windows Server");
            dt.Rows.Add("SQL Server");
            dt.Rows.Add("Visual Studio");
            dt.Rows.Add("Office");
            dt.AcceptChanges();

            // BindingSource 設定
            bs.PositionChanged += Bs_PositionChanged;
            bs.DataSource = dt;
            bindingNavigator1.BindingSource = bs;

            // TextBox DataBinding 設定
            Binding bindShow = new Binding("Text", bs, "ProductName", true);
            bindShow.Format += BindShow_Format;
            txtShow.DataBindings.Add(bindShow);

            Binding bindHide = new Binding("Text", bs, "ProductName", true);
            bindHide.Format += BindHide_Format;
            txtHide.DataBindings.Add(bindHide);

            // 重點:測試 txtHide.Visible = false 和 Form.Controls.Add(txtHide) 前後差異
            txtHide.Visible = false;
            this.Controls.Add(txtHide);

            GetTextPropertyData();
        }

        /// <summary>
        /// BindingSource 移動時,必須顯示最新資料
        /// </summary>
        /// <param name="sender">BindingSource</param>
        /// <param name="e">EventArgs</param>
        private void Bs_PositionChanged(object sender, EventArgs e)
        {
            GetTextPropertyData();
        }

        /// <summary>
        /// 取得 
        /// txtHide、txtShow Text Property 資料
        /// BindingSource.Current 資料
        /// 並顯示在 TextInfo 內
        /// </summary>
        private void GetTextPropertyData()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine($"TextBox1:{txtHide.Text}");
            sb.AppendLine($"TextBox2:{txtShow.Text}");
            sb.AppendLine($"BindingSource.Current:{GetCurrentValue()}");
            TextInfo.Text = sb.ToString();
        }

        private void BindShow_Format(object sender, ConvertEventArgs e)
        {
            lstFormatTrigger.Items.Add($"{GetCurrentValue()} - BindShow_Format");
        }

        private void BindHide_Format(object sender, ConvertEventArgs e)
        {
            lstFormatTrigger.Items.Add($"{GetCurrentValue()} - BindHide_Format");
        }

        /// <summary>
        /// 從 BindingSource 取得目前資料
        /// </summary>
        /// <returns>ProductName 資料</returns>
        private string GetCurrentValue()
        {
            return (bs.Current as DataRowView).Row.Field<string>("ProductName");
        }
    }
}
測試1:先把 txtHide 加入 Form.Controls 後,再把 txtHide 隱藏
結果1:txtHide 的 Binding.Format Event 正常觸發,txtHide.Text Property 也可以抓到值

[C#] Control.Visible 和 DataBinding-2

測試2:先把 txtHide 隱藏後,再加入 Form.Controls
結果2:txtHide 的 Binding.Format Event 沒有觸發,txtHide.Text Property 抓不到值

[C#] Control.Visible 和 DataBinding-3

沒有留言:

張貼留言