Orientating elements in a TreeView - wpf

I have a TreeView in my XAML, each element of which is a StackPanel which allows each element to have an image and some text. They are orientated one atop the other as you can see here.
What I would like, and this may not be possible with a TreeView, is for the items (in this case 'FamilyMember') to appear horizontally rather than vertically. So, for example, you click the drop down for the family - you don't see them in a vertical list but in a horizontal one.
The XAML is as follows:
<TreeView Name="trvFamilies">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type self:Family}" ItemsSource="{Binding Members}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageGroup}" Margin="0,0,5,0" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" [" Foreground="Blue" />
<TextBlock Text="{Binding Members.Count}" Foreground="Blue" />
<TextBlock Text="]" Foreground="Blue" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type self:FamilyMember}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" (" Foreground="Green" />
<TextBlock Text="{Binding Age}" Foreground="Green" />
<TextBlock Text=" years)" Foreground="Green" />
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
Any attempts made within the DataTemplate element only apply to each of the vertically aligned elements.
Maybe my efforts are on the wrong track if this is my goal. If so, if an alternative panel or control is better than I will gladly use it.
Thanks!

Related

Getting selected item from Treeview

I have a TreeView and want to get the selected item from it.
The Treeview itself is populated not manually, but from data in the code. Since it is populated this way, I'm not sure how to get information out of it.
Here is the XAML:
<TreeView Name="trvFamilies" HorizontalAlignment="Left" Margin="10,10,3,3" Width="340">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type self:Scene}" ItemsSource="{Binding Characters}">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="New" Click="MenuItem_Click"></MenuItem>
<MenuItem Header="Remove" Click="MenuItem_Click_1"></MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
<Image Source="{StaticResource ImageSceneRegular}" Margin="0,0,5,0" Width="64" Height="64"/>
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" [" Foreground="Blue" />
<TextBlock Text="{Binding Characters.Count}" Foreground="Blue" />
<TextBlock Text="]" Foreground="Blue" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type self:Character}">
<Border BorderThickness="1" Background="AliceBlue" CornerRadius="8,8,3,3">
<StackPanel Orientation="Horizontal" Margin="4" Background="White">
<Image Source="{Binding Img}" Margin="0,0,5,0" Width="64" Height="64" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" (" Foreground="Green" />
<TextBlock Text="{Binding Age}" Foreground="Green" />
<TextBlock Text=" years)" Foreground="Green" />
</StackPanel>
</Border>
</DataTemplate>
</TreeView.Resources>
</TreeView>
It is populated by data from an ObservableCollection which is populated within the code and then assigned to the ItemSource of the treeview (and it works fine).
So let's say I had a TextBlock which sat outside the TreeView and wanted to populate it with information from the selected Character (that's the type which populates the drop down part of the TreeView), I don't know how to do that, be it using XAML only or code behind.
Any help on how to do this would be very much appreciated.

Alignment in ListViewItem using DataTemplate

