<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      happyhippy

      這個世界的問題在于聰明人充滿疑惑,而傻子們堅信不疑。--羅素

      更新內(nèi)容:

      1. Tab/Enter跳轉(zhuǎn)到下一列;
      2. 最后一行最后一列,Tab/Enter自動增加新行;
      3. 增加新行后,自動跳轉(zhuǎn)到新增行的第一列;
      4. 刪除行后,自動選中上一行;
      5. Up/Down/Left/Right自動編輯;

       

      實現(xiàn)方式:

      1. Tab/Enter跳轉(zhuǎn)到下一列

          從google搜到的一篇文章《Datagrid cell navigation with enter key》,文中最開始提到在DataGrid的KeyDown事件中進行處理。但是DataGrid里面做了一些封裝,我們在自己注冊(通過+=操作符來登記、或者XAML中定義)的KeyDown事件中,截獲不到Enter/Tab等鍵。所以最后原作者有提出一個思路:繼承DataGrid,重新OnKeyDown方法。

          但我之前的思路,是通過擴展方法來擴展DataGrid,再來重寫就有點兒郁悶了。于是找出Reflector,翻了下DataGrid的實現(xiàn)(reflector中copy出來的):

         1: // happyhippy.cnblogs.com
         2: // 構(gòu)造函數(shù)
         3: public DataGrid()
         4: {
         5:     //省略
         6:     base.KeyDown += new KeyEventHandler(this.DataGrid_KeyDown);
         7:     base.KeyUp += new KeyEventHandler(this.DataGrid_KeyUp);
         8:     //省略
         9: }
        10:  
        11: private void DataGrid_KeyDown(object sender, KeyEventArgs e)
        12: {
        13:     if (!e.Handled)
        14:     {
        15:         e.Handled = this.ProcessDataGridKey(e);
        16:     }
        17: }
        18:  
        19: private bool ProcessDataGridKey(KeyEventArgs e)
        20: {
        21:     bool flag = false;
        22:     switch (e.Key)
        23:     {
        24:         case Key.Tab:
        25:             return this.ProcessTabKey(e);
        26:  
        27:         case Key.Enter:
        28:             flag = this.ProcessEnterKey();
        29:             break;
        30:  
        31:         case Key.Escape:
        32:             return this.ProcessEscapeKey();
        33:  
        34:         case Key.PageUp:
        35:             flag = this.ProcessPriorKey();
        36:             break;
        37:  
        38:         case Key.PageDown:
        39:             flag = this.ProcessNextKey();
        40:             break;
        41:  
        42:         case Key.End:
        43:             flag = this.ProcessEndKey();
        44:             break;
        45:  
        46:         case Key.Home:
        47:             flag = this.ProcessHomeKey();
        48:             break;
        49:  
        50:         case Key.Left:
        51:             flag = (base.FlowDirection == FlowDirection.LeftToRight) ? this.ProcessLeftKey() : this.ProcessRightKey();
        52:             break;
        53:  
        54:         case Key.Up:
        55:             flag = this.ProcessUpKey();
        56:             break;
        57:  
        58:         case Key.Right:
        59:             flag = (base.FlowDirection == FlowDirection.LeftToRight) ? this.ProcessRightKey() : this.ProcessLeftKey();
        60:             break;
        61:  
        62:         case Key.Down:
        63:             flag = this.ProcessDownKey();
        64:             break;
        65:  
        66:         case Key.Insert:
        67:             return this.ProcessCopyKey();
        68:  
        69:         case Key.A:
        70:             return this.ProcessAKey();
        71:  
        72:         case Key.C:
        73:             return this.ProcessCopyKey();
        74:  
        75:         case Key.F2:
        76:             return this.ProcessF2Key(e);
        77:     }
        78:     if (flag && base.IsTabStop)
        79:     {
        80:         base.Focus();
        81:     }
        82:     return flag;
        83: }

        我們可以發(fā)現(xiàn),KeyDown中已經(jīng)定義一部分按鍵的處理,并更新了KeyEventArgs.Handled屬性。MSDN對該屬性的解釋是:

          將事件標記為已處理將會限制路由事件在事件路由過程中對于偵聽器的可見性。事件將仍然進行路由過程的其余部分,但只會在響應(yīng)中調(diào)用在 AddHandler(RoutedEvent, Delegate, Boolean) 方法調(diào)用中明確添加的其 HandledEventsToo 為 true 的處理程序。 將不會調(diào)用實例偵聽器上的默認處理程序(比如用可擴展應(yīng)用程序標記語言 (XAML) 表示的那些處理程序)。處理標記為已處理的事件這種情形并不常見。

          如果您是定義您自己的事件的控件作者,則您在類級別所做的有關(guān)事件處理的決策將影響您的控件的用戶,以及派生控件的任何用戶,并可能會影響您的控件所包含或包含您的控件的其他元素。有關(guān)更多信息,請參見 將路由事件標記為“已處理”和“類處理”。

          在極少數(shù)情況下,適合處理其中 Handled 標記為 true 的事件,并通過將 Handled 更改為 false 來修改事件參數(shù)。 在控件輸入事件的某些區(qū)域(比如 KeyDown 與 TextInput 鍵處理)中,低級別和高級別的輸入事件會爭用處理,并且每個事件都會嘗試使用不同的路由策略,因此,可能必須要這樣做。

          也就是說,在將KeyEventArgs.Handled,我們通過+=來自己注冊的處理程序,就無法執(zhí)行了。一種替代思路就是在不要用+=來注冊處理程序,而是調(diào)用AddHandler(RoutedEvent, Delegate, Boolean) 方法來注冊處理程序:

         1: //之前的處理方式,將監(jiān)聽不到已經(jīng)處理過的Tab/Enter等鍵
         2: //dataGrid.KeyDown += KeyDownHandler<T>; //注冊按鍵事件
         3: //只能通過下列方式來注冊
         4: dataGrid.AddHandler(DataGrid.KeyDownEvent, new KeyEventHandler(KeyDownHandler<T>), true);

       

         但在使用的時候發(fā)現(xiàn),如果當(dāng)前Cell(TextBlock)處于編輯狀態(tài),要按兩次Tab/Enter才能跳轉(zhuǎn)到下一列:第一次提交更改,第二次才執(zhí)行跳轉(zhuǎn)操作。

         回過頭來看,上面的DataGrid的部分源碼,跟進去看了下KeyUp事件的處理,發(fā)現(xiàn)KeyUp并沒有去更改KeyEventArgs.Handled屬性。因此,我們可以考慮在DataGrid上注冊自定義KeyUp事件,來做一些額外處理:

         1: dataGrid.KeyUp += KeyUpHandler<T>;
         2:  
         3: private static void KeyUpHandler<T>(object sender, KeyEventArgs e) where T : class, new()
         4: {
         5:       DataGrid dataGrid = sender as DataGrid;
         6:       switch (e.Key)
         7:       {
         8:              case Key.Tab:
         9:                     goto case Key.Enter;
        10:              case Key.Enter:
        11:                     if (dataGrid.CurrentColumn != null)
        12:                     {
        13:                         if (dataGrid.IsLastRow() & dataGrid.IsLastCell()) // Last Row And Last Cell (End of the grid)
        14:                         {
        15:                             dataGrid.AddEntity<T>();
        16:                         }
        17:                         else if (dataGrid.IsLastCell()) // Last Cell
        18:                         {
        19:                             dataGrid.SelectedIndex = dataGrid.SelectedIndex + 1;
        20:                             dataGrid.NextCellToEdit();
        21:                         }
        22:                         else // Normal navigation
        23:                         {
        24:                             dataGrid.NextCellToEdit();
        25:                         }
        26:                     }
        27:                     break;
        28:              default:
        29:                     break;
        30: }

      clip_image001[4]

       

      2. 最后一行最后一列,Tab/Enter自動增加新行

          能捕捉到Tab/Enter后,處理就比較簡單了;只需判斷時候在最后一行、最后一列,如果是,則調(diào)用上一篇文章中的增加新行方法:

         1: if (dataGrid.IsLastRow() & dataGrid.IsLastCell())
         2: {
         3:     dataGrid.AddEntity<T>();
         4: }

       

      3. 增加新行后,自動跳轉(zhuǎn)到新增行的第一列

          可以嘗試在后臺代碼中,將DataGrid聚焦在新增行的第一列上:

         1: dataGrid.SelectedItem = entity;
         2: dataGrid.CurrentColumn = dataGrid.Columns[0];
         3: dataGrid.NextCellToEdit();

          但是在實際使用過程中,可能會遇到如下異常:

      image

          這是因為,新增加的行,可能(有時能成功,有時可能失敗)還沒有來得及在UI顯示出來,如果在這時設(shè)置SelectedItem/CurrentColumn,并調(diào)用ScrollIntoView,就會出現(xiàn)上面的異常。一種代替思路,就是用一個計時器來進行處理,如果執(zhí)行失敗,則下次接著執(zhí)行,直到成功為止:

         1: public static void ScrolToFirstColumn(this DataGrid dataGrid, object entity)
         2: {
         3:     DispatcherTimer timer = new DispatcherTimer();
         4:     timer.Interval = TimeSpan.FromTicks(100);
         5:     object sucess = false;
         6:     timer.Tick += (o, e) =>
         7:     {
         8:         if (!(bool)sucess)
         9:         {
        10:             dataGrid.SelectedItem = entity;
        11:             dataGrid.CurrentColumn = dataGrid.Columns[0];
        12:             dataGrid.NextCellToEdit();
        13:             sucess = true;
        14:             timer.Stop(); //執(zhí)行完畢后,就不再執(zhí)行。
        15:         }
        16:     };
        17:     timer.Start();
        18: }

       

      4. 刪除行后,自動選中上一行

         默認情況下,行被刪除行后,DataGrid沒有選中任何行。如果想連續(xù)刪除、或者用Up/Down/Left/Right跳轉(zhuǎn)的話,就需要每次用鼠標點一下,著實不方便。于是提供了此功能:

         1: public static void DeleteCurrentRow(this DataGrid dataGrid)
         2: {
         3:     object entity = dataGrid.SelectedItem;
         4:     IList dataSource = dataGrid.ItemsSource as IList;
         5:     if (entity == null || dataSource == null || dataSource.Count == 0)
         6:     {
         7:         return;
         8:     }
         9:  
        10:     int selectedIndex = dataGrid.SelectedIndex; //刪除前,記錄當(dāng)前行的位置
        11:     if (ExtenderInfo[dataGrid].Deleteable)
        12:     {
        13:         dataSource.Remove(entity);
        14:         dataGrid.SelectedIndex = selectedIndex - 1;//刪除后,重置當(dāng)前行
        15:     }
        16:     dataGrid.BeginEdit();
        17:     ExtenderInfo[dataGrid].RaiseRowChangedEvent(dataGrid,
        18:         new EntityChangedEventArgs() { ChangedEntities = new List<object> { entity }, Type = "Delete" });
        19: }

       

      5. Up/Down/Left/Right自動編輯

          上一篇文章中,通過在DataGrid的KeyDown事件中,見按鍵記錄到DataGrid.Tag中,然后進入編輯狀態(tài)時再賦值給單元格中的文本框(TextBox),來實現(xiàn)即時編輯功能。但在使用的時候,發(fā)現(xiàn)如果使用中文輸入法、或者列使用的是自定義模板列(不是TextBox),就會遇到問題:
          如果是中文輸入法+默認的TextBox:DataGrid會將第一個字符賦給TextBox,這樣就多出一個字符,每次得多按一次BackSpace鍵。
          如果是使用自定義模板列,而不是TextBox,就會丟失第一次字符按鍵。

          一種替代的思路,就是在捕捉Up/Down/Left/Right后,讓DataGrid立即進入編輯狀態(tài)。如上面第1點所述,還是要在KeyUp事件中進行處理。

       

       

       

      6. 不給代碼怎馬叫給力

      happyhippy.cnblogs.com.BatchInput.rar

      posted on 2011-01-12 20:33  Silent Void  閱讀(3066)  評論(12)    收藏  舉報

      主站蜘蛛池模板: 内射囯产旡码丰满少妇| 欧美黑人性暴力猛交在线视频| 中文字幕亚洲人妻一区| 亚洲av高清一区二区三| 国产av一区二区三区精品| 久久国产精品精品国产色| 人妻互换一二三区激情视频 | 2019亚洲午夜无码天堂| 日本熟妇大乳| 天天干天天干| 国产精品麻豆中文字幕| 武功县| 中文字幕亚洲综合久久蜜桃| 国语自产精品视频在线看| 丰满少妇呻吟高潮经历| 一区二区三区国产亚洲网站| 国内自拍视频一区二区三区| 国产91精品丝袜美腿在线| 无码AV无码免费一区二区 | 深夜在线观看免费av| 中文字幕乱码视频32| 人人妻碰人人免费| 亚洲欧美日韩成人综合一区| 黔南| 久久精品国产亚洲av久| 亚洲偷偷自拍码高清视频| 在线免费观看视频1区| 国产婷婷综合在线视频中文| 四虎成人高清永久免费看| 国产精品一区二区国产主播| 亚洲色欲色欱WWW在线| 国产激情一区二区三区成人 | 久久久无码精品午夜| 日韩人妻无码精品无码中文字幕| 久久一日本道色综合久久| 2021国产成人精品久久| 湖南省| 熟女精品视频一区二区三区| 免费午夜无码片在线观看影院| 精品少妇无码一区二区三批| 中文字幕在线精品国产|