wpf中组合框选择的奇怪行为

时间:2014-04-28 11:02:01

标签: c# wpf wpf-controls visual-tree visualtreehelper

我正在开发一个应用程序,其中我们有一个主窗口,在不同的dock选项中有这么多的子窗口。因此,一个扩展坞具有一个属性面板窗口,允许用户修改所选实体的属性,并且在更改值后,用户必须单击控件底部的“应用”按钮。所以,我愿意提供某种功能,如果用户修改了某些值而不是单击“应用”,如果用户单击除了属性面板视图的子控件之外的其他位置,则应该向用户发出“请先点击”的消息申请保存您的更改“。为此,我在MainWindow的鼠标按下事件上编写了以下代码。

private void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
{        
    var hitObject = this.InputHitTest(e.GetPosition(this)) as  DependencyObject;
    if (hitObject.FindVisualAncestor<PropertyPanelUserControl>() == null)
    {
        MessageBox.Show("Please save your changes");
    }        
}

所以,逻辑就是这样,在主窗口的鼠标按下时,获取命中对象并检查它是否是属性面板控件的子控件,然后它将PropertyPanelUserControl作为其父级和其他控件而不是它们的一部分或者ChildPanelUserControl的子控件,然后会提示用户单击apply。

上面的代码工作非常棒...但是我发现了一个奇怪的问题,我在属性面板中有一个组合框,其中包含1到10个条目。因此,当用户尝试将值更改为其他值时,那么用户将不会被给出该消息,因为到目前为止用户正在单击属性面板控件,当我在组合框中选择项目后检查鼠标按下事件中的命中对象时,则命中对象是chromeButton或组合框。但是当我选择最后一个项目10时,然后命中对象作为具有属性面板控件的边框。

<Border><View:PropertyPanelControl/></Border>及以上检查失败,因为border没有祖先作为属性面板控件,而border是控件的祖先。因此,即使只更改组合框值,用户也会收到消息, 此外,我已经确定我点击组合框项目不在外面,所以,现在问题是为什么wpf以这种奇怪的方式表现以及如何解决这个问题。

1 个答案:

答案 0 :(得分:1)

你的第一个问题很奇怪:

  

为什么wpf以这种奇怪的方式表现

你描述了发生了什么,这对我来说似乎完全正常。用户点击ComboBoxItemHitTest告诉您已点击ComboBoxItem ...我没有看到任何问题。

  

如何解决此问题

现在我想象一下,如果你已经拍摄了ComboBoxItem并沿着视觉树向上移动,那么你就会找到你的PropertyPanelUserControl控件。尝试这样的事情:

HitTestResult result = VisualTreeHelper.HitTest(this, e.GetPosition(this));
UIElement uIElement = result.VisualHit.GetParentOfType<PropertyPanelUserControl>();
if (uIElement != null)
{
    // the user clicked inside the PropertyPanelUserControl control
}

GetParentOfType方法是我创建的一种扩展方法,它在可视化树中查找特定类型的第一个元素...如果您愿意,可以轻松地将其重构为常规方法:

public static T GetParentOfType<T>(this DependencyObject element) where T : DependencyObject
{
    Type type = typeof(T);
    if (element == null) return null;
    DependencyObject parent = VisualTreeHelper.GetParent(element);
    if (parent == null && ((FrameworkElement)element).Parent is DependencyObject) parent = ((FrameworkElement)element).Parent;
    if (parent == null) return null;
    else if (parent.GetType() == type || parent.GetType().IsSubclassOf(type)) return parent as T;
    return GetParentOfType<T>(parent);
}
相关问题