How to add TreeView to AvalonDock? - wpf

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>

Related

Stepping through material design wpf treeview with additional TreeViewAssist requires two keystrokes per step

when adding a TreeViewAssist.AdditionalTemplateSelector item to a wpf material design treeview (http://materialdesigninxaml.net/) I need two keystrokes to get to the next element because it always focusses the additional template.
I did not find any properties that could avoid this behaviour. It even exists in the TreeView demo of the material design package.
Here is the xaml example from the original material design demo which also requires 2 keystrokes to jump to the next element (event when the additional template is disabled).
<TreeView>
<materialDesign:TreeViewAssist.AdditionalTemplate>
<DataTemplate>
<materialDesign:ColorZone
Mode="PrimaryLight"
CornerRadius="6">
<TextBlock
FontSize="10"
Margin="8 1 8 1"
FontStyle="Italic">
8 planets
</TextBlock>
</materialDesign:ColorZone>
</DataTemplate>
</materialDesign:TreeViewAssist.AdditionalTemplate>
<TreeViewItem
Header="Solar System">
<TreeViewItem
Header="Mercury"
materialDesign:TreeViewAssist.AdditionalTemplate="{x:Static materialDesign:TreeViewAssist.SuppressAdditionalTemplate}" />
<TreeViewItem
Header="Venus"
materialDesign:TreeViewAssist.AdditionalTemplate="{x:Static materialDesign:TreeViewAssist.SuppressAdditionalTemplate}" />
<TreeViewItem
Header="Earth"
materialDesign:TreeViewAssist.AdditionalTemplate="{x:Static materialDesign:TreeViewAssist.SuppressAdditionalTemplate}" />
<TreeViewItem
Header="Mars"
materialDesign:TreeViewAssist.AdditionalTemplate="{x:Static materialDesign:TreeViewAssist.SuppressAdditionalTemplate}" />
<TreeViewItem
Header="Jupiter"
materialDesign:TreeViewAssist.AdditionalTemplate="{x:Static materialDesign:TreeViewAssist.SuppressAdditionalTemplate}" />
<TreeViewItem
Header="Saturn"
materialDesign:TreeViewAssist.AdditionalTemplate="{x:Static materialDesign:TreeViewAssist.SuppressAdditionalTemplate}" />
<TreeViewItem
Header="Uranus"
materialDesign:TreeViewAssist.AdditionalTemplate="{x:Static materialDesign:TreeViewAssist.SuppressAdditionalTemplate}" />
<TreeViewItem
Header="Neptune"
materialDesign:TreeViewAssist.AdditionalTemplate="{x:Static materialDesign:TreeViewAssist.SuppressAdditionalTemplate}" />
</TreeViewItem>
</TreeView>
I would be grateful if someone has a way to achieve the desired behavior to only require 1 keystroke to walk through the tree without even focusing the additional template.

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 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.

WPF -treeview items can't be selected at 4th level when using datatemplate within datatemplate

I tried to implement treeview with 4 levels using WPF/C#.Net 4.0.It loads all 4 levels but can't select 4th level and when selecting 3rd level it select group with 4th level.
Continent->Country->District->Artifacts is one structure but there is another one Continent->Products->Artifacts
Resource DataTemplates->
<DataTemplate x:Key="DistrictTemplates">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=ArtifactName}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="CountryTemplate">
<TreeViewItem ItemsSource="{Binding Path=District}"
ItemTemplate=" {StaticResource DistrictTemplates}"
Header="{Binding Path=Code}">
</TreeViewItem>
</DataTemplate>
TreeView code->
<TreeView Name="treeExplorer" MouseDoubleClick="TreeView_MouseDoubleClick" SelectedItemChanged="treeExplorer_SelectedItemChanged">
<TreeViewItem Name="tviDefinition" IsExpanded="True" Header="Continent">
<TreeViewItem ItemsSource="{Binding Path=Country}" ItemTemplate="{StaticResource CountryTemplate}" Header="Country" />
</TreeViewItem>
</TreeView>
there are some other treeItems as well.I can't use inline template inside the TreeView.Resources and also im confused if can use this HierarchicalDataTemplate sine i cant call Country.Districts.ArtifactName and got two hierarchies but I can call Country.Districts() and then Districts has code property and using code i can find Artifacts.And im using datatemplates inside usercontrol.resources
How would I be able to do this?
Here's something I've written that goes 4 levels deep. It's a TreeView which shows HL7 message structure. For a quick background HL7 is a field separated message. You have a message. Each message has a Segment. Each Segment has at least one field. A field could have multiple components. A component can have subcomponents. This tree displays the HL7 message structure, where each level is a part of the HL7 message format.
For example, if there is PID segment in the message the tree would like this:
PID
...PID.1
...PID.2
......PID.2.1
......PID.2.2
......PID.2.3
......PID.2.4
.........PID.2.4.1
.........PID.2.4.2
etc...
Here is the XAML:
<TreeView x:Name="hl7Structure" ItemsSource="{Binding Path=MessageSegments}" IsEnabled="True">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type MyNamespace:MessageSegment}" ItemsSource="{Binding Path=Fields}">
<TextBox x:Name="segmentName" BorderBrush="Transparent" BorderThickness="0" Text="{Binding Path=Name}" FocusVisualStyle="{x:Null}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type MyNamespace:MessageField}" ItemsSource="{Binding Path=Components}">
<TextBlock x:Name="fieldName" Text="{Binding Path=Name}" ToolTip="{Binding Path=Info}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type MyNamespace:MessageComponent}" ItemsSource="{Binding Path=Subcomponents}">
<TextBlock x:Name="componentName" Text="{Binding Path=Name}" ToolTip="{Binding Path=Info}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type MyNamespace:MessageSubcomponent}">
<TextBlock x:Name="subComponentName" Text="{Binding Path=Name}" ToolTip="{Binding Path=Info}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
Now the explanation of how it works. I have a base object that each HL7 message piece inherits. The ItemsSource of the TreeView is bound to that collection. Since there are 4 levels, where 3 show hierarchy and one that does not, there are 3 HierarchicalDataTemplates and 1 DataTemplate.
Think of it this way...The HL7 Message Segment, Field, and Components are tree nodes because they have children. The HL7 subcomponent is a leaf, because it has none. Each tree node gets a HierarchicalDataTemplate, but each leaf just gets a DataTemplate.
Each of HierarchicalDataTemplates know what object type to display by using the DataType property. Here is where I tell the control, the child type it's displaying. This allows me to use the base type collection and then display all the child types at their appropriate node levels.
Hope this helps.
Finally I managed to solve this.Thanks Josh and everyone.
Resource DataTemplates->
<DataTemplate x:Key="DistrictTemplates">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=ArtifactName}" />
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="CountryTemplate" DataType="Continent.Countries" ItemsSource="{Binding Path=District}" ItemTemplate="{StaticResource DistrictTemplates}">
<TextBlock Text="{Binding Path=Code}"/>
</HierarchicalDataTemplate>
TreeView code->
<TreeView Name="treeExplorer" MouseDoubleClick="TreeView_MouseDoubleClick" SelectedItemChanged="treeExplorer_SelectedItemChanged">
<TreeViewItem Name="tviDefinition" IsExpanded="True" Header="Continent">
<TreeViewItem ItemsSource="{Binding Path=Country}" ItemTemplate="{StaticResource CountryTemplate}" Header="Countries" />
</TreeViewItem>
</TreeView>

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

Resources