0

我正在开发一个应用程序,其中我们有一个主窗口,它在不同的停靠选项中有很多子窗口。因此,一个停靠栏有一个属性面板窗口,允许用户修改所选实体的属性,并且在更改值后,用户必须单击控件底部的应用按钮。所以,我愿意拥有某种功能,如果用户修改了一些值而不是点击应用,如果用户点击属性面板视图的子控件之外的其他地方,那么用户应该收到一条消息“请先点击申请以保存您的更改”。为此,我在 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 作为其父控件,而其他控件不是部分或子控件PropertyPanelUserControl,然后会提示用户单击应用。

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

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

4

1 回答 1

1

你的第一个问题很奇怪:

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

你描述了发生的事情,这对我来说似乎完全正常。用户单击 aComboBoxItem并且您HitTest告诉您您已单击 a 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);
}
于 2014-04-28T12:56:57.307 回答