Hierarchical TreeList View WPF - wpf

Basically I need to implement a control like this one in WPF, preferably with MVVM support:
(source: msdn.com)
How can I achieve that?

You need something like this using TreeView with some styles for TreeViewItem :
<TreeView>
<TreeViewItem Header="Employee1">
<TreeViewItem Header="Jesper"/>
<TreeViewItem Header="Aaberg"/>
<TreeViewItem Header="12345"/>
</TreeViewItem>
</TreeView>
or you can take a look at Tekerik controls : http://www.telerik.com/products/wpf/overview.aspx
which as controls as you wish but sure with a price :)

Related

Powershell and WPF Treeview

I'm currently working on a powershell tool where I need to create a gui. It seems that according to my needs I would need to use WPF instead of Windows Form. The treeview control in windows forms doesn't let you customize the treeview items. Here is a sample of what I need :
Basically I would need to add treeviewitems on the fly. According to the nodeLevel, I would need to apply different image and progress bar. I would also need to be able to change the visibility of these controls. And all of these will be accomplished using powershell.
Can someone show me a direction, how should I approach this ? How/where should I start ?
You can use standard XAML for WPF to create window with arbitrary controls, events, styles and so on. Then call XamlReader.Load() to create a WPF Window object and Window.ShowDialog() to show it.
# WPF Window with XAML
[xml]$xaml = #"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Window" Title="WPF Window from PowerShell" WindowStartupLocation = "CenterScreen"
Width = "800" Height = "600" ShowInTaskbar = "True">
<TreeView>
<TreeViewItem Header="Group 1">
<TreeViewItem Header="Item 1">
<StackPanel Orientation="Horizontal">
<Image Source="image.png" />
<TextBlock Text="Level 2.0" />
<ProgressBar Minimum="0" Maximum="100" Name="Progress" Width="100" IsIndeterminate="True"/>
<Button>Start</Button>
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="Item 1"></TreeViewItem>
<TreeViewItem Header="Item 1"></TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="Group 2">
<TreeViewItem Header="Item 1"></TreeViewItem>
<TreeViewItem Header="Item 1"></TreeViewItem>
<TreeViewItem Header="Item 1"></TreeViewItem>
</TreeViewItem>
</TreeView>
</Window>
"#
$XmlNodeReader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load($XmlNodeReader)
$Window.ShowDialog()

How to add TreeView to AvalonDock?

I am using perfect library AvalonDock and would like to show TreeView inside docking layout. So my TreeView should be dockingable.
I cannot figured out how TreeView should be added to AvalonDock. For example, I have standard layout.
I've tried this old approach, however this code is not working as I'm using AvalonDock 2.0 and there is no ResizingPanel, DockableContent:
<avalonDock:ResizingPanel Orientation="Horizontal">
<avalonDock:DockablePane>
<avalonDock:DockableContent x:Name="fileFrame" Title="File List">
<TreeView Name="fileTree"/>
</avalonDock:DockableContent>
<avalonDock:DockableContent x:Name="viewFrame" Title="View List">
<TreeView Name="viewTree"/>
</avalonDock:DockableContent>
</avalonDock:DockablePane>
</avalonDock:ResizingPanel>
My goal is to have TreeView at the left side at start of program like in Visual Studio:
How to add TreeView to AvalonDock to see TreeView at start of MainWindow?
Edit:
Now I can see TreeView in Visual Studio:
However, there is no TreeView in started program(just yellow screen):
How to show TreeView with dummy data at the left side at start of program like in Visual Studio?
You can't add a control directly to the LayoutAnchorablePane - you have to wrap it in a LayoutAnchorable:
<avalonDock:DockingManager x:Name="dockManager" >
<avalonDock:LayoutRoot>
<avalonDock:LayoutPanel Orientation="Vertical">
<avalonDock:LayoutDocumentPane/>
<avalonDock:LayoutAnchorablePane Name="ToolsPane" DockHeight="150">
<avalonDock:LayoutAnchorable>
<TreeView Name="viewTree"/>
</avalonDock:LayoutAnchorable>
</avalonDock:LayoutAnchorablePane>
</avalonDock:LayoutPanel>
</avalonDock:LayoutRoot>
</avalonDock:DockingManager>
Edit:
If you want your treeview on the leftside, here a snippet with some dummy data:
<avalonDock:DockingManager x:Name="dockManager">
<avalonDock:LayoutRoot>
<avalonDock:LayoutPanel Orientation="Horizontal">
<avalonDock:LayoutAnchorablePane Name="ToolsPane" DockWidth="150">
<avalonDock:LayoutAnchorable>
<TreeView Name="viewTree">
<TreeViewItem Header="North America">
<TreeViewItem Header="USA" />
<TreeViewItem Header="Canada" />
<TreeViewItem Header="Mexico" />
</TreeViewItem>
<TreeViewItem Header="South America">
<TreeViewItem Header="Argentina" />
<TreeViewItem Header="Brazil" />
<TreeViewItem Header="Uruguay" />
</TreeViewItem>
</TreeView>
</avalonDock:LayoutAnchorable>
</avalonDock:LayoutAnchorablePane>
<avalonDock:LayoutDocumentPane />
</avalonDock:LayoutPanel>
</avalonDock:LayoutRoot>
</avalonDock:DockingManager>

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.

