I have a treeview control in wpf..i need to add an image at evry node.how is it possible?
If you want to have unique images for each node, you can do something like:
<TreeView>
<TreeViewItem>
<TreeViewItem.Header>
<Image Source="/WpfApplication2;component/folder.png" Height="25" Width="25"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem.Header>
<Image Source="/WpfApplication2;component/folder1.png" Height="25" Width="25"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem.Header>
<Image Source="/WpfApplication2;component/folder2.png" Height="25" Width="25"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem.Header>
<Image Source="/WpfApplication2;component/folder3.png" Height="25" Width="25"/>
</TreeViewItem.Header>
</TreeViewItem>
</TreeView>
or, if you want to have the same image for each node, you can do something like this:
<Window.Resources>
<Image Source="/WpfApplication2;component/folder.png" Height="25" Width="25" x:Key="FolderIcon" x:Shared="false"/>
</Window.Resources>
<Grid>
<TreeView>
<TreeViewItem>
<TreeViewItem.Header>
<StaticResourceExtension ResourceKey="FolderIcon"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem.Header>
<StaticResourceExtension ResourceKey="FolderIcon"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem.Header>
<StaticResourceExtension ResourceKey="FolderIcon"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem.Header>
<StaticResourceExtension ResourceKey="FolderIcon"/>
</TreeViewItem.Header>
</TreeViewItem>
</TreeView>
</Grid>
Hope this helps.
UPDATE to answer the following question: "how can i change the image/icon on clicking/expanding the node"
Here is a quick and dirty solution.
Xaml:
<Window.Resources>
<Image Source="/WpfApplication2;component/folder.png" Height="25" Width="25" x:Key="FolderIcon" x:Shared="false"/>
<Image Source="/WpfApplication2;component/folderOpened.jpg" Height="25" Width="25" x:Key="FolderOpenIcon" x:Shared="false"/>
</Window.Resources>
<Grid>
<TreeView>
<TreeViewItem PreviewMouseLeftButtonDown="itemExpanded" Name="treeViewItem">
<TreeViewItem.Header>
<StaticResourceExtension ResourceKey="FolderIcon"/>
</TreeViewItem.Header>
<TreeViewItem>
<TreeViewItem/>
</TreeViewItem>
</TreeViewItem>
</TreeView>
</Grid>
C# / Code-behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void itemExpanded(object sender, RoutedEventArgs e)
{
if (treeViewItem.IsExpanded)
{
treeViewItem.Header = FindResource("FolderIcon");
}
else
{
treeViewItem.Header = FindResource("FolderOpenIcon");
}
}
}
You can also accomplish this using the "Expanded" event as well. If you want eliminate "code-behind" you can also do this using a Command or Converter.
Move image to resource section and set x:Shared="False":
<Window.Resources>
<Image Source="links.png" x:Key="imgLinks" x:Shared="False"/>
Use it in template:<StaticResource ResourceKey="imgLinks"/>
Related
I am trying to build a help module with a treeview and the goal is to have a different view show up in the redbox based on selected treeview item. how would I go about to do that?
This is all the code I have:
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TreeView Margin="2" Width="250" HorizontalAlignment="Left" Height="auto" IsEnabled="True" FontSize="20">
<TreeViewItem Header="Introduction">
</TreeViewItem>
<TreeViewItem Header="Logging in" Margin="0,10,0,0">
<TreeViewItem Header="Changing Password" Margin="0,10,0,0"/>
</TreeViewItem>
<TreeViewItem Header="Home" Margin="0,10,0,0">
<TreeViewItem Header="Dashboard Elements" Margin="0,10,0,0"/>
<TreeViewItem Header="Parking Spots" Margin="0,10,0,0" />
<TreeViewItem Header="Docking Spots" Margin="0,10,0,0"/>
</TreeViewItem>
<TreeViewItem Header="Log Table" Margin="0,10,0,0"/>
<TreeViewItem Header="Security" Margin="0,10,0,0">
<TreeViewItem Header="Domestic Trucks" Margin="0,10,0,0"/>
<TreeViewItem Header="International Trucks" Margin="0,10,0,0"/>
</TreeViewItem>
<TreeViewItem Header="Administration" Margin="0,10,0,0" Visibility="{Binding Source={x:Static model:ViewModel.CurrentUser}, Path=IsAdmin, Converter={StaticResource My.Converter.BoolToHidden}}">
<TreeViewItem Header="Permissions" Margin="0,10,0,0"/>
<TreeViewItem Header="Editing a User" Margin="0,10,0,0"/>
<TreeViewItem Header="Adding a new company" Margin="0,10,0,0"/>
</TreeViewItem>
</TreeView>
</Grid>
I really think that this Control is not doing what you expect. I would rather use Markdown to create a help file and save it to html, pdf or xps. You can open this document when the user hits the help button. IMO it is not a good idea to "hard-code" a Help module.
But to answer your question any way, you can do it this way:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TreeView x:Name="TreeView_TOC">
<TreeViewItem Header="Chapeter 1">
<TreeViewItem.Tag>
<TextBlock Text="Your Content goes here" />
</TreeViewItem.Tag>
</TreeViewItem>
</TreeView>
<ContentControl Grid.Column="1"
Content="{Binding ElementName=TreeView_TOC, Path=SelectedItem.Tag, Mode=OneWay}"/>
</Grid>
Happy documenting
Tim
How would I add an icon to each of these parent nodes
I tried adding under each TreeViewItem but the icon doesn't show and when I bind my collection to the ItemSource, it says it must be empty fist.
<TreeView x:Name="tvMessages" HorizontalAlignment="Left" Height="262" Margin="10,37,0,0" VerticalAlignment="Top" Width="248">
<TreeViewItem x:Name="itemsCritical" Header="Critical">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Description}"/>
<TextBlock Text="{Binding ID}" Visibility="Hidden"/>
</StackPanel>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem x:Name="itemsAlert" Header="Alert">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Description}"/>
<TextBlock Text="{Binding ID}" Visibility="Hidden"/>
</StackPanel>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem x:Name="itemsInformational" Header="Informational">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Description}"/>
<TextBlock Text="{Binding ID}" Visibility="Hidden"/>
</StackPanel>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</TreeView>
Take a look at this example:
<TreeViewItem Name="treeViewItem1" IsEnabled="True">
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<Image Height="16" Source="Images/16x16_red_lamp.png" Width="16" />
<TextBlock Margin="5,0" Text="HostA: Disconnected" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
Just place the Image inside and tell the Source where is your Icon located.
You can also use HeaderTemplate in case you have Bindings against associated item.
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" />
So I am having an issue with the TreeView. If I build a tree view statically, every node in the tree is selectable in that when I click on it, it highlights itself blue, indicating that node is selected.
<TreeView
Grid.Column="0"
Grid.Row="2"
MinHeight="100"
MinWidth="100"
BorderBrush="White"
DataContext="{Binding Projects, Source={x:Static SizingApp:Manager.Instance}}">
<TreeViewItem Header="Project 1" IsExpanded="True">
<TreeViewItem Header="Step 1" IsExpanded="True">
<TreeViewItem Header="Load 1" IsExpanded="True"></TreeViewItem>
<TreeViewItem Header="Load 2" IsExpanded="True"></TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="Step 2" IsExpanded="True">
<TreeViewItem Header="Load 1" IsExpanded="True"></TreeViewItem>
<TreeViewItem Header="Load 2" IsExpanded="True"></TreeViewItem>
</TreeViewItem>
</TreeViewItem>
However, I am Binding to the TreeView to populate it. Furthermore, I am binding to objects that implement Emiel Jongerius's BindableObjectBase3 class. This is a wonderful base class implementation that allows my objects to be Bindable and implement the INotifyPropertyChanged interface with the concern for manual DependencyProperty management.
So this is the basic class structure (simplified from my actual objects) that I am trying to implement in a TreeView.
public abstract class MyCustomClass : BindableObjectBase3
{
private string m_strName;
public virtual string Name
{
get
{
using (this.GetPropertyTracker(() => this.Name))
{
return m_strName;
}
}
set
{
this.SetValue(ref this.m_strName, value, () => this.Name);
}
}
}
public class Project : MyCustomClass
{
private List<Step> m_steps;
public List<Step> Steps
{
get
{
using (this.GetPropertyTracker(() => this.Steps))
{
return m_steps;
}
}
set
{
this.SetValue(ref this.m_steps, value, () => this.Steps);
}
}
}
public class Step : MyCustomClass
{
private List<Load> m_loads;
public List<Load> Loads
{
get
{
using (this.GetPropertyTracker(() => this.Loads))
{
return m_loads;
}
}
set
{
this.SetValue(ref this.m_loads, value, () => this.Steps);
}
}
}
public class Load : MyCustomClass
{
}
And this is the basic XAML I use to implement the TreeView:
<TreeView
Grid.Column="0"
Grid.Row="2"
MinHeight="100"
MinWidth="100"
BorderBrush="White"
DataContext="{Binding Projects, Source={x:Static SizingApp:Manager.Instance}}">
<TreeView.Resources>
<HierarchicalDataTemplate x:Key="LoadTemplate">
<TreeViewItem Header="{Binding Path=Name}">
</TreeViewItem>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="StepTemplate">
<TreeViewItem Header="{Binding Path=Name}" IsExpanded="True"
ItemsSource="{Binding Path=Loads}"
ItemTemplate="{StaticResource LoadTemplate}">
</TreeViewItem>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="ProjectTemplate">
<TreeViewItem Header="{Binding Path=Name}" IsExpanded="True"
ItemsSource="{Binding Path=Steps}"
ItemTemplate="{StaticResource StepTemplate}">
</TreeViewItem>
</HierarchicalDataTemplate>
</TreeView.Resources>
<TreeViewItem
Header="{Resx ResxName=PSSPECApplication.Controls.ProjectControlResources, Key=projectTree_Header}"
ItemsSource="{Binding}"
IsExpanded="True"
Focusable="True"
ItemTemplate="{StaticResource ProjectTemplate}">
</TreeViewItem>
</TreeView>
Now all of this works fine as far as binding goes. I can bind to an ObservableCollection<Project> and as I add/remove/manipulate projects, the TreeView updates accordingly.
However, the only node in the TreeView that seems selectable is the first node (the one that is static). All of the other nodes create through dynamic Binding do not indicate that they are selected on the GUI. I would expect that they would also highlight blue when clicked on. But instead they do nothing. Does anyone have an idea of why?
You shouldn't be defining TreeViewItems explicitly in your ItemTemplates. The reason you can't select any of the items is that they have no parent TreeView to control selection behavior. You need to let the TreeView generate the TreeViewItem controls for you and only use the item templates to define the UI for the Headers and the bindings for their items. Use something like this instead:
<Window.Resources>
<HierarchicalDataTemplate x:Key="LoadTemplate">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="StepTemplate" ItemsSource="{Binding Loads}" ItemTemplate="{StaticResource LoadTemplate}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="ProjectTemplate" ItemsSource="{Binding Steps}" ItemTemplate="{StaticResource StepTemplate}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView MinHeight="100" MinWidth="100" BorderBrush="White"
ItemsSource="{Binding Path=Projects}"
ItemTemplate="{StaticResource ProjectTemplate}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
My TreeView is acting just as the original poster has described. I'm able to select everything in my TreeView Control but If I select a childnode the Parent Node is what Highlights even though It binds and clicks the child. I tried structuring my code to resemble John Bowen's suggestion and still get the same results. Here is my XAML Code:
<Fluent:RibbonWindow.Resources>
<HierarchicalDataTemplate x:Key="MyTreeViewStyle" ItemsSource="{Binding Contacts}">
<!-- Display the Index by showing it's Index string -->
<StackPanel Orientation="Horizontal">
<Image x:Name="img" Width="16" Height="16" Stretch="Fill" Source="Images\closedfolder16.png" />
<TextBlock Text="{Binding Index}" Margin="5,0" ToolTip="{Binding Index}"/>
</StackPanel>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="img2" Width="16" Height="16" Stretch="Fill" Source="Images\closedfolder16.png" />
<TextBlock Text="{Binding Name}" Margin="5,0" ToolTip="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</Fluent:RibbonWindow.Resources>
Then I use it here in my TreeView Control:
<Grid>
<TreeView Margin="2,2,2,2" x:Name="MyTreeView" ItemTemplate="{StaticResource MyTreeViewStyle}" ItemContainerStyle="{StaticResource AlwaysExpand}" ScrollViewer.CanContentScroll="True" BorderThickness="0" TreeViewItem.Selected="btnDisplayContact_Click" />
</Grid>
The result is this screenshot, notice how the parent node D is highlighted after clicking the child node, instead of the child node being highlighted:
http://home.swbell.net/davis32/Snapshot.png
Can't post images so just cut and paste the URL link.
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