1

しばらくの間、カスタム チェック ボックス コントロールに問題があり、この質問を投稿しました...問題はイベントに関連していないようです。

カスタム コントロールは、チェック ボックス付きのグループ ボックスです。チェック ボックスが false の場合、すべてのグループ コントロールを無効にする必要があります。簡単に聞こえますが、内部コントロールがフォーカスを失うと、checked change イベントが発生するという問題があります。

もう少し掘り下げた後、チェックされたプロパティを別のオブジェクトにバインドすることに絞り込んだと思います。バインディングが含まれていると正しく動作しませんが、バインディングを削除するとすべてが期待どおりに動作します。

問題が見つかったので、問題を解決する方法がわかりません。

誰でも助けることができますか?

これが私のテストアプリケーションのコードです--

フォーム: ここに画像の説明を入力

フォームコード:

public partial class Form1 : Form
{
    TestProperties m_TP;

    public Form1()
    {
        // Create instance of TestProperties
        m_TP = new TestProperties();

        InitializeComponent();

        BindControls();
    }

    private void BindControls()
    {
        // Bind the values to from the controls in the group to the properties class

        // When the line below is commented out the control behaves normally
        //this.checkedGroupBox1.DataBindings.Add("Checked", m_TP, "GroupChecked");
        this.numericUpDown1.DataBindings.Add("Value", m_TP, "SomeNumber");
        this.textBox1.DataBindings.Add("Text", m_TP, "SomeText");
        this.checkBox1.DataBindings.Add("Checked", m_TP, "BoxChecked");

        // Bind the values of the properties to the lables
        this.label4.DataBindings.Add("Text", m_TP, "GroupChecked");
        this.label5.DataBindings.Add("Text", m_TP, "SomeNumber");
        this.label6.DataBindings.Add("Text", m_TP, "SomeText");
        this.label8.DataBindings.Add("Text", m_TP, "BoxChecked");
    }
}

プロパティ ストレージ クラス:

class TestProperties
{
    public bool GroupChecked { get; set; }
    public decimal SomeNumber { get; set; }
    public string SomeText { get; set; }
    public bool BoxChecked { get; set; }

    public TestProperties()
    {
        GroupChecked = false;
        SomeNumber = 0;
        SomeText = string.Empty;
        BoxChecked = true;
    }
}

編集: これが私のカスタムコントロールのソースです:

/// <summary>
/// Custom control to create a checked group box.
/// Enables / disables all controls within the group depending upon the state of the check box
/// </summary>
public class CheckedGroupBox : System.Windows.Forms.GroupBox
{
    #region Private Member Variables
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Checkbox to enable / disable the controls within the group
    /// </summary>
    private CheckBox chkBox;

    /// <summary>
    /// Label for the group box which is set to autosize
    /// </summary>
    private Label lblDisplay;
    #endregion

    /// <summary>
    ///  Default constructor for the control
    /// </summary>
    public CheckedGroupBox()
    {
        // This call is required by the Windows Form Designer.
        InitializeComponent();

        // The text of these controls should always be empty.
        this.Text = "";
        this.chkBox.Text = "";
    }

    #region Events & Delegates

    /// <summary>
    /// Event to forward the change in checked flag
    /// </summary>
    public event EventHandler CheckedChanged;

    /// <summary>
    /// Event to forward the change in checked state of the checkbox
    /// </summary>
    public event EventHandler CheckStateChanged;

    private void chkBox_CheckedChanged(object sender, EventArgs e)
    {
        // Disable the controls within the group
        foreach (Control ctrl in this.Controls)
        {
            if (ctrl.Name != "chkBox" && ctrl.Name != "lblDisplay")
            {
                ctrl.Enabled = this.chkBox.Checked;
            }
        }

        // Now forward the Event from the checkbox
        if (this.CheckedChanged != null)
        {
            this.CheckedChanged(sender, e);
        }
    }

    private void chkBox_CheckStateChanged(object sender, EventArgs e)
    {
        // Forward the Event from the checkbox
        if (this.CheckStateChanged != null)
        {
            this.CheckStateChanged(sender, e);
        }
    }

    #endregion

    #region Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.chkBox = new System.Windows.Forms.CheckBox();
        this.lblDisplay = new System.Windows.Forms.Label();
        this.SuspendLayout();
        // 
        // chkBox
        // 
        this.chkBox.Location = new System.Drawing.Point(8, 0);
        this.chkBox.Name = "chkBox";
        this.chkBox.Size = new System.Drawing.Size(16, 16);
        this.chkBox.TabIndex = 0;
        this.chkBox.CheckStateChanged += new System.EventHandler(this.chkBox_CheckStateChanged);
        this.chkBox.CheckedChanged += new System.EventHandler(this.chkBox_CheckedChanged);
        // 
        // lblDisplay
        // 
        this.lblDisplay.AutoSize = true;
        this.lblDisplay.Location = new System.Drawing.Point(24, 0);
        this.lblDisplay.Name = "lblDisplay";
        this.lblDisplay.Size = new System.Drawing.Size(97, 13);
        this.lblDisplay.TabIndex = 1;
        this.lblDisplay.Text = "CheckedGroupBox";
        // 
        // CheckedGroupBox
        // 
        this.BackColor = System.Drawing.Color.AliceBlue;
        this.Controls.Add(this.chkBox);
        this.Controls.Add(this.lblDisplay);
        this.Size = new System.Drawing.Size(100, 100);
        this.ResumeLayout(false);
        this.PerformLayout();

    }
    #endregion

    #region Public properties

    [Bindable(true), Category("Appearance"), DefaultValue("Check Group Text")]
    public override string Text
    {
        get{ return this.lblDisplay.Text; }
        set{ this.lblDisplay.Text = value; }
    }

    [Bindable(true), Category("Appearance"), DefaultValue("Checked")]
    public System.Windows.Forms.CheckState CheckState
    {
        get{ return this.chkBox.CheckState; }
        set
        { 
            this.chkBox.CheckState = value; 

            foreach( Control ctrl in this.Controls )
            {
                if( ctrl.Name != "chkBox" && ctrl.Name != "lblDisplay" )
                {
                    ctrl.Enabled = this.chkBox.Checked;
                }
            }
        }
    }

    [Bindable(true), Category("Appearance"), DefaultValue("True")]
    public bool Checked
    {
        get{ return this.chkBox.Checked; }
        set
        { 
            this.chkBox.Checked = value; 

            foreach( Control ctrl in this.Controls )
            {
                if( ctrl.Name != "chkBox" && ctrl.Name != "lblDisplay" )
                {
                    ctrl.Enabled = this.chkBox.Checked;
                }
            }
        }
    }

    [Bindable(true), Category("Behavior"), DefaultValue("False")]
    public bool ThreeState
    {
        get{ return this.chkBox.ThreeState; }
        set{ this.chkBox.ThreeState = value; }
    }

    #endregion

}
4

