UserControlへのTabによるフォーカス移動について

1,401 views
Skip to first unread message

masatakashibuya

unread,
Jul 26, 2018, 6:08:11 AM7/26/18
to OpenTouryoProject
Open棟梁とは関係ないですが
WindowsFormで、UserControlが配置されているような画面で
Tabによるフォーカス移動をした場合についてです。

UserControl上にFocus可能なコントロールがない場合、
UserControlがActiveControlとなりFocusされている?状態となります。
Focus可能なコントロールがない場合は、次のタブインデックス順のControlへフォーカス移動してほしいです。

UserControl上にフォーカス可能なコントロールがない場合は
UserControlのプロパティのCanGetFocusをFalseにするとかできればいいのですが...

なにかいい方法はないでしょうか。

daisukenishino

unread,
Jul 26, 2018, 10:50:18 PM7/26/18
to OpenTouryoProject
渋谷さん

ControlStyles.Selectableと言うメソッドがあるようです。


なので、試してないですが、

対象となるコンテナ系のコントロールを再起検索して、
Control.HasChildrenがfalseなら、
ControlStyles.Selectableをfalseに設定するとかどうでしょう?

ただ調べてみると、

Control.SetStyle メソッドはprotected なので
コレを操作する場合、コンテナ系のコントロールの
カスタムコントロールを作成する必要があるかも知れません。

西野

2018年7月26日木曜日 19時08分11秒 UTC+9 masatakashibuya:

masatakashibuya

unread,
Jul 27, 2018, 3:24:26 AM7/27/18
to OpenTouryoProject
西野様

コンテナ系のコントロールには、コントロールが配置されているのですが
Enableが変更されたりなどで、活性非活性が切り替わります。
配置されたコントロールが全てフォーカスできない状態になった場合、UserControl上でフォーカスが行方不明になります。

コントロールの状態を常に監視して、SetStyleを切替えるというのも
現実的ではないような....


2018年7月27日金曜日 11時50分18秒 UTC+9 daisukenishino:

daisukenishino

unread,
Jul 27, 2018, 3:59:46 AM7/27/18
to OpenTouryoProject
渋谷さん

UserControlだとCustomControl化は不要ですね。

しかし、活性・非活性、表示・非表示制御だとHasChildrenは使えないですね。
となると、Observerなどの監視ではなく、活性・非活性、表示・非表示で
値を変更した後、再帰検索してSetStyleで設定する値を制御できないか?

ななどと考えます。

西野

2018年7月27日金曜日 16時24分26秒 UTC+9 masatakashibuya:

masatakashibuya

unread,
Jul 31, 2018, 2:37:47 AM7/31/18
to OpenTouryoProject
西野様

ありがとうございます。

UserControlのコンストラクタで、UserControl上のコントロールの活性非活性・表示非表示処理にイベントを追加して。
UserControl上のコントロールの活性非活性・表示非表示イベントで
UserControl上のコントロールがフォーカス可能な状態かどうか再帰検索して、不可能ならSelectableをfalseにするというふうに
やってみようと思います。

UserControl上に子UserControlがある場合は、子UserControlのSelectableを確認し、さらに子のコントロールは確認しなくておkかなと思います。


2018年7月27日金曜日 16時59分46秒 UTC+9 daisukenishino:

masatakashibuya

unread,
Nov 1, 2018, 4:49:13 AM11/1/18
to OpenTouryoProject
この件について対応しました。コードを共有させていただきます。

1.まずユーザーコントロールのSelectableスタイルを取得または設定するプロパティを作成します。
        /// <summary>
        /// このユーザーコントロールが選択可能かどうかを取得または設定します。
        /// </summary>
        public bool Selectable
        {
            get
            {
                return this.GetStyle(ControlStyles.Selectable);
            }
            set
            {
                if (this.GetStyle(ControlStyles.Selectable) != value)
                {
                    this.SetStyle(ControlStyles.Selectable, value);
                    this.OnSelectableChanged(EventArgs.Empty);
                }
            }
        }


        // ユーザーコントロールのSelectable・Visibleが変更した時のイベントに
        // ユーザーコントロール上の各コントロールが活性かどうかをチェックする処理を追加します。
        userControl.SelectableChanged += new EventHandler(this.ChkActive);
        userControl.VisibleChanged += new EventHandler(this.ChkActive);

