Keyboard Navigation fails when there are hidden items in TreeView - wpf

So I have a TreeView like the one below, with certain items being hidden. If I try to go through the tree using arrow keys, I get stuck at the items surrounding the "collapsed" items. Try it yourself.
<Window x:Class="Example.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TreeViewBug" Height="300" Width="300">
<Grid>
<TreeView>
<TreeViewItem Header="a." />
<TreeViewItem Header="b" Visibility="Collapsed" />
<TreeViewItem Header="c." />
<TreeViewItem Header="d" />
<TreeViewItem Header="e." />
<TreeViewItem Header="f" Visibility="Collapsed"/>
<TreeViewItem Header="g." />
<TreeViewItem Header="h" />
</TreeView>
</Grid>
</Window>
Nobody else seems to have posted this question (or blogged about it) and so I'm posting it in the hopes of getting a non-hacky solution to this. So here's my question:
How do I fix this bug?
I'm planning on extending the default TreeView to skip items with Visibility set to Hidden/Collapsed or IsEnabled set to false. Has anybody else encountered this before and come up with a good solution?

I don't understand why this happens.
I could fix it by adding:
IsEnabled="False"
to the collapsed items. Then, navigation works as you'd expect.

Here's a solution that works: Disable the item you are hiding. If the item is disabled, keyboard navigation works as it is supposed to. So whenever you set the Visibility of the item, set IsEnabled to false when the item is not visible.
Try the code in the question but add IsEnabled="false" to all the collapsed items. It should work.

Related

WPF: Scrollviewer not limiting content to size of window

I have a treeview with a scrollviewer. When the treeview becomes to full with treenodes i want the scrollbar to show up. But no matter how big the treeview gets it never shows up. The treeview grows outside of window without limiting itself to staying inside window.
The structure is currently:
MainWindow contains a Frame that displays a page, the page contains a usercontrol, the usercontrol contains a treeview.
The usercontrol is set to "stretch", but instead of stretching to fit it's parent (limiting the space and thus making scrollbar appear), it stretches to fit all it's children (and thus stretching outside of screen).
How would i go on about making the "auto" sizing limiting itself to it's parent, instead of making it showing all children?
How i would like it to look/work like
How it actually looks/works like
Code, kinda irrelevant, i just wanna know how i should apply scrollview:
MainWindow:
<Frame Source="View/Pages/StartPage.xaml" x:Name="MainFrame" NavigationUIVisibility="Hidden"/>
</DockPanel>
MainPage:
<Grid>
<Frame Source="ParamFrameV.xaml" x:Name="pageFrame" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
ParamFrameV (the usercontrol):
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" VerticalAlignment="Top" MaxHeight="I WANNA LIMIT HEIGHT SO THAT IT WONT GO OFF SCREEN" Width="283">
<TreeView ItemsSource="{Binding Nodes}" ItemContainerStyle="{StaticResource TreeViewItemExpandedStyle}">
//irrelevant code for this question
</TreeView>
</ScrollViewer>
that works just fine for me:
<Grid>
<ScrollViewer Height="{Binding ElementName=ParentGridName, Path=ActualHeight"}" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" VerticalAlignment="Top" Width="283">
<TreeView Width="50" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<TreeViewItem Header="hi"></TreeViewItem>
<TreeViewItem Header="hi2"></TreeViewItem>
<TreeViewItem Header="hi3"></TreeViewItem>
<TreeViewItem Header="hi4"></TreeViewItem>
<TreeViewItem Header="hi5"></TreeViewItem>
<TreeViewItem Header="hi6"></TreeViewItem>
<TreeViewItem Header="hi7"></TreeViewItem>
<TreeViewItem Header="hi8"></TreeViewItem>
</TreeView>
</ScrollViewer>
</Grid>
Note:
scroling on the treeview itself will not scroll as it will capture your scroll event but i bet there is a way around this

How to Create DropdownList with CheckBox in WPF application?

