Теперь вам нужно дважды щелкнуть или щелкнуть значок+. Есть ли способ сделать это, если пользователь нажимает в любом месте на node, он расширяется?
Как расширить WPF TreeView на один клик элемента
Ответ 1
Возможно, это не самое элегантное решение, но это работает:
static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
while (source != null && source.GetType() != typeof(T))
source = VisualTreeHelper.GetParent(source);
return source;
}
то в обработчике TreeViewItem.Selected:
private void Treeview_Selected(object sender, RoutedEventArgs e)
{
var treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
if (treeViewItem != null) treeViewItem.IsExpanded = true;
}
Маска VisualUpwardSearch берется здесь: Выберите TreeView Node правой кнопкой мыши перед отображением ContextMenu
Привет
Ответ 2
У меня была такая же проблема, и я нашел хорошее решение благодаря fooobar.com/questions/425777/....
В элементе tree.xaml TreeView вы можете напрямую подключиться к событию TreeViewItem Selected:
<TreeView ItemsSource="{StaticResource Array}" TreeViewItem.Selected="TreeViewItem_Selected"/>
Затем в вашем файле control.xaml.cs позади вы можете захватить выбранный TreeViewItem из RoutedEventArgs и установить его в IsExpanded:
private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
TreeViewItem tvi = e.OriginalSource as TreeViewItem;
if (tvi == null || e.Handled) return;
tvi.IsExpanded = !tvi.IsExpanded;
e.Handled = true;
}
Приятный и чистый. Надеюсь, это поможет кому-то!
Ответ 3
У меня была та же проблема, и я сделал это с функциональной функцией Style, так что вам не нужно обрабатывать событие.
Я определил стиль для TreeViewItem
<Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}">
<!--<Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<CheckBox Style="{StaticResource TreeViewItemCB}" IsChecked="{Binding Path=IsExpanded,Mode=OneWayToSource,RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press">
<Grid Background="{StaticResource TreeViewItemBackground}" Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Name="Bd">
<ContentPresenter x:Name="PART_Header" ContentSource="Header"/>
</Border>
<ItemsPresenter x:Name="ItemsHost" Grid.Row="1"/>
</Grid>
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Важной частью является определение checkBox в ControlTemplate и привязка к нему. Когда CheckBox установлен, элемент будет расширен одним щелчком мыши.
<CheckBox Style="{StaticResource TreeViewItemCB}" IsChecked="{Binding Path=IsExpanded,Mode=OneWayToSource,RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press">
это стиль для checkbox, так что он растягивается и не отображает окно с штрихом.
<Style x:Key="TreeViewItemCB" TargetType="CheckBox" BasedOn="{StaticResource baseStyle}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="Background" Value="Transparent"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<ContentPresenter VerticalAlignment="Stretch" HorizontalAlignment="Stretch" RecognizesAccessKey="True"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Ответ 4
@BJennings дал отличный ответ. Однако, если вы хотите развернуть или свернуть уже выбранный элемент, это не сработает. Чтобы улучшить это, вы можете просто добавить: tvi.IsSelected = false; (если вам все равно, находится ли элемент в выбранном состоянии.)
Итак, все коды выглядят так:
private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
TreeViewItem tvi = e.OriginalSource as TreeViewItem;
if (tvi == null || e.Handled) return;
tvi.IsExpanded = !tvi.IsExpanded;
tvi.IsSelected = false;
e.Handled = true;
}
Ответ 5
Принятое решение имеет странное поведение при навигации с помощью клавиатуры и не сбрасывает элемент, когда он уже выбран. Кроме того, просто выведите новый класс из TreeViewItem и переопределите метод MouseLeftButtonDown. Вам также необходимо установить TreeView.ItemsSource в коллекцию нового класса TreeViewItem.
protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
if (!e.Handled && base.IsEnabled)
{
this.IsExpanded = !this.IsExpanded;
e.Handled = true;
}
base.OnMouseLeftButtonDown(e);
}
Ответ 6
Другой подход - использовать Attached propperties.
public class VirtualOneClickExpandButtonBehavior : DependencyObject
{
public static bool GetEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(EnabledProperty);
}
public static void SetEnabled(DependencyObject obj, bool value)
{
obj.SetValue(EnabledProperty, value);
}
public static readonly DependencyProperty EnabledProperty =
DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(VirtualOneClickExpandButtonBehavior),
new UIPropertyMetadata(false, EnabledPropertyChangedCallback
));
private static void EnabledPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var treeView = dependencyObject as TreeView;
if (treeView == null) return;
treeView.MouseUp += TreeView_MouseUp;
}
private static void TreeView_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
if (treeViewItem != null) treeViewItem.IsExpanded = !treeViewItem.IsExpanded;
}
static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
while (source != null && source.GetType() != typeof(T))
source = VisualTreeHelper.GetParent(source);
return source;
}
}
И тогда вы можете использовать его вот так.
<TreeView controls:VirtualOneClickExpandButtonBehavior.Enabled="true" ItemsSource="{Binding HierarchicalModel}"/>
Это хороший подход, если вы используете шаблон MVVM, потому что вам не нужен код.
И нападает на Маркуста для его VisualUpwardSearch (источник DependencyObject)
Ответ 7
Основываясь на ответе BJennings, если я хочу поместить функцию private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
в статический класс, как я могу это сделать? Я старался:
xmlns:wpfcommonhelpers="clr-namespace:WPFCommon.Helpers"
<TreeView ItemsSource="{StaticResource Array}" TreeViewItem.Selected="wpfcommonhelpers:TreeViewItemHelper.TreeViewItem_Selected"/>
public static class TreeViewItemHelper
{
public static void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
var tvi = e.OriginalSource as TreeViewItem;
if (tvi == null || e.Handled) return;
tvi.IsExpanded = !tvi.IsExpanded;
tvi.IsSelected = false;
e.Handled = true;
}
}
Но не работает... Есть идеи? Спасибо
Ответ 8
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Cursor" Value="Hand" />
<EventSetter Event="MouseUp" Handler="TreeViewItem_Click"/>
</Style>
</TreeView.ItemContainerStyle>
private void TreeViewItem_Click(object sender, MouseButtonEventArgs e)
{
((TreeViewItem) sender).IsExpanded = !((TreeViewItem) sender).IsExpanded;
Thread.Sleep(700);
}
Вот ответ, Наслаждайся
Ответа на этот вопрос: Ali Rahimy