Is it possible to attach different DataTemplates so that the children render differently to the same HierarchicalDataTemplate, which as I understand controls the View of the header
I am trying to do it without success::
<Window.Resources>
<DataTemplate
x:Key="ChildTemplate1">
<Label Content="Blah">
</DataTemplate>
<DataTemplate
x:Key="ChildTemplate2">
<Label Content="Blah2">
</DataTemplate>
<HierarchicalDataTemplate
x:Key="RootTemplate"
ItemTemplate={StaticResource ChildTemplate2}"
ItemsSource="{Binding Path=Children}">
<Label Content="Header">
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView ItemTemplate="{StaticResource RootTemplate}">
<TreeViewItem ItemTemplate="{StaticResource ChildTemplate1}"/>
</TreeView>
So again, what I am trying to do is override the DataTemplate set in HierarchicalDataTemplate(ChildTemplate2) with ChildTemplate1
Related
I have a TabControl which defines some data templates to show content based on the selected tab.
<TabControl
Grid.Row="1"
ItemsSource="{Binding ExerciseViewModels}"
SelectedItem="{Binding SelectedExercise}">
<TabControl.Resources>
<DataTemplate DataType="local:SubtractExerciseViewModel">
<local:SubtractUserControl/>
</DataTemplate>
<DataTemplate DataType="local:SumExerciseViewModel">
<local:SubtractUserControl/>
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
But when I run, the selected tab shows the name of the ViewModel (thus the DataTemplate for the specific type is not used).
What am I missing?
PS: Using MvvmLight but not really of any relevance. All the view models obviously exist (see screenshot, it has the reference to an object of type SuusRekenWonder.SumExerciseViewModel). So I am doing something wrong in XAML. But what?
In your TabControl-Resources you have to use x:Type for your DataType. Then your Resources look like:
<TabControl.Resources>
<DataTemplate DataType="{x:Type local:SubtractExerciseViewModel}">
<local:SubtractUserControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:SumExerciseViewModel}">
<local:SubtractUserControl/>
</DataTemplate>
</TabControl.Resources>
Given ResourceDictionary:
<GroupBox x:Key="Group"
x:Shared="False">
<ItemsControl ItemsSource="{Binding Items}">
...
</ItemsControl>
</GroupBox>
<ItemsControl x:Key="Test"
x:Shared="False"
ItemsSource="{Binding Items}">
...
</ItemsControl>
Both ItemsControl content is identical. Is it possible to avoid duplicating same xaml (... is quite big)? Is it possible to create Test instance from within Group.
You could use a ContentControl:
<ItemsControl x:Key="Test"
x:Shared="False"
ItemsSource="{Binding Items}">
</ItemsControl>
<GroupBox x:Key="Group" x:Shared="False">
<ContentControl Content="{StaticResource Test}" />
</GroupBox>
Note that the ItemsControl resource must be defined before the GroupBox resource.
As pointed out by #grek40, you could also set the Content property of the GroupBox directly to the ItemsSource resource provided that the GroupBox doesn't contain any other controls.
Actually, you can directly set the content
<GroupBox x:Key="Group" x:Shared="False" Content="{StaticResource Test}">
I'm not really a fan of x:Shared (bugged me some times), so how about using some DataTemplate instead?
<DataTemplate x:Key="TestTemplate">
<ItemsControl ItemsSource="{Binding Items}">
<!-- Whatever it is you have inside... -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Background="Yellow"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
<GroupBox Content="{Binding}" ContentTemplate="{StaticResource TestTemplate}">
</GroupBox>
I am confused of WPFs data binding and style declaration for TreeViews, especially for child nodes.
My ViewModel contains an object with the following hierarchy:
- Component1
- SubcomponentA
- SubcomponentB
- Component2
- SubcomponentX
- SubcomponentY
- SubcomponentZ
I would like to modify the XAML file so I do not have to do anything within the .cs file.
This piece of code actually works:
<TreeView Name="tvComponent" ItemsSource="{Binding BpModule.BpComponentPrototypes.Elements}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding BpSubcomponents.Elements}">
<StackPanel Orientation="Horizontal">
<CheckBox Name="cb_run"></CheckBox>
<TextBlock Text="{Binding ShortName}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
However, I would like to create different styles for root and child nodes.
I tried different approaches with almost completely different XAML code. But the major problem was to describe the dependency of the binding of child nodes to their parent and so they remained empty during runtime.
Can you help me out?
Thank you.
In my opinion you can use the implicit DataTemplate mechanism (take a look here to the DataType property). In this way you can define more DataTemplates, each one of them "linked" to a specific Type.
<TreeView Name="tvComponent" ItemsSource="{Binding BpModule.BpComponentPrototypes.Elements}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:RootType}"ItemsSource="{Binding ...}">
...
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:ComponentType}" ItemsSource="{Binding BpSubcomponents.Elements}">
<StackPanel Orientation="Horizontal">
<CheckBox Name="cb_run"></CheckBox>
<TextBlock Text="{Binding ShortName}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:SubcomponentType}">
...
</DataTemplate>
</TreeView.Resources>
</TreeView>
Otherwise you can always use a DataTemplateSelector to create your own logic which chooses the right template for you.
Well, somehow I achieved to provide different designs for root and children nodes. Here is the XAML code:
<TreeView Name="tvSoftwareComponentPrototypes" ItemsSource="{Binding Path=BpModule.BpComponentPrototypes.Elements}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding BpSubcomponents.Elements}">
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="cb_run"></CheckBox>
<Image Source="/Resources/SubComponent.png" Margin="5,0,3,0" />
<TextBlock Text="{Binding ShortName}" />
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="cb_swc" Checked="cb_swc_Checked" Unchecked="cb_swc_Unchecked"></CheckBox>
<Image Source="/Resources/Component.png" Margin="5,0,3,0" />
<TextBlock Text="{Binding ShortName}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
And the next problem is that I cannot access the Checkboxes at runtime.
WPF freaks me out :/
EDIT:
Hold on .. actually this is quite easy by changing the checkbox to the following XAML code:
<CheckBox Name="cb_swc" IsChecked="{Binding Path=PropertyName, Mode=TwoWay}"/>
This is a logging project, the Title provides the name of the item and the message logs each stage. Therefore, there are many Messages for each Title.
For the purpose of asking a question, I am simplifying my objects.
My Log class has 2 properties.
List<LogDetails>
string Title
And my LogDetails class has 1 property:
string Message
I am not able to bind the Message to my XAML. The Title binds as desired.
My xaml code:
<Window x:Class="BackUps.Logging.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myData="clr-namespace:BackUps.Logging"
Title="MainWindow"
Height="350"
Width="525">
<Grid>
<TreeView ItemsSource="{Binding}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type myData:Log}"
ItemsSource="{Binding LogDetailsList}">
<TextBlock Text="{Binding Title}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="{x:Type myData:LogDetails}">
<StackPanel>
<TextBlock Text="{Binding Message}" />
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
and my code behind
public MainWindow(List<Log> logs)
{
InitializeComponent();
this.DataContext = logs;
}
My result is (where you can see the missing entries):
This is the Auto's window, which shows the object I'm trying to bind.
What have I missed or doing wrong?
I had a similar problem in the past, and fixed it by (completely) changing the xaml to the form:
<Grid>
<TreeView ItemsSource="{Binding}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type myData:Log}"
ItemsSource="{Binding LogDetailsList}">
<TextBlock Text="{Binding Title}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type myData:LogDetails}>
<TextBlock Text="{Binding Message}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
I have a 4-level tree structure, defined by:
<HierarchicalDataTemplate DataType="{x:Type src:Level1}" ItemsSource="{Binding Path=Level2Items}">
<TextBlock Text="{Binding Path=Level1Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type src:Level2}" ItemsSource="{Binding Path=Level3Items}">
<TextBlock Text="{Binding Path=Level2Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type src:Level3}" ItemsSource="{Binding Path=Level4Items}">
<TextBlock Text="{Binding Path=Level3Name}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type src:Level4}">
<TextBlock Text="{Binding Path=Level4Name}"/>
</DataTemplate>
And it works great. The only thing is, I can't programmatically select any of my bound items, because they're not of type TreeViewItem (and therefore don't have the "IsSelected" property). Is there a way to automatically wrap databound items in a particular container type (in this case: TreeViewItem)?
If your items are in a TreeView, they'll be wrapped in a TreeViewItem automatically by the TreeView's ItemContainerGenerator. You can do something like this to ensure the IsSelected property on TreeViewItem maps to a property on your data class:
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected" Value="{Binding MyIsSelectedProperty}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>