2.チェック処理を実装します

        /// <summary>
        /// このユーザーコントロール上のコントロールがアクティブかどうかをチェックし、アクティブなコントロールが1つでもある場合、このユーザーコントロールも選択可能とする
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ChkActive(object sender, EventArgs e)
        {
            // 子のコントロールをチェックする
            foreach (Control ctrl in this.Controls)
            {
                // アクティブなコントロールが1つでもあれば、ユーザーコントロールを選択可能とし処理を抜ける
                if (this._ChkActive(ctrl))
                {
                    this.Selectable = true;
                    return;
                }
            }

            this.Selectable = false;
        }

        /// <summary>
        /// チェック処理
        /// </summary>
        /// <param name="ctrl"></param>
        /// <returns></returns>
        private bool _ChkActive(Control ctrl)
        {
            bool visible = ctrl.Visible;
            bool tabstop = ctrl.TabStop;
            bool selectable = false;

            // ユーザーコントロールの場合はSelectableを確認
            if (ctrl is HekUserControl)
            {
                var u = (HekUserControl)ctrl;
                selectable = u.Selectable;
            }
            // 他のコントロールはEnableを確認
            else
            {
                selectable = ctrl.Enabled;
            }

            // アクティブな時
            if (visible &&  tabstop && selectable)
            {
                return true;
            }

            // さらに子のコントロールがある時、かつユーザーコントロールでない時
            if (ctrl.Controls.Count != 0 && !(ctrl is HekUserControl))
            {
                foreach (Control next in ctrl.Controls)
                {
                    if (this._ChkActive(next))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

3.ユーザーコントロール上の各コントロールのVisible・TabStop・Enable・Selectable(ユーザーコントロールのみ)のChangeイベントにチェック処理を追加します

        // 追加する
        usercontrol.AddChangeActiveEvent();

        /// <summary>
        /// ChkActive処理をイベントに追加する
        /// </summary>
        public void AddChangeActiveEvent()
        {
            foreach (Control ctrl in this.Controls)
            {
                this._AddChangeActiveEvent(ctrl);
            }
        }

        /// <summary>
        /// ChkActive処理をイベントに追加する
        /// </summary>
        /// <param name="ctrl"></param>
        private void _AddChangeActiveEvent(Control ctrl)
        {
            // ユーザーコントロールはSelectableのみ
            if (ctrl is HekUserControl)
            {
                var u = (HekUserControl)ctrl;
                u.SelectableChanged += new EventHandler(this.ChkActive);
            }
            // ユーザーコントロール以外のコントロールの場合
            else
            {
                ctrl.VisibleChanged += new EventHandler(this.ChkActive);
                ctrl.TabStopChanged += new EventHandler(this.ChkActive);
                ctrl.EnableChanged += new EventHandler(this.ChkActive);

                // さらに子のコントロールがある時
                if (ctrl.Controls.Count != 0)
                {
                    foreach (Control next in ctrl.Controls)
                    {
                        this._AddChangeActiveEvent(next);
                    }
                }
            }
        }


2018年7月31日火曜日 15時37分47秒 UTC+9 masatakashibuya:

nishi.74322014

unread,
Nov 21, 2018, 6:58:17 AM11/21/18
to OpenTouryoProject
渋谷さん

ありがとうございます。

Gメールの通知を操作ミスで切っていて気が付きませんでした。
以降、.利用機会があればこちらを参考にさせて頂こうと思います。

※ もっと、掲載場所として適切な場所があるかもしれません。
 GitHub Gistなんかでもイイかも。



西野
Reply all
Reply to author
Forward
0 new messages