/// <summary> /// 尝试焦点移动到目标元素 /// </summary> /// <param name="target"></param> public void FlowTo(ComponentBase target) { //如果目标不在列表中,则不处理 var targetIndex = FlowList.IndexOf(target); if (targetIndex < 0) { return; } //若当前要素为空,则重置到顶点 var currentIndex = FlowList.IndexOf(CurrentElement); if (currentIndex < 0) { MoveFocusHost(FlowNavigation.Top); return; } //开始组织焦点移动 if (currentIndex > targetIndex) { //尝试往目标进行转移 SetFlow(target); } else if (currentIndex < targetIndex) { //检查是否允许跳过控制 if (GetCanSkipFlow(target)) { SetFlow(target); } else { while (true) { if (!MoveFocusHost(FlowNavigation.Forward)) { break; } var index = FlowList.IndexOf(CurrentElement); if (targetIndex <= index) { break; } } } } }
/// <summary> /// 鼠标操作 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnPreviewMouseDown(object sender, RoutedEventArgs e) { if (_target != sender) { return; } e.Handled = true; //如果外部已经禁用用户输入或内部正在处理,终结事件并返回 if (!CanAcceptUserInput) { return; } #region 获取点击的元素 var source = e.OriginalSource as FrameworkElement; var clickedElement = FlowList.FirstOrDefault(x => x == source || x.IsAncestorOf(source)); if (clickedElement == null) { if (source != null) { //若点击元素为滚动条内部,则需要支持继续路由 e.Handled = source.FindVisualTreeAncestor(x => x is ScrollBar) == null; //触发路由事件FlowMouseDownEvent source.RaiseEvent(new RoutedEventArgs { RoutedEvent = FlowMouseDownEvent }); } return; } #endregion //进行移动操作 FlowTo(clickedElement); //如果没移动或移动成功,则标志鼠标事件未处理 if (CurrentElement == clickedElement) { e.Handled = false; } return; }
void _target_Ready(object sender, EventArgs e) { _target.Loaded -= _target_Ready; //检查上层是否存在开启焦点的控件,防止嵌套 if (_target.FindVisualTreeAncestor(x => FlowManager.GetIsFlowScope(x)) != null) { throw new NotSupportedException("上层已经开启焦点流程控制,系统不支持嵌套使用!目标:" + _target); } //如果区域的背景为空,会导致鼠标点击事件的穿透,影响控制效果 if (_target.GetValue(Control.BackgroundProperty) == null) { _target.SetValue(Control.BackgroundProperty, Brushes.Transparent); } FlowList = FlowList.Create(_target); //foreach (var item in FlowList) //{ // SetManagerInstance(item, this); //} //如果已经设置好焦点控件,则无须重置 if (CurrentElement == null) { this.MoveFocusHost(FlowNavigation.Top); } }
/// <summary> /// 按照参数指定的方向进行一次移动 /// </summary> public bool MoveFocusHost(FlowNavigation navigation) { //当前焦点元素的位置 var currentIndex = FlowList.IndexOf(CurrentElement); switch (navigation) { case FlowNavigation.Top: //清除当前焦点元素,然后重新往下移动 CurrentElement = null; return(MoveFocusHost(FlowNavigation.Forward)); case FlowNavigation.Backward: //若当前元素不存在,则移动到顶端 if (currentIndex < 0) { return(MoveFocusHost(FlowNavigation.Top)); } //从当前位置倒序查找回退位置,若当前位置为0,则不移动 while (currentIndex > 0) { currentIndex--; var target = FlowList[currentIndex]; if (IsFlowable(target)) { //位置合适,进行移动,此时触发Enter系列事件 if (!RaiseEnterEvent(target)) { return(false); } CurrentElement = target; return(true); } } FlowToTop?.Invoke(this, new RoutedEventArgs()); return(false); case FlowNavigation.Forward: if (CurrentElement != null && !RaiseLeaveEvent(CurrentElement)) { return(false); } //沿着流程列表往下找焦点控件 while (currentIndex + 1 < FlowList.Count) { currentIndex++; var target = FlowList[currentIndex]; if (IsFlowable(target)) { if (!RaiseEnterEvent(target)) { return(false); } CurrentElement = target; return(true); } } //触发移动到最后的事件 FlowToEnd?.Invoke(this, new RoutedEventArgs()); return(false); default: return(false); } }