Treeview Item Loses Selection When Focus Is Lost - wpf

I have noticed this on an application I am working on right now, so I created a simple test app to demonstrate. Below is my a window and the event handler for the treeview items. If you expand either the "One" or "Two" parent nodes, and click one of the children, the child that was selected does not show up as selected after the Focus() method is called on the text box. Instead, selection pops to the parent node. Does anyone have any idea how to overcome this, and have the selection remain with the selected child node? Thanks.
<Window
x:Class="DockingSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
WindowState="Maximized"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TreeView Margin="6">
<TreeViewItem Header="One">
<TreeViewItem Header="One" Selected="TreeViewItem_Selected" />
<TreeViewItem Header="Two" Selected="TreeViewItem_Selected" />
<TreeViewItem Header="Three" Selected="TreeViewItem_Selected" />
</TreeViewItem>
<TreeViewItem Header="Two">
<TreeViewItem Header="One" Selected="TreeViewItem_Selected" />
<TreeViewItem Header="Two" Selected="TreeViewItem_Selected" />
<TreeViewItem Header="Three" Selected="TreeViewItem_Selected" />
</TreeViewItem>
</TreeView>
<TextBox Grid.Column="1" x:Name="textbox" />
</Grid>
private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
textbox.Focus();
}
With the above window and the "Selected" event handl

Give some time for TreeView to finish their events by doing this instead:
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => textbox.Focus()));

Set TreeView.HideSelection to false.

Related

Switch between Views according to TreeView SelectedItem

i can't find a solution to this problem.
i have a treeview, and i'm trying to get to the point where i'm clicking/double clicking and it opens a view on a different part of the window(lets say using a gridsplitter and the tree is on the right and the relevant view will open on the left by setting the contentcontrol content DP).
thanks
I used
Simplifying the WPF TreeView by Using the ViewModel Pattern
to build my Treeview.
my xaml looks like :
<TreeView ItemsSource="{Binding Parents,IsAsync=True}" Name="tree" SelectedItemChanged="tree_SelectedItemChanged" Background="Transparent" >
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:XMLParentViewModel}"
ItemsSource="{Binding Children}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MinHeight="20" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding ParentDisplayText}" TextWrapping="Wrap"/>
</Grid>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:XMLChildViewModel}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MinHeight="20" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding ChildDisplayText}" TextWrapping="Wrap" MouseDown="TextBlock_PreviewMouseDown" />
</Grid >
</DataTemplate>
</TreeView.Resources>
</TreeView>
and the to know what kind of element is selected :
private void tree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if( tree.SelectedItem.GetType() == typeof(XMLChildViewModel))
//Do what you need
}
I can adapt this code for you but if you have more questions
What clemens said, but also I have a hard time understanding what the problem/issue is? All the help we can get understanding your question, will make all the help you get even better :)
I think This will help. Here the XAML Code...
<TreeView Name="treenavigator" Grid.Row="1">
<TreeViewItem DisplayMemberPath="Item" Header="Item" Name="navitem">
<TreeViewItem Header="Add Item" Name="additem" />
<TreeViewItem Header="Update Item Details" Name="updateitem" />
<TreeViewItem Header="View Item Details" Name="viewitemdetails" />
<TreeViewItem Header="Delete Items" Name="deleteitem" />
</TreeViewItem>
</TreeView>
Here the Sample C# Code. grdForm is the grid in main window that I load the User Controller, and AddItem is the User Controller That I load into grdForm.
private void navitem_Selected(object sender, RoutedEventArgs e)
{
if (treenavigator.SelectedValue.ToString() == additem.ToString())
{
AddItem ItemView = new AddItem();
grdform.Children.Add(ItemView);
}
}

How to bind a resource to a flowdocumentreader from a treeview with only XAML?

