Reputation: 105
I'm trying to generate one element that alows me to show some images into a treeview
using WPF. I sopose that I have to generate my own TreeViewItem
in order to bind the properties I want into the TreeView
control. This is my own TreeViewItem
:
public class TreeViewItem : System.Windows.Controls.TreeViewItem
{
public ImageSource Image { get; set; }
public TreeViewItem(string text, ImageSource displayedImage)
{
this.Header = text;
this.Image = displayedImage;
}
}
With this object generated, I define the structure of my custom TreeView in order to bind all data:
<UserControl x:Class="test.TreeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="100">
<Grid>
<TreeView Name="TVTree" x:FieldModifier="public">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<Grid Margin="2" MinHeight="25" MaxHeight="25" MinWidth="60">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding Image}" Height="16" Width="16"/>
<TextBlock Grid.Column="1" Text="{Binding Header}" Margin="5,0"/>
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
As long as I know, I'm trying to bind the Image Source with the image source of my custom control, and the text of the textblock with the header of my treeviewItem
. The problem is that the control doesn't display the image and I find out that the header is not beeing displayed too. It only displays the result of ToString()
method (which is the same as the string defined as the Header of the object).
Anybody knows how can I bind this data correctly? Thanks in advance
Upvotes: 0
Views: 106
Reputation: 22079
When you use data templates, you need to define your data as type e.g. TreeItem
and its appearance in a template, here a HierarchicalDataTemplate
for a TreeView
. A TreeItem
could look like this.
public class TreeItem
{
public string Header { get; }
public ImageSource Image { get; }
public ObservableCollection<TreeItem> Children { get; }
public TreeItem(string header, ImageSource displayedImage, ObservableCollection<TreeItem> children)
{
Header = header;
Image = displayedImage;
Children = children;
}
}
You do not inherit from TreeViewItem
, because you define data. A TreeViewItem
is a container in the view that wraps your data template as an item of the TreeView
. In a TreeView
there is a hierarchy of items, so you must provide a collection of subitems for any item. This collection can be null
or empty if there are no further items.
Then you need a view model for your user control which exposes a collection of TreeItems
that you can bind to. I just created a list of dummy data with three nested items in Children
collections to show the hierarchy.
public class TreeControlViewModel
{
public ObservableCollection<TreeItem> TreeItems { get; }
public TreeControlViewModel()
{
TreeItems = new ObservableCollection<TreeItem>
{
new TreeItem("Item 1", null, null),
new TreeItem("Item 2", null, null),
new TreeItem("Item 3", null, null),
new TreeItem("Item 4", null, new ObservableCollection<TreeItem>
{
new TreeItem("Item 41", null, null),
new TreeItem("Item 42", null, new ObservableCollection<TreeItem>
{
new TreeItem("Item421", null, null)
})
}),
new TreeItem("Item 5", null, null)
};
}
}
Next you have to create an instance of the TreeControlViewModel
and assign it to the TreeControl
user control, so you can bind to its TreeItems
property, which is the collection for the TreeView
.
<UserControl x:Class="test.TreeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="200"
d:DesignWidth="100">
<UserControl.DataContext>
<local:TreeControlViewModel/>
</UserControl.DataContext>
<!-- ...your tree view XAML code. -->
</UserControl
At last, be sure to actually bind to the TreeItems
collection via ItemsSource
, otherwise no items are displayed.
<TreeView Name="TVTree" ItemsSource="{Binding TreeItems}">
As a note, ObservableCollection
will notify and trigger updating the TreeView
when you modify the collection of items with e.g. Add
or Remove
. If you are interested in modifiying properties like Header
, too, you should have a look at INotifyPropertyChanged
an how it is implemented to enable updates for them in the user interface, too. For the sake of simplicity and focus on your issue I will skip this part.
Upvotes: 1
Reputation: 21241
Your bindings are looking for an Image
and Header
in the DataContext
, which would be your VM in standard MVVM WPF. If you check your output window in Visual Studio you will see binding errors to that effect.
You do not need your TreeViewItem
class, you are already defining the view for a tree item with your template.
You do need a TreeItemVM
to bind to. Add your properties in there instead. They should be data only. No visual classes.
Upvotes: 0