none
TFSoft-[Enter键]转[Tab键]行为控件(支持嵌套控件) RRS feed

  • 问题

  • 鉴于很多人提出,如何在输入界面中,按下回车键,需要让下一个控件得到焦点的问题(也就是模拟[Tab键]按下的效果)。
    网上始终没有人给出较为完满的解决方案。

    TFSoft就写了一个TFEnterBehaviour类给大家参考使用。

    调用方法:
    <UserControl x:Class="TFNjrySla.XT_CtLogin"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
                 xmlns:ex="clr-namespace:EX;assembly=TFSoftSlaLib"   //TFEnterBehaviour引用,请据情修改
        >
    <Grid x:Name="GrdTest">
      <---这里是引用TFEnterBehaviour---------------->
        <i:Interaction.Behaviors>
           <ex:TFEnterBehaviour></ex:TFEnterBehaviour>           
       </i:Interaction.Behaviors>
      <---这里是你的输入控件,GrdTest内可以包括嵌套的输入控件(省略)--->
    </Grid>

    行为类:
        //--------------------------------------------------------------------------------------------
        //TFEnterBehaviour
        //--------------------------------------------------------------------------------------------
        public class TFEnterBehaviour : Behavior<FrameworkElement> {
            private FrameworkElement AssociatedContainer;
            private Type[] CanAcceptEnterControlTypes;
            private List<TFEnterBehaviourItem> CanAcceptEnterControlList;
            //--------------------------------------------------------------------------------------------
            public TFEnterBehaviour() {
                CanAcceptEnterControlTypes = new Type[] { typeof(TextBox), typeof(CheckBox),
                                                          typeof(ComboBox), typeof(PasswordBox) };
            }
            //------------------------------------------------------------------------------------------------
            protected override void OnAttached() {
                base.OnAttached();
                AssociatedContainer = AssociatedObject;
                AssociatedContainer.KeyDown += new KeyEventHandler(AssociatedContainer_KeyDown);
                AssociatedContainer.Loaded += new RoutedEventHandler(AssociatedContainer_Loaded);
            }
            //--------------------------------------------------------------------------------------------
            protected override void OnDetaching() {
                AssociatedContainer.KeyDown -= new KeyEventHandler(AssociatedContainer_KeyDown);
                AssociatedContainer.Loaded -= new RoutedEventHandler(AssociatedContainer_Loaded);
                base.OnDetaching();
            }
            //------------------------------------------------------------------------------------------------
            void AssociatedContainer_Loaded(object sender, RoutedEventArgs e) {
                InitCanAcceptEnterControlList();
            }
            //--------------------------------------------------------------------------------------------
            private void AssociatedContainer_KeyDown(object sender, KeyEventArgs e) {
                if (e.Key == Key.Enter) {
                    if (e.OriginalSource is Control) {
                        var ElNext = GetNextCanAcceptEnterControl((Control)e.OriginalSource);
                        if (ElNext != null) { e.Handled = true; ElNext.Focus(); };
                    }
                }
            }
            //--------------------------------------------------------------------------------------------
            private void InitCanAcceptEnterControlList() {
                CanAcceptEnterControlList = new List<TFEnterBehaviourItem>();
                CanAcceptEnterControlList.Clear();
                if (AssociatedContainer != null) {
                    if (CanAcceptEnterControlTypes != null && CanAcceptEnterControlTypes.Length > 0) {
                        InitCanAcceptEnterControlListSub(AssociatedContainer);
                    }
                }
                if (CanAcceptEnterControlList.Count >= 2) {
                    CanAcceptEnterControlList.Sort(new TFEnterBehaviourItemTabIndexComparer());
                }
            }
            //--------------------------------------------------------------------------------------------
            private void InitCanAcceptEnterControlListSub(FrameworkElement ElContainer) {
                var I = 0; var N = VisualTreeHelper.GetChildrenCount(ElContainer);
                var J = 0; var ElCurrent = (FrameworkElement)null;
                for (I = 0; I <= N - 1; I++) {
                    ElCurrent = (FrameworkElement)VisualTreeHelper.GetChild(ElContainer, I);
                    if (ElCurrent is Control) {
                        var CtlCurrent = (Control)ElCurrent;
                        for (J = 0; J <= CanAcceptEnterControlTypes.Length - 1; J++) {
                            if (CtlCurrent.GetType() == CanAcceptEnterControlTypes[J]) {
                                if (CtlCurrent.IsTabStop) {
                                    var EnterBehaviourItem = new TFEnterBehaviourItem();
                                    EnterBehaviourItem.ObjRef = CtlCurrent; EnterBehaviourItem.ObjTabIndex = CtlCurrent.TabIndex;
                                    CanAcceptEnterControlList.Add(EnterBehaviourItem);
                                }
                            }
                        }
                    }
                    InitCanAcceptEnterControlListSub(ElCurrent);
                }
            }
            //--------------------------------------------------------------------------------------------
            private Control GetNextCanAcceptEnterControl(Control CurrentControl) {
                var Rlt = (Control)null;
                if (CurrentControl == null) {
                    if (CanAcceptEnterControlList.Count > 0) Rlt = CanAcceptEnterControlList[0].ObjRef;
                } else {
                    for (var I = 0; I <= CanAcceptEnterControlList.Count - 1; I++) {
                        if (CurrentControl == CanAcceptEnterControlList[I].ObjRef) {
                            if (I == CanAcceptEnterControlList.Count - 1) {
                                Rlt = CanAcceptEnterControlList[0].ObjRef;
                            } else {
                                Rlt = CanAcceptEnterControlList[I + 1].ObjRef;
                            }
                            break;
                        }
                    }
                }
                return Rlt;
            }
            //--------------------------------------------------------------------------------------------
            //class TFEnterBehaviourItem
            //--------------------------------------------------------------------------------------------
            private class TFEnterBehaviourItem {
                public Control ObjRef { get; set; }
                public Int32 ObjTabIndex { get; set; }
                public TFEnterBehaviourItem() { ObjRef = null; ObjTabIndex = -1; }
            }
            //--------------------------------------------------------------------------------------------
            //class TFEnterBehaviourItemTabIndexComparer
            //--------------------------------------------------------------------------------------------
            private class TFEnterBehaviourItemTabIndexComparer : IComparer<TFEnterBehaviourItem> {
                int IComparer<TFEnterBehaviourItem>.Compare(TFEnterBehaviourItem x, TFEnterBehaviourItem y) {
                    return x.ObjTabIndex.CompareTo(y.ObjTabIndex);
                }
            }
            //--------------------------------------------------------------------------------------------
        }
        //--------------------------------------------------------------------------------------------
    • 已编辑 TFSoft 2009年12月17日 8:52
    2009年12月9日 19:39

答案

  • 1) 谢谢你的夸奖。

    2) 我愿意在此共享我的其他代码(如:直接在SL中无缝访问后台数据库的TFData Access类,无缝的意思就是说和你在后台访问数据库的方法基本一样),如果这里的朋友喜欢。

    3) 我的C#代码看起来像VB.net代码,因为我1个月前,从未使用过C#,只是大家动不动就是C#,我只好用C#写,可能写的格式不太好,请谅解。
    2009年12月17日 9:02

全部回复

  • 你好,
      
          很不错的Behavior,会帮助到很多人的,谢谢你与大家的分享

    2009年12月17日 2:08
  • 1) 谢谢你的夸奖。

    2) 我愿意在此共享我的其他代码(如:直接在SL中无缝访问后台数据库的TFData Access类,无缝的意思就是说和你在后台访问数据库的方法基本一样),如果这里的朋友喜欢。

    3) 我的C#代码看起来像VB.net代码,因为我1个月前,从未使用过C#,只是大家动不动就是C#,我只好用C#写,可能写的格式不太好,请谅解。
    2009年12月17日 9:02