This time I am working on a help-window mini-application (to include in the other project, the imageediting application).
I have a grid with two columns and a gridsplitter inbetween. On the left I have a treeview with several nodes (set in XAML) and on the right a flowdocumentreader.
I have about 10 resourcedictionaries where I keep my documents, one for each node, that I want to display in my flowdocumentreader. I actually have no idea how to bind this! Anybody have an idea how I can do this? My code so far (only one resourcedictionary added)
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary x:Name="About" Source="About.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="500"/>
</Grid.ColumnDefinitions>
<GridSplitter HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Grid.Column="1" ResizeBehavior="PreviousAndNext" ResizeDirection="Columns"
Width="5" Background="#FFBCBCBC"/>
<TreeView Width="250" Grid.Column="0" FontFamily="Segoe UI" FontSize="16">
<TreeViewItem Header="Help">
<TreeViewItem Header="About the application"></TreeViewItem>
<TreeViewItem Header="Getting started"></TreeViewItem>
<TreeViewItem Header="Images from Flickr"></TreeViewItem>
<TreeViewItem Header="Images from the computer"></TreeViewItem>
<TreeViewItem Header="Images from the browser"></TreeViewItem>
<TreeViewItem Header="Editing">
<TreeViewItem Header="Open and Save"></TreeViewItem>
<TreeViewItem Header="Uploading"></TreeViewItem>
<TreeViewItem Header="Crop"></TreeViewItem>
<TreeViewItem Header="Resize"></TreeViewItem>
<TreeViewItem Header="Filters"></TreeViewItem>
<TreeViewItem Header="Adding text"></TreeViewItem>
<TreeViewItem Header="Remove red eyes"></TreeViewItem>
</TreeViewItem>
</TreeViewItem>
</TreeView>
<FlowDocumentReader Grid.Column="2" >
</FlowDocumentReader>
</Grid>
You could use the Tag property of the nodes to define a string value to be loaded.
Then do a binding on the selected Node's Tag.
If you then use a converter you can load your document content from file/res.Dict or whatever:
<TreeView x:Name="documentTreeView" Width="250" Grid.Column="0" FontFamily="Segoe UI" FontSize="16">
<TreeViewItem Header="Help">
<TreeViewItem
Header="About the application"
Tag="ResDict1.xaml"></TreeViewItem>
....
<FlowDocumentReader Document="{Binding ElementName=documentTreeView, Path=SelectedItem.Tag, Converter={StaticResource stringToFlowDocumentConverter}}" Grid.Column="2" />

2 identical Controls in the same Grid ? (WPF/xaml)

Here is a simple code that exposes my problem :
<Grid>
<TreeView Name="myTreeViewEvent" >
<TreeViewItem Header="Employee1"/>
</TreeView>
<TreeView Name="myTreeViewEvent2" >
<TreeViewItem Header="Employee2"/>
</TreeView>
</Grid>
The thing is that my 2nd Treeview "overwrites" the 1st one...
Is there a way to change the behaviour so that the 2nd Treeview is "added" to the 1st one ?
(nb : no, I can't put them in the same Treeview cause in my "real" code, I got 2 different Treeviews that I CAN'T merge... and I gotta display them in the same grid !)
Try this
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TreeView Name="myTreeViewEvent" >
<TreeViewItem Header="Employee1"/>
</TreeView>
<TreeView Grid.Row="1" Name="myTreeViewEvent2" >
<TreeViewItem Header="Employee2"/>
</TreeView>
</Grid>
EDIT
Then what prevents you from using this approach?
<Grid>
<StackPanel>
<TreeView Name="myTreeViewEvent">
<TreeViewItem Header="Employee1"/>
</TreeView>
<TreeView Name="myTreeViewEvent2">
<TreeViewItem Header="Employee2"/>
</TreeView>
</StackPanel>
</Grid>
In this case there is no strict division. The items will strech up.

How to keep an area a constant/relative size while user expands/collapses treeview?

