In questo momento è necessario fare doppio clic o fare clic sull'icona +. C'è un modo per farlo in modo che se un utente fa clic in qualsiasi punto del nodo si espande?Come espandere WPF TreeView con un solo clic dell'articolo
risposta
Forse non è la soluzione più elegante, ma questo funziona:
static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
while (source != null && source.GetType() != typeof(T))
source = VisualTreeHelper.GetParent(source);
return source;
}
poi nel TreeViewItem.Selected Handler:
private void Treeview_Selected(object sender, RoutedEventArgs e)
{
var treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
if (treeViewItem != null) treeViewItem.IsExpanded = true;
}
la magia VisualUpwardSearch è preso da qui: Select TreeView Node on right click before displaying ContextMenu
Cordiali saluti
Ho avuto lo stesso problema e f buona soluzione grazie allo another StackOverflow post.
Nel elemento TreeView del control.xaml, è possibile collegare direttamente nel caso selezionati della TreeViewItem:
<TreeView ItemsSource="{StaticResource Array}" TreeViewItem.Selected="TreeViewItem_Selected"/>
Poi nel codice control.xaml.cs alle spalle, si può afferrare quella selezionata TreeViewItem dai RoutedEventArgs e impostarlo su 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;
}
Bello e pulito. Spero che questo aiuti qualcuno!
+1 per il codice XAML. Risolto il problema perfettamente. (Così fa la risposta accettata (che ho anche svalutato)). –
Secondo me, questo è il metodo migliore! C'è solo un difetto: quando si tenta di comprimere un elemento non selezionato facendo clic sull'icona di compressione, viene selezionato e il gestore eventi impedisce di comprimerlo. Devi incapsulare il gestore di eventi in 'if (! E.Handled) {...}' e impostare 'e.Handled = true;' subito dopo aver attivato la proprietà 'IsExpanded'. – kroimon
Un altro problema è che quando si fa clic su una vista ad albero già selezionata, essa non collassa o si espande. –
La soluzione accettata ha un comportamento strano quando si naviga con la tastiera e non collassa l'elemento quando è già selezionato. In alternativa, è sufficiente derivare una nuova classe da TreeViewItem e sovrascrivere il metodo MouseLeftButtonDown. È inoltre necessario impostare TreeView.ItemsSource su una raccolta della nuova classe 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);
}
Ho avuto lo stesso problema e l'ho fatto con la funzione Stylenality in modo che non sia necessario gestire l'evento.
ho definito uno stile per il 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>
La parte importante è quello definito la casella di controllo nella ControlTemplate e il legame con esso. Quando il CheckBox è selezionato, l'oggetto sarà espanso con un solo clic.
<CheckBox Style="{StaticResource TreeViewItemCB}" IsChecked="{Binding Path=IsExpanded,Mode=OneWayToSource,RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press">
questo è lo stile per la casella di controllo in modo che si allunga e non visualizza la scatola con la corsa.
<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>
Soluzione brillante! – l33t
<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);
}
Ecco la risposta, goditela
Risposta da: Ali Rahimy
Un altro approch sarebbe quella di utilizzare propperties allegati.
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;
}
}
E quindi è possibile utilizzarlo in questo modo.
<TreeView controls:VirtualOneClickExpandButtonBehavior.Enabled="true" ItemsSource="{Binding HierarchicalModel}"/>
Questo è un buon approc se si utilizza il modello MVVM perché non è necessario il codebehind.
E Thaks per Markust per il suo VisualUpwardSearch (fonte DependencyObject)
Urtando una risposta molto vecchio. Sto provando questa soluzione ma ho un'etichetta con AccessText e ottengo l'elemento System.Windows.Documents.Run come OriginalSource. Questo non è un elemento visivo o visivo3d e quindi GetParent genera un'eccezione. Qualche idea su come procedere? –