Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the ComboBox that a ComboBoxItem resides in

Tags:

combobox

wpf

I need to find the ComboBox that a ComboBoxItem resides in.

In codebehind I catch an event when a ComboBoxItem is clicked, but I don't know which one of several ComboBoxes that the specific ComboBoxItem belongs to. How do I find the ComboBox?

Normally you can use LogicalTreeHelper.GetParent() and traverse up the logical tree from the ComboBoxItem to find the ComboBox. But this only works if the ComboBoxItems are added to the ComboBox manually, not when the items are applied to the ComboBox with databinding. When using databinding, the ComboBoxItems do not have the ComboBox as a logical parent (I don't understand why).

Any ideas?

More info:

Below is some code reconstructing my problem (not my actual code). If I would change from databinding the ComboBoxItems to setting them manually (in the XAML), the variable "comboBox" would be set to the correct ComboBox. Now comboBox is only null.

XAML:

<ComboBox Name="MyComboBox" ItemsSource="{Binding Path=ComboBoxItems, Mode=OneTime}" />

CodeBehind:

public MainWindow()
{
    InitializeComponent();

    MyComboBox.DataContext = this;
    this.PreviewMouseDown += MainWindow_MouseDown;
}

public BindingList<string> ComboBoxItems
{
    get
    {
        BindingList<string> items = new BindingList<string>();
        items.Add("Item E");
        items.Add("Item F");
        items.Add("Item G");
        items.Add("Item H");
        return items;
    }
}

private void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
{
    DependencyObject clickedObject = e.OriginalSource as DependencyObject;
    ComboBoxItem comboBoxItem = FindVisualParent<ComboBoxItem>(clickedObject);
    if (comboBoxItem != null)
    {
        ComboBox comboBox = FindLogicalParent<ComboBox>(comboBoxItem);
    }
}

//Tries to find visual parent of the specified type.
private static T FindVisualParent<T>(DependencyObject childElement) where T : DependencyObject
{
    DependencyObject parent = VisualTreeHelper.GetParent(childElement);
    T parentAsT = parent as T;
    if (parent == null)
    {
        return null;
    }
    else if (parentAsT != null)
    {
        return parentAsT;
    }
    return FindVisualParent<T>(parent);
}

//Tries to find logical parent of the specified type.
private static T FindLogicalParent<T>(DependencyObject childElement) where T : DependencyObject
{
    DependencyObject parent = LogicalTreeHelper.GetParent(childElement);
    T parentAsT = parent as T;
    if (parent == null)
    {
        return null;
    }
    else if(parentAsT != null)
    {
        return parentAsT;
    }
    return FindLogicalParent<T>(parent);
}
like image 397
haagel Avatar asked Dec 01 '22 02:12

haagel


1 Answers

This is probably what you are looking for:

var comboBox = ItemsControl.ItemsControlFromItemContainer(comboBoxItem) as ComboBox;

I love how descriptive that method-name is.


On a side-note, there are some other useful methods which can be found in the property ItemsControl.ItemContainerGenerator which let you get the container associated with the templated data and vice versa.

On another side-note, you usually should not be using any of them and instead use data-binding actually.

like image 149
H.B. Avatar answered Dec 05 '22 08:12

H.B.