I am new to WPF. I wan to create a Dropdown List which will contain CheckBox items in to it as show in image. Is it Possible?
This is not the perfect solution to your question, but maybe it helps you anyway.
(You don't have to use <Canvas> but i like it because it's more comfortable to place elements)
<Canvas>
<ListBox Canvas.Left="280" Canvas.Top="40" Width="170">
<ListBoxItem>
<TreeView>
<TreeViewItem Header="Outboard">
<TreeViewItem Header="Generic">
<CheckBox>Bronze</CheckBox>
<CheckBox>Clear</CheckBox>
</TreeViewItem>
<TreeViewItem Header="Guardian">
<CheckBox>Clear</CheckBox>
<CheckBox>UltraWhite</CheckBox>
</TreeViewItem>
</TreeViewItem>
</TreeView>
</ListBoxItem>
</ListBox>
</Canvas>
Sry can't post a picture yet because i don't have enough Reputations.
So i uploaded it.
http://imageshack.us/scaled/thumb/849/examplezt.png
I used a Listbox instead of a Combobox and you only can check the latest items.

How to: Add items on the same line in a TreeView in Silverlight 4.0

I want to add a TreeViewItem and some other controls to the right of the TreeViewItem on the same line next to the header. I want the other controls to be visible without having to expand the item as well. Comment with any questions and I'll try to answer them. Thanks, seeker.
P.S. Thought I had found an answer earlier, but I was wrong. :(
Let's give it a blind shot:
<TreeView>
<TreeViewItem>
<TreeViewItemHeader>
<StackPanel Orientation="Horizontal">
<TextBlock>Header text</TextBlock>
<Button>Some other button</Button> <!-- this is `some other control -->
</StackPanel>
</TreeViewItemHeader>
</TreeViewItem>
</TreeView>
It's not that clear what do you want to achieve, maybe a mockup?

WPF: Focus in a Window and UserControl

I'm trying to get a UserControl to tab properly and am baffled. The logical tree looks like this.
|-Window
-Grid
-TabControl
-TabItem
-StackPanel
-MyUserControl
|-StackPanel
-GroupBox
-Grid
-ComboBox
-Textbox1
-Textbox2
Everything works fine, except when the visibility converter for the ComboBox returns Visibility.Collapsed (don't allow user to change database mode), then when textbox1 is selected, instead of being able to tab through the controls in the UserControl, the focus shifts to a button declared at the bottom of the window. Nothing else apart from the controls displayed has TabIndex or FocusManager properties set.
I'm banging my head against a brick wall and I must be missing something. I've tried IsFocusScope=True/False, played with FocusedElement and nothing works if that ComboBox is invisible (Visibility.Collapsed).
<Window x:Class="MyNamespace.Client.WinInstaller"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
FocusManager.FocusedElement="{Binding ElementName=tabWizard}">
<Window.Resources>
<props:Settings x:Key="settings" />
</Window.Resources>
<Grid Grid.IsSharedSizeScope="True">
<!-- row and column definitions omitted -->
<loc:SmallHeader Grid.Row="0" x:Name="headerBranding" HeaderText="Setup" />
<TabControl x:Name="tabWizard" DataContext="{StaticResource settings}" SelectedIndex="0" FocusManager.IsFocusScope="True">
<TabItem x:Name="tbStart" Height="0">
<StackPanel>
<TextBlock Text="Database Mode"/>
<loc:DatabaseSelector x:Name="dbSelector" AllowChangeMode="False" TabIndex="1"
AvailableDatabaseModes="SQLServer" IsPortRequired="False"
DatabaseMode="{Binding Default.DbMode,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
DatabasePath="{Binding Default.DatabasePath,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</TabItem>
...
The top of the user control is below:
<UserControl x:Class="MyNamespace.Client.DatabaseSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="root"
FocusManager.IsFocusScope="True"
FocusManager.FocusedElement="{Binding ElementName=cboDbMode}">
<UserControl.Resources>
<conv:DatabaseModeIsFileBased x:Key="DatabaseModeIsFileBased"/>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</UserControl.Resources>
<StackPanel DataContext="{Binding}">
<GroupBox>
<Grid>
<!-- row and column definitions omitted -->
<Label Content="Database Mode"/>
<ComboBox x:Name="cboDbMode" SelectedValue="{Binding ElementName=root,Path=DatabaseMode,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Value" SelectedValuePath="Key" TabIndex="1" Visibility="{Binding AllowChangeMode,ElementName=root,Converter={StaticResource BooleanToVisibilityConverter}}" />
<!-- AllowChangeMode is a DependencyProperty on the UserControl -->
<Grid><!-- row and column definitions omitted -->
<Label "Host"/>
<TextBox x:Name="txtDBHost" Text="{Binding ElementName=root,Path=DatabaseHost,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" TabIndex="2" />
<TextBox x:Name="txtDBPort" Text="{Binding ElementName=root,Path=DatabasePortString,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" TabIndex="3" />
I know this response is quite late... but have you tried:
<UserControl ... KeyboardNavigation.TabNavigation="Local">
Doing so will ensure once your UserControl has recieved focus, you will navigate only through TabStop within your UserControl (instead of worring about conflicting TabIndex values throughout your app). After looping through the TabStops of your UserControl, TabNavigation will resume to the TabStop outside of it.
http://msdn.microsoft.com/en-us/library/system.windows.input.keyboardnavigationmode.aspx
Maybe the problem is that you hide the FocusManager.FocusedElement.
Anyway, you could make life easier by just eliminating some complicating factors:
Remove FocusManager.FocusedElement...
the ComboBox is the first control within anyway.
Remove FocusManager.IsFocusScope...
I suppose it's ok if everytime you enter the usercontrol the first control within will be focussed, not the one that was focussed when you left it before. Just let the usercontrol be "inlined" in the surrounding controls.
Remove the explicit TabIndices in the UserControl. Your layout already implies the same ordering.
If you eliminate these three complicating factors, you might already be done.
Maybe you also have to set your UserControl Focusable=False, s.t. the focus is passed to the first focussable Control within - comboBox or TextBox1.

TreeView construction (C#) in WPF Application

I am trying to make a WPF Application containing a treeview, whose data will be populated from the database. Since I am new to all this, I tried using the simple tutorial that can be found at http://dev102.blogspot.com/2007/12/how-to-use-hierarchical-datatemplate-in.html
I tried following the steps exactly, but all I am getting is just the root node. My xaml looks like this:
<Window x:Class="Hierarchical_attempt.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:Hierarchical_attempt"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type data:Root}"
ItemsSource="{Binding Path=WebPages}">
<TextBlock Text="{Binding Title}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type data:WebPage}"
ItemsSource="{Binding Path=LinksInPage}">
<TextBlock Text="{Binding PageTitle}" />
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView Name="tree1">
<TreeViewItem ItemsSource="{Binding Path=Webpages}"
Header="{Binding Title}">
</TreeViewItem>
</TreeView>
</Grid>
</Window>
Can you plese tell me where am I going wrong? I am just tring this since this will give me a heads up as to how to go about the treeview. However, what I actually have to do is to populate the data fom the database in the treeview. If you know of any step by step tutorial available, then that will also be really helpful. Thanks. Please reply soon.
It looks as though you have a typo on your binding path. It should be:
<TreeView>
<TreeViewItem ItemsSource="{Binding Path=WebPages}"
Header="{Binding Title}">
</TreeViewItem>
</TreeView>
Note that the P in WebPages is in upper case.
If you are using Visual Studio to develop this, then you should examine the Output pane when running the application. Any binding errors such as this won't raise exceptions, but they will create helpful messages there.
I also simplified the XAML slightly in the original question.

Resources