<TreeView
x:Name="TreeView"
DataContext="{Binding ApplicationMenu, Mode=TwoWay}"
ItemsSource="{Binding ApplicationMenuNodes}"
Width="Auto"
FontFamily="Segoe UI"
BorderThickness="0"
BorderBrush="Transparent"
Background="Transparent"
>
<TreeView.Resources>
<HierarchicalDataTemplate
DataType="{x:Type businessobject:ApplicationMenu}"
ItemsSource="{Binding ApplicationMenuNodes}"
/>
</TreeView.Resources>
</TreeView>
I have a treeview with a hierarchical data template. This is bound to a collec tion of ApplicationMenu objects, each containing it's own collection of ApplicationMenu objects.
I'm trying to obtain the selected ApplicationMenu, but I can't seem to find an way to do so. I don't care if it's MVVM or code behind.
Any help would be greatly appreciated.
Related
So, I have a listview with different datatemplates as seen here:
<ListView Panel.ZIndex="0" x:Name="FilterList" Margin="10,0" Grid.Row="2"
Grid.ColumnSpan="3" Background="White" ItemTemplateSelector="{StaticResource
ReportFilterTemplateSelector}" ItemsSource="{Binding reportParameters,
Mode=TwoWay}" ScrollViewer.CanContentScroll="False">
One of my sample datatemplates can be seen below. Everything shows up great. My problem, is that for this (and other) datatemplates, I can have multiple instances of the same one. In this particular instance, the treeview itemssource is bound to DataContext.OfficeListText to populate all the elements.
<DataTemplate x:Key="office">
<Grid MinHeight="35" MaxHeight="250">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding rpName}" VerticalAlignment="Center" Grid.Row="0" Grid.Column="0" />
<Expander HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1"
Header="{Binding Path=DataContext.OfficeListText, RelativeSource=
{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
VerticalAlignment="Top" ExpandDirection="Down">
<TreeView Tag="{Binding rpParameter}" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" ItemsSource="{Binding
Path=DataContext.OfficeList, RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type UserControl}}, Mode=TwoWay}"
ItemTemplate="{StaticResource CheckBoxItemTemplate}"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"/>
</Expander>
</Grid>
</DataTemplate>
The main problem with this is one, for instance, if I select an office in say the first treeview, the 2nd treeview shows the same. Essentially I want them to have the same itemssource initially but have separate instances. Since they are generated dynamically that is where I'm getting stuck. Any help would be appreciated.
I'm not sure what other code would be necessary, since I'm sure most of it will be irreverent based on what I'll need to do to make this work, but if you would like more I will gladly provide. Thanks!
Currently your TreeView binds to a single instance of OfficeList that belongs to your UserControl's DataContext. This means that every TreeView points to the same list. If I understand your question correctly, what you really want is to have a different instance of OfficeList for each TreeView.
I don't recommend instantiating a new OfficeList each time the DataTemplate is applied to a reportParameter. You could do that with a ValueConverter, but it would be pretty hacky.
The cleaner solution would be to have a class that contains the data for your reportParameter, plus an instance of OfficeList, and then bind to instances of that class instead of binding to the UserControl. Depending on how the reportParameters are structured (I am going to assume that reportParameters is a list of objects of type ReportParameter), there are two ways you might want to do this:
1) If ReportParameter is a ViewModel, you can simply add an OfficeList property to the ReportParameter class, and initialize it when you instantiate each ReportParameter.
Then your TreeView would look like this:
<TreeView Tag="{Binding rpParameter}" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" ItemsSource="{Binding Path=OfficeList, Mode=TwoWay}"
ItemTemplate="{StaticResource CheckBoxItemTemplate}"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"/>
2) If ReportParameter is not a ViewModel (and thus it would not be appropriate to add an OfficeList parameter), then create a new class called something like ReportParameterViewModel that contains 2 properties: ReportParameter and OfficeList. Instead of binding your ListView to a list of ReportParameter, bind to a list of ReportParameterViewModel.
Then your ListView will look something like this:
<ListView Panel.ZIndex="0" x:Name="FilterList" Margin="10,0" Grid.Row="2"
Grid.ColumnSpan="3" Background="White" ItemTemplateSelector="{StaticResource
ReportFilterTemplateSelector}" ItemsSource="{Binding reportParameterViewModels,
Mode=TwoWay}" ScrollViewer.CanContentScroll="False">
Your TextBlock will look like this:
<TextBlock Text="{Binding ReportParameter.rpName}" VerticalAlignment="Center" Grid.Row="0" Grid.Column="0" />
Your TreeView will look like this:
<TreeView Tag="{Binding rpParameter}" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" ItemsSource="{Binding Path=OfficeList, Mode=TwoWay}"
ItemTemplate="{StaticResource CheckBoxItemTemplate}"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"/>
I've started to learn about WPF. And I've chosen to build simple ItemStructureCreator.
I am using MVVM pattern as well.
I implemented some classes, and faced an problem to properly bind it to my TreeView.
Now I want my StructureManagerView to have TreeView control assosiated with my structure.
I tried to bind it like this:
<TreeView Name="tree" DataContext="{Binding MainItem}" Grid.Column="0" Background="Beige">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Item.Children}">
<TextBlock Text="{Binding Item.Code}" HorizontalAlignment="Stretch"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Or like this (Here I think is wrong cause ItemsSource property expects collection):
<TreeView Name="tree" ItemsSource="{Binding MainItem}" Grid.Column="0" Background="Beige">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Item.Children}">
<TextBlock Text="{Binding Item.Code}" HorizontalAlignment="Stretch"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Can you please help me to set Bindigs correctly.
Regards, Dmitry.
Converting My comment into an answer:
The TreeView doesn't have the concept of a "Main Item".
You should Bind the ItemsSource Property of the TreeView Itself.
ItemsSource="{Binding MainItem}"
should be replaced by
ItemsSource="{Binding MainItems}"
where MainItems is an IEnumerable
I have a TreeView bound to an MVVM observable collection.
My item template is composed by an image and a textblock like the following code show:
<HierarchicalDataTemplate x:Key="TreeViewItemTemplate" ItemsSource="{Binding Items, Mode=OneWay, NotifyOnSourceUpdated=True}">
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<Image
Margin="-20,0,5,0"
Source="{Binding Icon, Converter={StaticResource TreeViewIconConverter}, Mode=OneWay}"
Style="{DynamicResource SmallIcon}"/>
<Label Content="{Binding Label}"/>
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
</HierarchicalDataTemplate>
The problem happens when you Click over an item. If the Mouse cursor is over the StackPanel, the selection will not happen.
I have included also a screenshot to make this more clear.
Of course this happens because the StackPanel is now over the selection area.
Is there any workaround?
I found the answer by myself.
When you customize the TreeView using an hierarchical data template then you should not replicate the TreeViewItem.Header template because at runtime WPF will create one for you.
So, in order to have a custom TreeViewItem this code is enough:
<HierarchicalDataTemplate x:Key="TreeViewItemTemplate" ItemsSource="{Binding Items, Mode=OneWay, NotifyOnSourceUpdated=True}">
<StackPanel Orientation="Horizontal">
<Image
Margin="0,0,5,0"
Source="{Binding Icon, Converter={StaticResource TreeViewIconConverter}, Mode=OneWay}"
Style="{DynamicResource SmallIcon}"/>
<Label Content="{Binding Label}"/>
</StackPanel>
</HierarchicalDataTemplate>
I have a treeview inside of a dockpanel and all of the elements of the treeview are inside HierarchicalDataTemplates. Here is the code:
<DockPanel Margin="10,10,0,0" VerticalAlignment="Stretch" Grid.Row="0" Grid.RowSpan="5" Grid.Column="0">
<DockPanel.Resources>
<src:TreeViewFilter x:Key="MyList" />
<HierarchicalDataTemplate DataType="{x:Type src:TreeViewParent}" ItemsSource="{Binding Path=OrderAttributes}">
<TextBlock Text="{Binding Path=Name}" FontSize="24"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type src:OrderAttribute}" ItemsSource="{Binding Path=OrderAttributes}">
<TextBlock Text="{Binding Path=NameAndCount}" FontSize="16"/>
</HierarchicalDataTemplate>
</DockPanel.Resources>
<TreeView Name="treeView1" BorderThickness="2" ItemsSource="{Binding Source={StaticResource MyList}, UpdateSourceTrigger=PropertyChanged}" TreeViewItem.Selected="treeViewFilter"/>
</DockPanel>
As you can see, the DockPanel wraps around the TreeView. The icons I am trying to add would be in the second HierarchicalDataTemplate which binds to a string and displays as a textbox. Depending on the name of the "NameAndCount", I would choose an icon to be displayed next to it on the left.
Any ideas on a solution for my example? Or do I need to think about using different templates like StackPanel?
Add an Image-Control wherever you want, bind its Source to "NameAndCount" and use a IValueConverter to convert it to an image-path.
I have a ``TreeViewwhich uses a customItemsPanelto show the first level of items in aStackPanel, but I need to show subitems in aStackPaneltoo. The problem is, the second level of items are shown in aWrapPanel, and asHierarchicalDataTemplatedoesn't have anItemsPanel` property I'm not sure how to do this. This is my xaml:
<TreeView x:Name="treGlobalCards">
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True" Orientation="{Binding Orientation,RelativeSource={x:Static RelativeSource.TemplatedParent}}"
MaxWidth="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType={x:Type ScrollContentPresenter}}}"/>
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate x:Key="CardTypeTemplate" ItemsSource="{Binding Cards}">
<TextBlock Text="{Binding Path=CardType}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Create a new DataTemplate that uses a StackPanel and set the HierachicalDataTemplate's "ItemTemplate" to that new DataTemplate.
i.e.
<DataTemplate x:Key="someTemp">
<StackPanel />
</DataTemplate>
<HierarchicalDataTemplate x:Key="hierTemp" ItemSource="{Binding}" ItemTemplate="{StaticResource someTemp}" />