0

私は、さまざまなドックオプションに非常に多くの子ウィンドウを持つメインウィンドウがあるアプリケーションに取り組んでいます。したがって、1 つのドックには、ユーザーが選択したエンティティのプロパティを変更できるプロパティ パネル ウィンドウがあり、値を変更した後、ユーザーはコントロールの下部にある適用ボタンをクリックする必要があります。したがって、ユーザーが何らかの値を変更し、適用をクリックする代わりに、ユーザーがプロパティ パネル ビューのサブ コントロール以外の場所をクリックすると、「最初にクリックしてください」というメッセージがユーザーに表示されるような、ある種の機能を用意したいと考えていました。適用して変更を保存します。」このために、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はこの奇妙な振る舞いをしているのですか

あなたは何が起こるかを説明しましたが、それはすべて私には完全に正常に思えます. ユーザーが a をクリックするComboBoxItemと、あなたが aHitTestをクリックしたことが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 に答える