3

フォームにいくつかのコントロールがあります。

  • チェックされた状態に基づいて、ページ上の他のすべてのコントロールを有効/無効にするチェックボックス。
  • チェックされた状態に基づいて、ページ上の特定のコントロールを有効/無効にする役割を持ついくつかのラジオ ボタン。
  • 上記のコントロールによって操作されるその他のコントロール。

いくつかのシナリオが発生します。

  • フォームが初期化されると、チェックボックスの状態が読み込まれます。次に、フォーム上の残りのコントロールを有効または無効にします。
  • フォームの初期化が続くので、ラジオ ボタンの状態を読み込みます。ラジオボタンがチェックされているが無効になっている場合、これにより、以前の要件が取り消される可能性があります。そのため、最初にラジオボタンが有効になっていることを確認します。
  • フォームが読み込まれた後、ユーザーはラジオ ボタンをオンまたはオフにすることができます。これは些細なケースです。最後の要件を満たすコードを実行しただけです。ただし、別のケースとして、ユーザーがチェックボックスをオンまたはオフにする場合があります。チェックボックスが有効になると、ページ上のすべてのコントロールを無効にしたため、再度有効にする必要があります。ただし、これを行うと、ラジオ ボタンの要件に違反します。

このシナリオは、力ずくで処理するのは非常に簡単です。強調するためにいくつかのメソッドを作成しました。

private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
{
    snmpSettingsErrorProvider.Clear();

    foreach (Control control in grpBxSNMPv3.Controls)
    {
        if (control != sender)
            control.Enabled = ((CheckBox)sender).Checked;
    }
}

private void rdBtnAuthNoPriv_CheckedChanged(object sender, EventArgs e)
{
    RadioButton authNoPrivRadioButton = ((RadioButton)sender);

    if (authNoPrivRadioButton.Enabled)
    {
        bool isChecked = authNoPrivRadioButton.Checked;

        SetControlState(cmbBxAuthProtocol, isChecked);
        SetControlState(mskdTxtBxAuthPassword, isChecked);
        SetControlState(mskdTxtBxAuthPasswordConfirm, isChecked);

        SetControlState(cmbBxPrivacyProtocol, !isChecked);
        SetControlState(mskdTxtBxPrivacyPassword, !isChecked);
        SetControlState(mskdTxtBxPrivacyPasswordConfirm, !isChecked);
    }
}
//More methods for other checkedChange and also for when rdBtn's enable.

レイアウトの大まかなアイデア:

ここに画像の説明を入力

そうは言っても、私の質問は「単純」です。

  • メソッドは、他のメソッドが存在することを前提とせずに機能する必要があります。それでも、chkBx の存在に対する rdBtn の論理的ネットワークを維持すると、コードが互いに争わなければならないことになります。

次のようにコードを書くことができます:

private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
{
    snmpSettingsErrorProvider.Clear();

    txtBxEngineID = ((CheckBox)sender).Checked;
    rdBtnAuthNoPriv = ((CheckBox)sender).Checked;
    rdBtnAuthPriv = ((CheckBox)sender).Checked;
    rdBtnNoAuthNoPriv = ((CheckBox)sender).Checked;

    //Pass work for enabling Auth and Priv fields to rdBtn events.
}

このソリューションはより効率的であり、ちらつきがないことを保証します。それでも、ページ上のすべてのコントロールを有効にする「正常な完了」のために、chkBx が rdBtn のロジックに依存する必要があることも意味します。これは良いプログラミング手法ですか?

4

2 に答える 2

1

これはフォームに保持するのに賢明なコードだと思いますが、いくつか提案します。

1)鋳造にはわずかな処理コストがかかるため、ループ内での鋳造は避けてください。実際、一般的な概念として、結果が同じままであることが保証されている場合は、ループ内で繰り返しアクションを実行することは避けてください。したがって、最初の方法をそのように改善することができます。

private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
{
    snmpSettingsErrorProvider.Clear();

    // cast the sender once only
    CheckBox cb = sender as CheckBox;
    if (null == cb) return;

    foreach (Control control in grpBxSNMPv3.Controls)
    {
        if (control != sender)
            control.Enabled = cb.Checked;
    }
}

2)有効化/無効化ロジックを別のメソッドに移動し、コントロールイベントハンドラーから呼び出すことをお勧めします。これにより、他のコントロールから、必要に応じて同じロジックを再利用できるようになります。動作を制御イベントに緊密に結合すると、コードが重複することになります。そのようです;

private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
{
    snmpSettingsErrorProvider.Clear();

    // cast the sender once only
    CheckBox cb = sender as CheckBox;
    if (null == cb) return;

    SetEnabled(grpBxSNMPv3, cb.Checked, new[] { cb });
}

private void SetEnabled(Control parent, bool isEnabled, Control[] exludeControls)
{
    if (null == parent) return;

    foreach (Control control in parent.Controls)
    {
        if (!excludeControls.Contains(control))
            control.Enabled = isEnabled;
    }
}

これで、別のコントロールに含まれるすべてのコントロールを有効/無効にする再利用可能なメソッドができました。

3)最後の質問ですが、そうです、このアプローチは問題ないと思います。結合を少なくすることは常に良いことです。より再利用できるようにメソッドを設計する方法を考えてください。そうすれば、クリーンなソリューションを思い付くことができると思います。

于 2012-05-21T22:28:36.013 に答える
0

これが私が最終的に行ったものです。初期化中の2つのリストを除けば、私はそれでかなり問題ありません。彼らはおそらく彼ら自身のコントロール下にあるはずですが、私はまだそれを行うことができません.

public partial class DeviceSnmpSettings : UserControl, INotifyPropertyChanged
{
    private readonly List<Control> AuthenticationControls = new List<Control>(6);
    private readonly List<Control> PrivacyControls = new List<Control>(6);
    public event PropertyChangedEventHandler PropertyChanged;

