@@ -245,6 +245,12 @@ public partial class TreeView<TItem> : IModelEqualityComparer<TItem>
245245 [ Parameter ]
246246 public string ? ExpandNodeIcon { get ; set ; }
247247
248+ /// <summary>
249+ /// 获得/设置 是否开启键盘上下键操作 默认 false
250+ /// </summary>
251+ [ Parameter ]
252+ public bool EnableKeyboardArrowUpDown { get ; set ; }
253+
248254 [ CascadingParameter ]
249255 private ContextMenuZone ? ContextMenuZone { get ; set ; }
250256
@@ -283,6 +289,8 @@ public partial class TreeView<TItem> : IModelEqualityComparer<TItem>
283289
284290 private string ? _searchText ;
285291
292+ private string ? EnableKeyboardArrowUpDownString => EnableKeyboardArrowUpDown ? "true" : null ;
293+
286294 /// <summary>
287295 /// <inheritdoc/>
288296 /// </summary>
@@ -346,6 +354,91 @@ protected override async Task OnParametersSetAsync()
346354 }
347355 }
348356
357+ /// <summary>
358+ /// <inheritdoc/>
359+ /// </summary>
360+ /// <returns></returns>
361+ protected override Task InvokeInitAsync ( ) => InvokeVoidAsync ( "init" , Id , Interop , nameof ( TriggerKeyDown ) ) ;
362+
363+ /// <summary>
364+ /// 客户端用户键盘操作处理方法 由 JavaScript 调用
365+ /// </summary>
366+ /// <param name="key"></param>
367+ /// <returns></returns>
368+ [ JSInvokable ]
369+ public async ValueTask TriggerKeyDown ( string key )
370+ {
371+ // 通过 ActiveItem 找到兄弟节点
372+ // 如果兄弟节点没有时,找到父亲节点
373+ if ( ActiveItem != null )
374+ {
375+ await ActiveTreeViewItem ( key , ActiveItem ) ;
376+ StateHasChanged ( ) ;
377+ }
378+ }
379+
380+ private static bool IsExpand ( TreeViewItem < TItem > item ) => item . IsExpand && item . Items . Count > 0 ;
381+
382+ private List < TreeViewItem < TItem > > GetItems ( TreeViewItem < TItem > item ) => item . Parent ? . Items ?? Items ;
383+
384+ private async Task ActiveTreeViewItem ( string key , TreeViewItem < TItem > item )
385+ {
386+ var items = GetItems ( item ) ;
387+ var index = items . IndexOf ( item ) ;
388+
389+ if ( key == "ArrowUp" )
390+ {
391+ index -- ;
392+ if ( index >= 0 )
393+ {
394+ var currentItem = items [ index ] ;
395+ if ( IsExpand ( currentItem ) )
396+ {
397+ await OnClick ( currentItem . Items [ ^ 1 ] ) ;
398+ }
399+ else
400+ {
401+ await OnClick ( currentItem ) ;
402+ }
403+ }
404+ else if ( item . Parent != null )
405+ {
406+ await OnClick ( item . Parent ) ;
407+ }
408+ }
409+ else if ( key == "ArrowDown" )
410+ {
411+ if ( IsExpand ( item ) )
412+ {
413+ await OnClick ( item . Items [ 0 ] ) ;
414+ }
415+ else
416+ {
417+ index ++ ;
418+ if ( index < items . Count )
419+ {
420+ await OnClick ( items [ index ] ) ;
421+ }
422+ else if ( item . Parent != null )
423+ {
424+ await ActiveParentTreeViewItem ( item . Parent ) ;
425+ }
426+ }
427+ }
428+ }
429+
430+ private async Task ActiveParentTreeViewItem ( TreeViewItem < TItem > item )
431+ {
432+ var items = GetItems ( item ) ;
433+ var index = items . IndexOf ( item ) ;
434+
435+ index ++ ;
436+ if ( index < items . Count )
437+ {
438+ await OnClick ( items [ index ] ) ;
439+ }
440+ }
441+
349442 private async Task < bool > OnBeforeStateChangedCallback ( TreeViewItem < TItem > item , CheckboxState state )
350443 {
351444 var ret = true ;
@@ -416,7 +509,7 @@ private async Task OnClick(TreeViewItem<TItem> item)
416509 if ( ShowCheckbox && ClickToggleCheck )
417510 {
418511 item . CheckedState = ToggleCheckState ( item . CheckedState ) ;
419- await OnCheckStateChanged ( item ) ;
512+ await OnCheckStateChanged ( item , false ) ;
420513 }
421514
422515 StateHasChanged ( ) ;
0 commit comments