RadPane在FilterRow模式下切换过滤运算符时自动关闭的修复咨询
问题
我在RadDocking的RadPaneGroup中放置了一个RadPane,代码如下:
<telerik:RadPane x:Name="MyPinTab" Header="PinTab" IsPinned="False" CanFloat="False" CanUserClose="False" IsTabStop="False"> <views:MyPinTabView Tag="{Binding DataContext.MyPinTabViewModel, RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, NotifyOnTargetUpdated=True}" TargetUpdated="MyPinTab_OnUpdated" /> </telerik:RadPane>
该RadPane内包含一个设置了FilteringMode="FilterRow"的RadTreeListView。当我在UI中尝试切换过滤运算符时,RadPane会自动关闭。
我判断这是RadPane的逻辑问题:当RadDocking接收到鼠标点击时,会检查点击是否在其面板集合内,未固定的RadPane失去焦点(点击过滤运算符弹窗时会触发失焦),就会尝试关闭它。我曾尝试捕获该弹窗的鼠标点击事件并设置event.Handled = true,但这会同时阻止过滤运算符的切换操作。我想找RadDocking关闭RadPane时触发的事件,通过鼠标坐标和RadPane的宽高来取消关闭,但未找到相关事件。
解决方案
方法1:用RadPane的PreviewClose事件拦截不必要的关闭
RadPane自带PreviewClose事件,能在关闭前判断点击来源,从而取消操作:
- 给RadPane绑定事件:
<telerik:RadPane x:Name="MyPinTab" Header="PinTab" IsPinned="False" CanFloat="False" CanUserClose="False" IsTabStop="False" PreviewClose="MyPinTab_PreviewClose"> <!-- 内部视图内容 --> </telerik:RadPane>
- 后台实现事件逻辑:
private void MyPinTab_PreviewClose(object sender, Telerik.Windows.Controls.RadRoutedEventArgs e) { // 获取鼠标当前指向的元素 var targetElement = Mouse.DirectlyOver as FrameworkElement; if (targetElement == null) return; // 判断元素是否属于过滤弹窗相关控件 var filterPopup = targetElement.FindVisualParent<Telerik.Windows.Controls.GridView.FilterDropDownPopup>(); var filterOperatorBox = targetElement.FindVisualParent<Telerik.Windows.Controls.RadComboBox>(); if (filterPopup != null || (filterOperatorBox != null && filterOperatorBox.Name.Contains("FilterOperator"))) { // 拦截关闭操作 e.Handled = true; } }
需要自己实现一个视觉树查找的扩展方法:
public static T FindVisualParent<T>(this DependencyObject child) where T : DependencyObject { var parentObj = VisualTreeHelper.GetParent(child); if (parentObj == null) return null; if (parentObj is T parent) return parent; return parentObj.FindVisualParent<T>(); }
方法2:自定义RadDocking重写点击逻辑
如果方法1不够稳定,可以直接修改RadDocking处理外部点击的逻辑:
- 创建自定义RadDocking类:
public class CustomRadDocking : RadDocking { protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) { var clickElement = e.OriginalSource as FrameworkElement; // 检查点击是否在过滤弹窗内 bool isFilterPopupClick = clickElement?.FindVisualParent<Telerik.Windows.Controls.GridView.FilterDropDownPopup>() != null; if (isFilterPopupClick) { // 跳过默认的外部点击关闭逻辑 return; } base.OnPreviewMouseLeftButtonDown(e); } }
- XAML中替换原RadDocking为自定义的版本:
<local:CustomRadDocking> <!-- 你的RadPaneGroup和RadPane结构 --> </local:CustomRadDocking>
方法3:临时固定RadPane
在过滤弹窗打开时临时将RadPane设为固定,关闭后恢复:
- 给RadTreeListView绑定下拉框的打开/关闭事件:
// 假设你的RadTreeListView名为treeListView treeListView.AddHandler(RadComboBox.DropDownOpenedEvent, new RoutedEventHandler(FilterDropDown_Opened), true); treeListView.AddHandler(RadComboBox.DropDownClosedEvent, new RoutedEventHandler(FilterDropDown_Closed), true);
- 实现事件处理:
private void FilterDropDown_Opened(object sender, RoutedEventArgs e) { MyPinTab.IsPinned = true; } private void FilterDropDown_Closed(object sender, RoutedEventArgs e) { MyPinTab.IsPinned = false; }
这样在切换过滤运算符时,RadPane处于固定状态,不会因为失焦被关闭,弹窗关闭后自动恢复原状态。
内容的提问来源于stack exchange,提问作者kozurap
相关产品推荐
相关产品推荐