    public DeviceSnmpSettings()
    {
        InitializeComponent();
        InitializeAuthControls();
        InitializePrivacyControls();
    }

    public DeviceSnmpSettings(Point location)
        : this()
    {
        Location = location;
    }

    //TODO: Move out into sub-user control?
    private void InitializeAuthControls()
    {
        AuthenticationControls.Add(lblAuthPassword);
        AuthenticationControls.Add(mskdTxtBxAuthPassword);
        AuthenticationControls.Add(lblAuthProtocol);
        AuthenticationControls.Add(cmbBxAuthProtocol);
        AuthenticationControls.Add(lblAuthPasswordConfirm);
        AuthenticationControls.Add(mskdTxtBxAuthPasswordConfirm);
    }
    //TODO: Move out into sub-user control?
    private void InitializePrivacyControls()
    {
        PrivacyControls.Add(lblPrivacyPassword);
        PrivacyControls.Add(mskdTxtBxPrivacyPassword);
        PrivacyControls.Add(lblPrivacyProtocol);
        PrivacyControls.Add(cmbBxPrivacyProtocol);
        PrivacyControls.Add(lblPrivacyPasswordConfirm);
        PrivacyControls.Add(mskdTxtBxPrivacyPasswordConfirm);
    }

    private bool SNMPv3Enabled
    {
        get { return chkBxSNMPv3.Checked; }
        set { chkBxSNMPv3.Checked = value; }
    }

    private SNMPV3Mode SecurityMode
    {
        get
        {
            SNMPV3Mode mode = SNMPV3Mode.NoAuthNoPriv;

            if (rdBtnAuthNoPriv.Checked)
                mode = SNMPV3Mode.AuthNoPriv;
            else if(rdBtnAuthPriv.Checked)
                mode = SNMPV3Mode.AuthPriv;

            return mode;
        }
        set
        {
            switch (value)
            {
                case SNMPV3Mode.NoAuthNoPriv:
                    rdBtnNoAuthNoPriv.Checked = true;
                    break;
                case SNMPV3Mode.AuthNoPriv:
                    rdBtnAuthNoPriv.Checked = true;
                    break;
                default:
                    rdBtnAuthPriv.Checked = true;
                    break;
            }

            OnSecurityModeChanged();
        }
    }

    protected virtual void OnSecurityModeChanged()
    {
        AuthenticationControls.ForEach(control => SetControlEnabledState(control, AuthenticationEnabled));
        PrivacyControls.ForEach(control => SetControlEnabledState(control, PrivacyEnabled));
        NotifyPropertyChanged("SecurityMode");
    }

    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }

    private bool AuthenticationEnabled
    {
        get
        {
            return SNMPv3Enabled && (SecurityMode == SNMPV3Mode.AuthPriv || SecurityMode == SNMPV3Mode.AuthNoPriv);
        }
    }

    private bool PrivacyEnabled
    {
        get { return SNMPv3Enabled && SecurityMode == SNMPV3Mode.AuthPriv; }
    }

    private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
    {
        SetControlEnabledStates();
    }

    private void SetControlEnabledStates()
    {
        snmpSettingsErrorProvider.Clear();

        foreach (Control control in grpBxSNMPv3.Controls)
        {
            //Check each of the lists for the control to prevent flickering.
            if (control != chkBxSNMPv3 && !AuthenticationControls.Contains(control) && !PrivacyControls.Contains(control))
                control.Enabled = SNMPv3Enabled;
        }

        //Need to validate that our radio button's checked state is reflected properly.
        AuthenticationControls.ForEach(control => SetControlEnabledState(control, AuthenticationEnabled));
        PrivacyControls.ForEach(control => SetControlEnabledState(control, PrivacyEnabled));
    }

    public void LoadFields(NetworkDiscovery networkDiscovery)
    {
        SNMPv3Enabled = networkDiscovery.Snmpv3Enabled;
        SecurityMode = networkDiscovery.SecurityMode;
        txtBxSNMPv3Username.Text = networkDiscovery.Username;
        mskdTxtBxAuthPassword.Text = networkDiscovery.AuthPassword;
        mskdTxtBxAuthPasswordConfirm.Text = networkDiscovery.AuthPassword;
        cmbBxAuthProtocol.SelectedItem = networkDiscovery.AuthProtocol.ToString();
        mskdTxtBxPrivacyPassword.Text = networkDiscovery.PrivacyPassword;
        mskdTxtBxPrivacyPasswordConfirm.Text = networkDiscovery.PrivacyPassword;
        cmbBxPrivacyProtocol.SelectedItem = networkDiscovery.PrivacyProtocol.ToString();

        SetControlEnabledStates();
    }

    private void SetControlEnabledState(Control control, bool enabled)
    {
        control.Enabled = enabled;
                    //Clear errors set on errorProvider when control is disabled.
        if (!control.Enabled)
            snmpSettingsErrorProvider.SetError(control, string.Empty);
    }

    private void rdBtnNoAuthNoPriv_CheckedChanged(object sender, EventArgs e)
    {
        if (((RadioButton)sender).Checked)
            SecurityMode = SNMPV3Mode.NoAuthNoPriv;
    }

    private void rdBtnAuthNoPriv_CheckedChanged(object sender, EventArgs e)
    {
        if (((RadioButton)sender).Checked)
            SecurityMode = SNMPV3Mode.AuthNoPriv;
    }

    private void rdBtnAuthPriv_CheckedChanged(object sender, EventArgs e)
    {
        if (((RadioButton)sender).Checked)
            SecurityMode = SNMPV3Mode.AuthPriv;
    }
}
于 2012-05-21T22:51:52.223 に答える