#wpf
#wpf
Вопрос:
У меня есть изображение, отображаемое в DataTemplate. Я хочу изменить стиль DataTemplate, который окружает мое изображение при нажатии на изображение.
Раньше оно было вложено непосредственно в stackpanel, как показано ниже, поэтому я мог легко получить родительскую stackpanel, выполнив следующее.
StackPanel sp = img.Parent as StackPanel;
<StackPanel Name="uxSessionImageItem" Style="{DynamicResource RotatorItemTemplateUnselectedStyle}" Loaded="uxSessionImageItem_Loaded" >
<TextBlock Name="uxLabel" Width="150" Text="{Binding SessionImageID}" Foreground="White" VerticalAlignment="Center"/>
<Image MouseDown="ImagePanel_MouseDown" Name="uxImage" Style="{DynamicResource ItemTemplateImageStyle}" Source="{Binding ThumbPath}"/>
</StackPanel>
Мне пришлось добавить еще одну панель стека и границу между изображением и панелью стека, которую мне нужно найти. Какой синтаксис мне нужен, чтобы найти не границу, которая теперь является моим родительским элементом, и не stackpanel, которая является родительской для границы, а stackpanel над ней?
<StackPanel Name="uxSessionImageItem" Style="{DynamicResource RotatorItemTemplateUnselectedStyle}" Loaded="uxSessionImageItem_Loaded" >
<TextBlock Name="uxLabel" Width="150" Text="{Binding SessionImageID}" VerticalAlignment="Center" Style="{DynamicResource ItemTemplateImageNumberStyle}"/>
<StackPanel Name="uxSessionImageWrapper" Style="{DynamicResource RotatorItemImageWrapperStyle}" >
<Border Name="uxImageBorder" Style="{DynamicResource ItemTemplateImageBorderStyle}">
<Image MouseDown="ImagePanel_MouseDown" Name="uxImage" Style="{DynamicResource ItemTemplateImageStyle}" Source="{Binding ThumbPath}"/>
</Border>
</StackPanel>
</StackPanel>
Ответ №1:
Кодированный ответ хорош, но мне не нравится тот факт, что код в этой статье использует рекурсию для выполнения этой простой задачи, поэтому вот модифицированная версия, которая, возможно, может избежать переполнения стека (не уверен, что WPF может быть настолько вложенным, но стоит ли рисковать?)
public static T FindParentOfType<T>(this DependencyObject child) where T : DependencyObject
{
DependencyObject parentDepObj = child;
do
{
parentDepObj = VisualTreeHelper.GetParent(parentDepObj);
T parent = parentDepObj as T;
if (parent != null) return parent;
}
while (parentDepObj != null);
return null;
}
Ответ №2:
Вы можете использовать VisualTreeHelper для перемещения вверх или вниз по визуальному дереву. Свойство Parent является логическим родительским элементом, который отличается. Это объясняется более подробно здесь.
Вы можете использовать этот код Linq To Visual Tree, чтобы использовать инструкции типа Linq для обхода визуального дерева, но в конечном итоге это использует класс VisualTreeHelper. Или вы можете создавать методы расширения, подобные этому, чтобы упростить поиск предков (не обязательно прямых родителей).
Ответ №3:
Я действительно не понимаю, что, если вы уже назвали свою StackPanel uxSessionImageItem
, почему бы вам не использовать его для ссылки на него в вашем коде?
Комментарии:
1. Если это находится в DataTemplate, то вы не можете получить доступ по имени с помощью такого кода. Для каждого использования DataTemplate может быть несколько экземпляров StackPanel.
2. Спасибо, пропустил часть DataTemplate.
Ответ №4:
img.Parent.Parent.Parent
является внешней панелью стека.
(Тот факт, что в StackPanel есть несколько элементов на одном уровне, является проблемой только при переходе вниз по VisualTree, вверх всегда легко, поскольку у каждого элемента может быть только один родительский элемент.)
Редактировать: Как указал CodeNaked Parent
, используется логическое дерево, это не должно быть проблемой, если все, что вы ищете, — это относительная ссылка.