3 に答える 3

2

BindControlsメソッドを次のように変更する必要があります。これは、デフォルトでコントロールがm_TPのプロパティを反映するように更新されているが、値が変更されても変更がm_TPに反映されていないためです(Leaveイベントによってコントロールがコントロールに再バインドされると思います)データソース)。DataSourceUpdateModeパラメーターを追加することにより、変更は双方向で行われます。

private void BindControls()
{
    // Bind the values to from the controls in the group to the properties class

    // When the line below is commented out the control behaves normally
    this.checkedGroupBox1.DataBindings.Add("Checked", m_TP, "GroupChecked", false, DataSourceUpdateMode.OnPropertyChanged);
    this.numericUpDown1.DataBindings.Add("Value", m_TP, "SomeNumber", false, DataSourceUpdateMode.OnPropertyChanged);
    this.textBox1.DataBindings.Add("Text", m_TP, "SomeText", false, DataSourceUpdateMode.OnPropertyChanged);
    this.checkBox1.DataBindings.Add("Checked", m_TP, "BoxChecked", false, DataSourceUpdateMode.OnPropertyChanged);

    // Bind the values of the properties to the lables
    this.label4.DataBindings.Add("Text", m_TP, "GroupChecked");
    this.label5.DataBindings.Add("Text", m_TP, "SomeNumber");
    this.label6.DataBindings.Add("Text", m_TP, "SomeText");
    this.label8.DataBindings.Add("Text", m_TP, "BoxChecked");
}
于 2011-10-28T11:31:52.153 に答える
1

まず、バインディングが適切に機能するためには、プロパティ ストレージ クラスに INotifyPropertyChanged を実装する必要があります。ここで例を見てください

Visual Studio 環境で、タイプ「Object」を指す新しい DataSource を作成します。TestProperties クラスをソース オブジェクトとして選択します (クラスがリストに表示されない場合は、含まれているアセンブリがビルドされていて、WinForm プロジェクトにそれへの参照があることを確認してください)。

データ ソース構成ウィザード

ここで、BindingSource をツールボックスからカスタム コントロールにドラッグします。BindingSource の DataSource プロパティを、前の手順で作成した TestProperties データ ソースに設定します。

ここで、カスタム コントロール グループボックスを選択し、(DataBindings) セクションに移動します。詳細フィールドの「...」をクリックします。カスタム グリッド コントロールの "Enabled" プロパティを BindingSource の "BoxChecked" プロパティにバインドします。これはすべてデザイナーで (または必要に応じてコード ビハインドを介して) 実行できます。

ここに画像の説明を入力

BindingSource を介して、カスタム コントロールの他の WinForms 要素を TestProperties クラスの適切な要素にバインドします。

ここで、カスタム コントロールのプロパティを公開して、「親」フォームでバインドできるようにします。BindingSource の「DataSource」を新しく参照するプロパティに設定してください。

    private TestProperties _properties;
    public TestProperties Properties
    {
        get { return _properties; }
        set
        {
            _properties = value;
            this.bindingSource1.DataSource = _properties;
        }
    }

    public UserControl1()
    {
        InitializeComponent();
    }

コントロールをホストしている親フォームには、いくつかのオプションがあります。

1) 上記の例のように、UserControl によって公開された TestProperties クラスに直接バインディングを実行できます。

2) 親コントロールのユーザー コントロールにバインドをセットアップするために使用した BindingSource 演習を繰り返し、(親フォームの) 新しい BindingSource の DataSource プロパティを、UserControl の公開された TestProperties プロパティと等しくなるように設定できます。

于 2011-10-27T17:24:59.477 に答える
0

このようなものは、私が得ることができる限り近いものです:

ここに画像の説明を入力

私は明らかにグループボックス(チェックボックスを含む)のコードを持っていないので、できる限りのことをしました。

これは、これを一番上のチェックボックスに追加することで実現されます。

private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
   groupBox1.Enabled = ((CheckBox)(sender)).Checked;
}

また、この行を再度有効にしました。

this.checkBox1.DataBindings.Add("Checked", m_TP, "GroupChecked");
于 2011-10-27T16:51:51.890 に答える