Yogesh
Yogesh

Reputation: 3076

Strange behavior by combo box selection in wpf

I am working on an application, wherein we have a main window which is having so many child windows in different dock option. So, one dock is having a property panel window which allows a user to modify property of selected entity and after changing the value user has to click on apply button which is available in the bottom of the control. So, I was willing to have some sort of functionality that if user has modified some value and instead of clicking on apply, if user click somewhere else apart from property panel view's sub control's, then user should be given a message that "Please first click apply to save your changes". for this what I did, I wrote the following piece of code on the mouse down event of 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");
    }        
}

So, the logic is this, on mouse down of main window, get the hit object and check that if it is a child control of property panel control, then it will have PropertyPanelUserControl as its parent and other control which are not part or child control of PropertyPanelUserControl, then user will be prompted to click on the apply.

The above piece of code was working superb...but I figured out a strange issue, I had a combo box in the property panel which had entries from 1 to 10. So, when user tries to change value to other value, then user will not be given that message as, so far user is clicking on the property panel control and when i check the hit object in the mouse down event after selecting an item in the combo box, then hit object was the chromeButton or combo box. but When I selected the last item 10, then hit object comes as border which has the property panel control.

<Border><View:PropertyPanelControl/></Border> and above check fails, as border doesn't have ancestor as property panel control, rather border is the ancestor of the control. So, user gets a message even while changing only combo box value, Moreover, I have made sure that I was clicking on the combo box item not outside, So, now question is this why wpf is behaving in this weird way and how to address this issue.

Upvotes: 0

Views: 608

Answers (1)

Sheridan
Sheridan

Reputation: 69979

Your first question is strange:

why wpf is behaving in this weird way

You described what happens and it all seems totally normal to me. The user clicks on a ComboBoxItem and your HitTest tells you that you've clicked on a ComboBoxItem... I don't see any problem there.

how to address this issue

Now I imagine that if you had taken that ComboBoxItem and worked your way up the visual tree, then you would have found your PropertyPanelUserControl control. Try something like this instead:

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

The GetParentOfType method is an Extension method that I created that walks up the visual tree looking for the first element of a particular type... you can easily refactor it into a normal method if you prefer:

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);
}

Upvotes: 1

Related Questions