I'm using a ListView to show person first name and last name.
I want to align the first name to the left and the last name to the right
I wrote the following code:
<Windows.Resources>
<DataTemplate Datatype="{x:Type local:Person}">
<StackPanel Orientation="Horizontel">
<TextBlock Text="{Binding Path=FirstName}" TextAlignment="Left">
<TextBlock Text="{Binding Path=LastName}" TextAlignment="Right">
</StackPanel>
</DataTemplates>
</Windows.Resources>
<ListView Name="myList", ItemSource="{Binding}" />
The ListView.DataContext connected to ObservableCollection
The result is that both first name and last name align to the left.
I also tried to use DockPanel(How to make DockPanel fill available space)
but it doesnt work.
Thanks,
I found the solution in this post: [https://www.stackoverflow.com/questions/10765652/how-to-right-align-content-in-a-datatemplate][]
<Windows.Resources>
<DataTemplate DataType="{x:Type local:Person}">
<Grid>
<Grid.ColumnDefinition>
<ColumDefinition Width="*" />
<ColumDefinition Width="Auto" />
</Grid.ColumnDefinition>
<TextBlock Text="{Binding Path=FirstName}" Grid.Column="0">
<TextBlock Text="{Binding Path=LastName}" Grid.Column="1">
</Grid>
</DataTemplates>
</Windows.Resources>
<ListView Name="myList", ItemSource="{Binding}" HorzintalContentAlignment="Strech" />
You can use DockPanel for it
<Windows.Resources>
<DataTemplate DataType="{x:Type local:Person}">
<DockPanel>
<TextBlock Text="{Binding Path=FirstName}" HorizontalAlignemnt="Left">
<TextBlock Text="{Binding Path=LastName}" HorizontalAlignemnt="Right">
</DockPanel>
</DataTemplates>
</Windows.Resources>
<ListView Name="myList", ItemSource="{Binding}" HorzintalContentAlignment="Strech" />

Data Binding with WPF

I'm new to WPF and this following has stumped me for a while now:
I have an observableCollection of People object in my model that is bound to my tabControl. So each my a new People object is added, a new tab is created with People.Title as the Tab's header.
Each People object has an ObservableCollection of Friend object. Inside of the Tab I would like to have a List of two textboxes, one for Friend.FirstName and another for Friend.LastName.
My first requirement is working fine, but the second one is giving me an error 'ItemsSource is already in use'
Here's my code so far:
<TabControl Name="ConversationTabs" Grid.Row="0"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource HeaderInfoTabControl}"
ContentTemplate="{StaticResource DialogueList}" />
<Window.Resources>
<DataTemplate x:Key="HeaderInfoTabControl">
<TextBlock Text="{Binding Title}" />
</DataTemplate>
<DataTemplate x:Key="DialogueList">
<ItemsControl ItemsSource="{Binding Path=DialogueCollectionVM}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Sent}" />
<TextBlock Text="{Binding Path=DateSent}" />
<TextBlock Text="{Binding Path=Message}" />
</StackPanel>
</ItemsControl>
</DataTemplate>
</Window.Resources>
I appreciate your help.
You cannot add items to an ItemsControl and use the automatic population (via ItemsSource) at the same time. If that StackPanel is supposed to be used for the items in the ItemsSource you should do this:
<ItemsControl ItemsSource="{Binding Path=DialogueCollectionVM}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Sent}" />
<TextBlock Text="{Binding Path=DateSent}" />
<TextBlock Text="{Binding Path=Message}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

How to reuse contents in wpf/mvvm

I have a UI that displays a pattern of "first name/last name". So I thought I would reuse the same template. But I am facing some issues getting the binding right.
Note:-
PrimaryContactDataContext is nothing but a class, with a property named "value" which implements the *INotifyPropertyChanged" interface.
<StackPanel>
<ContentControl DataContext="{Binding Path=PrimaryContactDataContext.Value,Mode=TwoWay}" ContentTemplate="{StaticResource PersonalDetailsTemplate}" />
</StackPanel>
// See the Reusable template below
<UserControl.Resources>
<DataTemplate x:Key="PersonalDetailsTemplate" >
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Width="30" Text="Name"></TextBlock>
<TextBox Width="110" Text="{Binding LastName}" IsReadOnly="True"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Width="30" Text="Title"></TextBlock>
<TextBox Width="110" Text="{Binding firstName}" IsReadOnly="True"></TextBox>
</StackPanel>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
Set the Content of the ContentControl, not its DataContext:
<ContentControl Content="{Binding Path=PrimaryContactDataContext.Value,Mode=TwoWay}" ContentTemplate="{StaticResource PersonalDetailsTemplate}" />

Syntax to bind to the current dataitem's default indexer in WPF?

I have a Listbox with an itemssource set to an ObservableCollection of DataRow. Let's say each DataRow has 5 columns for this example.
In the DataTemplate of the ListBox I have 5 textblocks (1 for each column). My question is how can I bind to an indexer of the row to get the columns value?
Here is my attempt but nothing displays so I must have the syntax wrong:
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=.[0]}" />
<TextBlock Text="{Binding Path=.[1]}" />
<TextBlock Text="{Binding Path=.[2]}" />
<TextBlock Text="{Binding Path=.[3]}" />
<TextBlock Text="{Binding Path=.[4]}" />
</StackPanel>
</DataTemplate>
I know that indexers can be used in bindings because I've done something like this already:
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Collection[0].Name}" />
<TextBlock Text="{Binding Path=Collection[1].Name}" />
<TextBlock Text="{Binding Path=Collection[2].Name}" />
<TextBlock Text="{Binding Path=Collection[3].Name}" />
<TextBlock Text="{Binding Path=Collection[4].Name}" />
</StackPanel>
</DataTemplate>
Any help on correcting my syntax would be appreciated.
Your syntax should do. However, the following must go also:
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=[0]} />
<TextBlock Text="{Binding Path=[1]} />
<TextBlock Text="{Binding Path=[2]} />
<TextBlock Text="{Binding Path=[3]} />
<TextBlock Text="{Binding Path=[4]} />
</StackPanel>
</DataTemplate>
Check your ItemsSource. Does it really provide an indexer that is of type int? Maybe you have an indexer of another type or even no index. Maybe it's another object than you expect it to be?

Resources