I have a window that will be a variable size, currently it is 300 x 400 as shown below.
In the top part I have an expandable tree view
In the bottom part I have a long horizontal panel with a button in it.
I want the top area (treeview) to be about 95% of the height, with the button tool area a constant 50 high.
I want these proportions to stay constant as the user expands and collapses the tree view (and as it expands below the button toolbar, I want the viewscroller to pop in with a scrollbar.
How can I do this? Here's the best I could do so far, but the button area moves up as the user collapses the tree view. :
<Window x:Class="TestSize8383.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="400">
<Window.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
</Window.Resources>
<DockPanel Background="Beige" Margin="3" LastChildFill="False">
<ScrollViewer DockPanel.Dock="Top" Background="White" Margin="3">
<TreeViewItem DockPanel.Dock="Top" Background="White" Header="Page 1" IsExpanded="True">
<TreeViewItem Header="Part 1">
<TreeViewItem Header="Paragraph 1">
<TreeViewItem Header="Word 1"/>
<TreeViewItem Header="Word 2"/>
</TreeViewItem>
<TreeViewItem Header="Paragraph 2">
<TreeViewItem Header="Word 1"/>
<TreeViewItem Header="Word 2"/>
</TreeViewItem>
<TreeViewItem Header="Paragraph 3">
<TreeViewItem Header="Word 1"/>
<TreeViewItem Header="Word 2"/>
</TreeViewItem>
<TreeViewItem Header="Part 2">
<TreeViewItem Header="Paragraph 1">
<TreeViewItem Header="Word 1"/>
<TreeViewItem Header="Word 2"/>
</TreeViewItem>
<TreeViewItem Header="Paragraph 2">
<TreeViewItem Header="Word 1"/>
<TreeViewItem Header="Word 2"/>
</TreeViewItem>
<TreeViewItem Header="Paragraph 3">
<TreeViewItem Header="Word 1"/>
<TreeViewItem Header="Word 2"/>
</TreeViewItem>
</TreeViewItem>
</TreeViewItem>
</TreeViewItem>
</ScrollViewer>
<StackPanel DockPanel.Dock="Bottom" Background="Tan" Margin="3" Height="50">
<Button Content="Previous" Margin="5"/>
</StackPanel>
</DockPanel>
</Window>
How about using a Grid instead of using a DockPanel?
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0">
...
</ScrollViewer>
<StackPanel Grid.Row="1">
...
</StackPanel>
</Grid>
Based on the fixed layout you describe, I would use a Grid instead of DockPanel like so:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0">
<TreeView>
<!-- items excluded for brevity -->
</TreeView>
</ScrollViewer>
<StackPanel Grid.Row="1" Background="Tan" Margin="3">
<Button Content="Previous" Margin="5" />
</StackPanel>
</Grid>
You said the button must be a constant height of about 50 then immediately after that you talk about proportions? I'm not certain I understood you, but here is what I have for you in the meantime.
Make the DockPanel to have LastChildFill = True
Put the StackPanel above the ScrollViewer (first in the XAML code)
Make the ScrollViewer have VerticalScrollBarVisibility="Auto"
This will have these effects:
The button bar will always be visible
The scrollbar will pop into view when it is needed only

Strange WPF errors in Visual Studio

Does anybody know of the reason why ""could not create instance of UserControl"" error can occur. It seems to me that it occurs completely spontanous, for example after I add space after node or change tabulation. Maybe it's some kind of VS bug?
Here are controls. This configuration actually raises an error
<UserControl x:Class="ShortcutsPrototype.KeyboardShortcutsTreePanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ShortcutsPrototype="clr-namespace:ShortcutsPrototype">
<Grid Margin="3,3,3,3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<ShortcutsPrototype:KeyboardShortcutsTreeView />
<Button Grid.Row="1" Margin="3,3,3,3" Grid.Column="1" HorizontalAlignment="Stretch">Reset</Button>
</Grid>
</UserControl>
<UserControl x:Class="ShortcutsPrototype.KeyboardShortcutsTreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ShortcutsPrototype="clr-namespace:ShortcutsPrototype"
Height="300" Width="300">
<Grid>
<TreeView>
<TreeViewItem HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<ShortcutsPrototype:KeyboardShortcutsTreeViewEntry x:Name="generalTreeViewEntry" Title="General" />
</TreeViewItem.Header>
<TreeViewItem HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<ShortcutsPrototype:KeyboardShortcutsTreeViewEntry x:Name="generalNewFileTreeViewEntry" Title="New File" ShortcutKey="Ctrl+N" />
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<ShortcutsPrototype:KeyboardShortcutsTreeViewEntry x:Name="generalOpenFileTreeViewEntry" Title="Open File" ShortcutKey="Ctrl+O" />
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<ShortcutsPrototype:KeyboardShortcutsTreeViewEntry x:Name="generalSaveFileTreeViewEntry" Title="Save File" ShortcutKey="Ctrl+S" />
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<ShortcutsPrototype:KeyboardShortcutsTreeViewEntry x:Name="generalSaveAsFileTreeViewEntry" Title="Save File As.." ShortcutKey="Ctrl+Shift+S" />
</TreeViewItem.Header>
</TreeViewItem>
</TreeViewItem>
<TreeViewItem HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<ShortcutsPrototype:KeyboardShortcutsTreeViewEntry x:Name="debugerTreeViewEntry" Title="Debuger" />
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<ShortcutsPrototype:KeyboardShortcutsTreeViewEntry x:Name="refactoringTreeViewEntry" Title="Refactoring" />
</TreeViewItem.Header>
</TreeViewItem>
</TreeView>
</Grid>
</UserControl>
<UserControl x:Class="ShortcutsPrototype.KeyboardShortcutsTreeViewEntry"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="25">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Label x:Name="titleLabel" Grid.Column="0"></Label>
<Label x:Name="shortcutLabel" Grid.Column="1"></Label>
</Grid>
</UserControl>
Perhaps something in your CodeBehind file is throwing an exception. Have you checked that?
I have found that visual studio has quite the difficult time with WPF user controls.
The only thing that I can see is that it seems to use the latest compiled version of a control. Usually, building the solution will fix the errors I have. Sometimes, if I have multiple projects I have to build them manually one by one.

Resources