Binding Between elements inside DataTemplate - wpf

How can I make binding between properties of two elements inside dataTemplate ?
example :
// Bind Text property to Content property
<DataTemplate>
<TextBox Text="{Binding}" />
<Label Content="{Binding}" />
</Datatemplate>

If I correctly understood.
<DataTemplate>
<TextBox x:Name="p_text" Text="{Binding login}"/>
<Button Content="{Binding ElementName=p_text, Path Text}"/>
</DataTemplate>

Related

WPF binding from ListBox ItemTemplate

I have a problem binding from ListBox Itemtemplate that contains an Expander with its own HeaderTemplate and ContentTemplate.
<ListBox ItemsSource="{Binding Feeds}">
<ListBox.ItemTemplate>
<DataTemplate>
<Expander Content="{Binding Text}"
Header="{Binding Title}">
<Expander.HeaderTemplate>
<DataTemplate>
<DockPanel >
<TextBlock Text="{Binding PublishDate}" />
<TextBlock Text="{Binding}" />
</DockPanel>
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Source="{Binding ImageURL}" />
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Expander.ContentTemplate>
</Expander>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The PublishDate and ImageURL bindings don't work and I'd like to bind them to properties in the object Feed:
Public Class Feed
Public Property Title As String
Public Property PublishDate As DateTime
Public Property Text As String
Public Property ImageURL As String
End Class
I tried FindAncestor in the binding to find the ListBoxItem but it didn't help me.
the Content of the Expander serves as the DataContext for the ContentTemplate and the Header for the HeaderTemplate.
Set Content="{Binding}" and Header="{Binding}" instead. This sets the DataContext of both templates to the DataContext of the ListBoxItem (i.e. a Feed).

WPF binding Listbox layoutpanel

I´m using devexpress and I want to do a binding with a Listbox, but I have an error. Here my code:
<ListBox x:Name="_list" >
<ListBox.ItemTemplate>
<DataTemplate>
<dxd:LayoutPanel
Caption="{Binding nameList}"
AllowHide ="False" AllowFloat="False"
GotFocus="panel_GotFocus" >
<TextBox Text="Hello" />
</dxd:LayoutPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
With this code, Caption {Binding nameList} is empty.
I have tried this.
<ListBox x:Name="_list" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBox Text="{Binding nameList}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this case, text in TextBox is correct, I need to use the first code.
You seem to be a bit confused about how to use this ListBox. First, you need a collection property to bind to the ListBox.ItemsSource property. Let's say you have a collection of User objects called Users:
<ListBox ItemSource="{Binding Users}" />
Now we want to define how each User should be displayed... all the properties of the User class will be available to the Binding inside the DataTemplate. Let's say that the User class has two properties; Name and Age:
<DataTemplate DataType="{x:Type YourDataTypeNamespace:User}">
<StackPanel>
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
Then putting it all together:
<ListBox ItemSource="{Binding Users}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type YourDataTypeNamespace:User}">
<StackPanel>
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Bind to other element in a stackpanel without name

I'm creating a DataTemplate in WPF, so it won't compile if I use x:Name. This is the relevant part of my code:
<DataTemplate>
<StackPanel>
<Image .../>
<Textbox Width={Binding to image?, Path=ActualWidth} />
</StackPanel>
</DataTemplate>
How can I bind to the Image without the use of name?
You can use RelativeSource:
<DataTemplate>
<StackPanel>
<Image Source="{Binding Photo}"/>
<TextBox Width="{Binding Path=Children[0].ActualWidth, Mode=OneWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel, AncestorLevel=1}}" />
</StackPanel>
</DataTemplate>
You can't directly binding to Image but you can do that with StackPanel and property Children.

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>

Binding in Label.ContentTemplate

In the Xaml below, the first control (the TextBlock by itself) has no problem binding and rendering the value of RecordCount. But in the second control (the Label with the ContentTemplate), the value of RecordCount is not rendered. However, the literal "Cars" is rendered fine. So I know the ContentTemplate is working, but the binding to RecordCount from within the ContentTemplate is not. What am I doing wrong?
<TextBlock Text="{Binding RecordCount}"/>
<Label HorizontalAlignment="Center" >
<Label.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Width="100">
<TextBlock Text="{Binding RecordCount}"/>
<TextBlock Text=" Cars"/>
</StackPanel>
</DataTemplate>
</Label.ContentTemplate>
</Label>
Set the Content property on the Label to the current DataContext:
<Label HorizontalAlignment="Center" Content="{Binding}">
or, set the StackPanel as the Content and don't use a template at all:
<Label HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal" Width="100">
<TextBlock Text="{Binding RecordCount}"/>
<TextBlock Text=" Cars"/>
</StackPanel>
</Label>
The ContentTemplate is used to present the Content. Since it is null, the DataContext is null when your template is instantiated. The TextBlocks are still created, so Cars is rendered, but null doesn't have a RecordCount property so the first text block is rendered with no text.
Also, if you are only using two TextBlocks to concatenate text, you can use the StringFormat property in .NET 3.5 SP1 or later:
<Label Content="{Binding RecordCount}" ContentStringFormat="{}{0} Cars"/>
Just an alternative, you can bind the RecordCount to Label's Content and have DataTemplate takes care on how you are going to show it.
<Label HorizontalAlignment="Center" Content="{Binding RecordCount}" >
<Label.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Width="100">
<TextBlock Text="{Binding}"/>
<TextBlock Text=" Cars"/>
</StackPanel>
</DataTemplate>
</Label.ContentTemplate>
</Label>

Resources