#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. С помощью этого метода я смог убить чудовище со списком! Большое спасибо!