Syntax to bind to the current dataitem's default indexer in WPF? - 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?

Related

Binding a string doesn't show up, Binding another type does... WPF

I just started with WPF and databinding. First question on databinding.
Databinding on {Binding Periode.Einde} where Einde is of type DateTime works,
{Binding Arrangement} where Arrangement is of type Enum works, {Binding Limo.Info} where Info is of type String doesn't work.
Somebody has an explanation for that?
<ListView Grid.Column="3" Grid.Row="3" Name="hups" Background="{x:Null}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Background="BlueViolet" Opacity="80" DockPanel.Dock="Left">
<Image Source="images\limousine-car-VIP-transport-128.png" Height="50"/>
<StackPanel>
<TextBlock Text="Starttijdstip:" />
<TextBlock Text="{Binding Periode.Begin, ConverterCulture='nl-BE', StringFormat='dddd, dd MMMM yyyy HH:mm:ss'}" FontWeight="Bold" />
<TextBlock Text="Stoptijdstip:" />
<TextBlock Text="{Binding Periode.Einde, ConverterCulture='nl-BE', StringFormat='dddd, dd MMMM yyyy HH:mm:ss'}" FontWeight="Bold" />
</StackPanel>
</StackPanel>
<StackPanel DockPanel.Dock="Right" Background="BlueViolet" HorizontalAlignment="Right">
<TextBlock Text="Limo:" />
<TextBlock Text="{Binding Limo.Info}" FontWeight="Bold" />
<TextBlock Text="Arrangement:" />
<TextBlock Text="{Binding Arrangement}" FontWeight="Bold" />
</StackPanel>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In your binding expression Text="{Binding Limo.Info}" then if Limo.Info is of type string, then there are only 3 possible scenarios as to why nothing appears in your UI
1) Limo object is null
2) Info string is null or empty
3) Limo.Info is spelled incorrectly, and it's actually something else.
It has to be one of those 3 scenarios. check the objects you are passing into your ListView
Indeed Limo is null. It's Entity Framework with Lazy Loading I think...

Orientating elements in a TreeView

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!

How to Bind with a StringFormat

I have a ComboBox which I am binding to an IEnumerable<int> source.
The source has values like 12,13,14 but I want the ComboBox to display Version 12, Version 13, Version 14 etc with SelectedValue still 12, 13 and 14.
For now I am modifying the Source to add Version to it and then Binding the ComboBox to an IEnumerable.
XAML
<ComboBox x:Name="ComboBoxVersions"
SelectedIndex="0"
SelectionChanged="ComboBoxVersions_OnSelectionChanged"
ItemsSource="{Binding EnvironmentVersions}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You could use something like this
<TextBlock Text="{Binding StringFormat=Version: {0}}" />
using ComboBox.ItemStringFormat:
<ComboBox ItemsSource="{Binding EnvironmentVersions}"
ItemStringFormat="version: {0}" />
or using ComboBox.ItemTemplate
<DataTemplate>
<TextBlock Text="{Binding StringFormat=Version: {0}}" />
</DataTemplate>
or
<DataTemplate>
<TextBlock>
<Run Text="Version " />
<Run Text="{Binding }"/>
</TextBlock>
</DataTemplate>
Here's a simple way:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Version " />
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
Since the ItemTemplate only defines how the items are displayed, the SelectedItem property of the ComboBox still holds the original value from your collection of version numbers.
You can add a string format to the binding in the datatemplate.
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding StringFormat=Version {0}}" />
</DataTemplate>
</ComboBox.ItemTemplate>

How to use converters without binding paths?

I have a Combobox whose ItemsSource is an ObservableCollection of int values.
My combobox itemtemplate consists on an image and a textblock which content is given by 2 converters.
How can I set this 2 bindings? The following code does not compile:
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding, Converter={StaticResource IntToImageConverter}}" Stretch="None" />
<TextBlock Text="{Binding, Converter={StaticResource IntToStringConverter}}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
You need to remove the , so:
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Converter={StaticResource IntToImageConverter}}" Stretch="None" />
<TextBlock Text="{Binding Converter={StaticResource IntToStringConverter}}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>

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>

Resources