DataBinding to selected TreeViewItem only if child of other TreeViewItem

I have a custom class (NewBlockLabelInfo) with an observable collection of another custom class (DoorControllerLabelInfo) I've successfully databound the NewBlockLabelInfo class to the treeview, and everything displays fine.
I have a lot of textboxs that are data bound to certain properties, and updating these reflects in the treeview.
I'd like to databind one set of textboxs for the properties, to the selected item in the treeview IF the selected item is a child of the specified treeviewitem (Observable Collection, Door Controllers)
The Data Context is specified at the window level.
I've looked long and hard for a way to do this, let alone the best way.
Heres the WPF XAML for the TreeView
<TreeView Margin="12,150,582,16" Name="treeView1">
<TreeViewItem Header="{Binding Path=BlockName}" Style="{StaticResource BlockItem}" IsExpanded="True">
<TreeViewItem Style="{StaticResource PhoneNoItem}" Header="{Binding Path=TelephoneNumber}"/>
<TreeViewItem Style="{StaticResource DataNoItem}" Header="{Binding Path=DataNumber}"/>
<TreeViewItem Style="{StaticResource CompanyItem}" Header="{Binding Path=CompanyName}"/>
<TreeViewItem Style="{StaticResource ConnectedItem}" Header="{Binding Path=ConnectedDC}" />
<TreeViewItem IsExpanded="True" Header="Door Controllers" Foreground="#FF585858" ItemsSource="{Binding Path=DoorControllers, UpdateSourceTrigger=PropertyChanged}" Name="DCTreeViewItem" Selected="DCTreeViewItem_Selected">
<TreeViewItem.ItemTemplate>
<HierarchicalDataTemplate>
<TreeViewItem Header="{Binding Path=DCName}" Style="{StaticResource DCItem}" IsExpanded="True" Selected="DCTreeViewItem_Selected" >
<TreeViewItem Header="{Binding Path=Address}" Style="{StaticResource AddressItem}" />
<TreeViewItem Header="{Binding Path=Channel1}" Style="{StaticResource Door1Item}" />
<TreeViewItem Header="{Binding Path=Channel2}" Style="{StaticResource Door2Item}" />
</TreeViewItem>
</HierarchicalDataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem IsExpanded="True" Header="Flats" Foreground="#FF585858" ItemsSource="{Binding Path=FlatNames, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding}" Style="{StaticResource FlatsItem}" IsExpanded="True">
</TreeViewItem>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</TreeViewItem>
</TreeView>
How can I bind a textbox to a selected item property (or to the databound class property) of a TreeViewItem only if it is a child of Door Controllers TreeViewItem
Thank you in advance
Oliver
You would likely be best served with defining a DataTemplate selector, and creating several datatemplates. The selector can evaluate all kinds of logical rules, and return the template that you want.
Here is a pretty good getting started tutorial on DataTemplateSelectors.
EDIT
After rereading your question here is what I have got.
Do your model classes have navigation properties to get to parent objects? If so, you can use triggers (or more preferable if you are using MVVM) properties on the ViewModel to enable/disable/alter visibility based on what the parent object is rather than the parent TreeViewItem. It is a bit more difficult to access the visual tree the way you are describing.
I solved this myself by adding an event handler on click for each of the child TreeViewItems I am concerned with. With this I could then get the DataContext from it, and set it to be the DataContext of the TextBoxs, and create my own bindings.
Since DataContext retrieval is done by reference, and not by value this works.
Here is the event handler for when one of the child nodes are clicked than I am concerned with: (Forgive the temporary naming)
private void DCTreeViewItem_Selected(object sender, RoutedEventArgs e)
{
TreeViewItem currentItem = (TreeViewItem)e.OriginalSource;
textBox5.DataContext = ((DoorControllerLabelInfo)currentItem.DataContext);
Binding b = new Binding("DCName");
b.Mode = BindingMode.TwoWay;
b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(textBox5, TextBox.TextProperty, b);
}
From this, I set the path, binding mode, and update source trigger in the XAML so that only the Data Context need to be updated.
Thanks
Oliver

Keyboard Navigation fails when there are hidden items in TreeView

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.

Resources