Получить поле со списком, в котором находится элемент со списком

#wpf #combobox

#wpf #поле со списком

Вопрос:

Мне нужно найти поле со списком, в котором находится элемент со списком.

В codebehind я перехватываю событие при нажатии на элемент со списком, но я не знаю, к какому из нескольких полей со списком относится конкретный элемент со списком. Как мне найти поле со списком?

Обычно вы можете использовать LogicalTreeHelper.getParent() и перейдите вверх по логическому дереву из элемента со списком, чтобы найти поле со списком. Но это работает только в том случае, если элементы со списком добавляются в поле со списком вручную, а не когда элементы применяются к полю со списком с привязкой к данным. При использовании привязки данных элементы со списком не имеют поля со списком в качестве логического родителя (я не понимаю, почему).

Есть идеи?

Подробная информация:

Ниже приведен некоторый код, восстанавливающий мою проблему (не мой фактический код). Если бы я перешел от привязки данных элементов ComboBox к их настройке вручную (в XAML), переменной «ComboBox» было бы присвоено правильное поле со списком. Теперь поле со списком имеет только значение 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);
}
  

Ответ №1:

Вероятно, это то, что вы ищете:

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

Мне нравится, насколько описательно это название метода.


Кстати, есть несколько других полезных методов, которые можно найти в свойстве ItemsControl.ItemContainerGenerator , которые позволяют вам получить контейнер, связанный с шаблонными данными, и наоборот.

С другой стороны, обычно вам не следует использовать ни один из них и вместо этого фактически использовать привязку к данным.

Комментарии:

1. Отлично! Как раз то, что мне было нужно! Спасибо H.B.

2. С помощью этого метода я смог убить чудовище со списком! Большое спасибо!