How can I get multibinding to work in XAML ListBox? - xaml

The following shows me 3x "MultiTest.Model.Customers" in the ListBox (one for each record it should display).
What do I need to change in order for it to output the contents of the fields instead?
<Window.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContentTemplate" >
<Setter.Value>
<MultiBinding StringFormat="{}{1}, {0} ">
<Binding Path="FirstName" />
<Binding Path="LastName"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox x:Name="theCustomers"/>
</Grid>
binding in code-behind with ADO.NET Entity Framework:
MainEntities db = new MainEntities();
var customers = from c in db.CustomersSet
select c;
theCustomers.ItemsSource = customers;
ANSWER:
Thanks, Steve, here is your answer in my Window.Resources format:
<Window.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{1}, {0} ({2})">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
<Binding Path="ID"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox x:Name="theCustomers"/>
</Grid>

If you particularly want to use MultiBinding you should be able to use a DataTemplate with StringFormat.. something like:
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{1}, {0}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Or for something more complicated you could use a ValueConverter (or the multiple binding variant).

I've never used MultiBinding before. I have used, however, DataTemplates:
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"></TextBlock>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Email}" Margin="5,0"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Hope this helps!

Related

How to set up a binding from DataGridColumns to a multi-selection ComboBox?

I have a DataGrid and a custom ComboBox. The ComboBox used a ListBox to enable multi-select.
I intend to give a ObservableCollection<Data> Datas property as the data source for the ComboBox,where Data is a class with string name and bool checked. The problem is how to set up each column's visibility to a corresponding CheckBoxwhich used a Dataas its source ?
<Style x:Key="CheckBoxListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid x:Name="RootElement">
<CheckBox ClickMode="Press" Content="{Binding Path=Name}" IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Foreground="White"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I saw some post used something like the xmal below, but obviously I do not has any ElementName here.
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
Visibility="{Binding IsChecked,
Converter={StaticResource visibilityConverter},
ElementName=chkShowPrice}"/>
This binding is not straight forward as it looks. Since DataGridTextColumn does not fall in the same visual tree as DataGrid, so it is not possible to bind the Visibility of the column directly. However, a bit tricky approach but you may use x:Reference for the same.
Here is how we can do it
XAML
<!--I added this element to provide the DataContext by using x:Reference-->
<FrameworkElement x:Name="contextProvider" />
<DataGrid Grid.Column="1"
AutoGenerateColumns="False"
ItemsSource="{Binding DD}"
x:Name="dg"
Style="{StaticResource DataGridDemoStyle}">
<DataGrid.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</DataGrid.Resources>
<i:Interaction.Behaviors>
<behavior:DataGridDropBehavior></behavior:DataGridDropBehavior>
</i:Interaction.Behaviors>
<DataGrid.Columns>
<DataGridTextColumn x:Name="Column3"
Binding="{Binding Symbol}"
Header="Symbol"
Width="*"
IsReadOnly="True"
Visibility="{Binding DataContext.Data[0].IsSelected, Source={x:Reference contextProvider}, Converter={StaticResource BooleanToVisibilityConverter}}" />
<DataGridTextColumn x:Name="Column4"
Binding="{Binding Ask}"
Header="Ask"
Width="*"
IsReadOnly="True"
Visibility="{Binding DataContext.Data[1].IsSelected, Source={x:Reference contextProvider}, Converter={StaticResource BooleanToVisibilityConverter}}" />
<DataGridTextColumn x:Name="Column5"
Binding="{Binding Bid}"
Header="Bid"
Width="*"
IsReadOnly="True"
Visibility="{Binding DataContext.Data[2].IsSelected, Source={x:Reference contextProvider}, Converter={StaticResource BooleanToVisibilityConverter}}" />
<DataGridTextColumn x:Name="Column6"
Binding="{Binding Volume}"
Header="Vol"
Width="*"
IsReadOnly="True"
Visibility="{Binding DataContext.Data[3].IsSelected, Source={x:Reference contextProvider}, Converter={StaticResource BooleanToVisibilityConverter}}" />
</DataGrid.Columns>
</DataGrid>
I have binded the items from the same Data bound to multi select combo box to the visibility of the columns
changed the following so that the DataContext is available to all the elements instead of just datagrid.
dg.DataContext = d;
to
DataContext = d;
lastly to enable the IsChecked binding modify the CheckBox from
<CheckBox ClickMode="Press" Content="{Binding Path=Name}" IsChecked="true" Foreground="White"/>
to
<CheckBox ClickMode="Press" Content="{Binding Path=Name}" IsChecked="{Binding IsSelected}" Foreground="White"/>
that's all you need for such binding.
here is the link to the provided sample project DataGridColumnsVisibilityBinding.zip
Let me know if this helps.

How to bind the items count of listview in XAML

I have a problem with binding the count to the textblock.
I have a listview that it's items are binded to a Users object properties.
I want to get the count of all items that were binded.
Here is my ListView:
<ListView ItemsSource="{Binding Users}" x:Name="lvUsers">
<ListView.ItemTemplate>
<DataTemplate>
<ListViewItem IsHitTestVisible="False">
<StackPanel>
<facebookControls:ProfilePicture Height="74" Width="74" ProfileId="{Binding FacebookId}" />
<TextBlock Text="{Binding UserName}" FontSize="18" HorizontalAlignment="Center" />
</StackPanel>
</ListViewItem>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And here is my TextBlock:
<TextBlock Text="{Binding ElementName=lvUsers, Path=Items.Count, Mode=OneWay}" />
What am I doing wrong?
I know that if my ListView will be without Templates, just ListViewItems, it will work, but I need it to be like that.
Override the template for this ListView.
The sample below basically creates a style where it overrides the control template such that the regular ListView items (the ItemsPresenter) is wrapped in the StackPanel so that the TextBlock with count or whatever else can be added at the bottom.
<ListView ItemsSource="{Binding Users}">
<ListView.Style>
<Style TargetType="{x:Type ListView}">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderThickness="1" BorderBrush="LightGray">
<StackPanel>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
<TextBlock Margin="0,4" FontWeight="Bold">
<Run Text="Count: "/>
<Run Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Path=Items.Count, Mode=OneWay}"/>
</TextBlock>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</ListView.Style>
<ListView.ItemTemplate>
<DataTemplate>
<ListViewItem IsHitTestVisible="False">
<StackPanel>
<facebookControls:ProfilePicture Height="74" Width="74" ProfileId="{Binding FacebookId}" />
<TextBlock Text="{Binding UserName}" FontSize="18" HorizontalAlignment="Center" />
</StackPanel>
</ListViewItem>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

ListView ItemTemplate 100% width

How can I make content of each ListView item expands to 100% width when using a DataTemplate?
I have tried HorizontalContentAlignment="Stretch" in the ListView and HorizontalAlignment="Stretch" in the DataTemplate, but nothing seems to work, content is still aligned to the left.
I have something like this:
<ListView x:Name="questionsView" Background="{StaticResource ApplicationPageBackgroundThemeBrush}" HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="BlueViolet" HorizontalAlignment="Stretch">
<Grid HorizontalAlignment="Stretch">
<TextBlock Text="{Binding}" />
<TextBlock HorizontalAlignment="Right">16 minutes ago</TextBlock>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I guess there is one more layer between the ListView and the ItemTemplate.
I got it. Setting the ListView.ItemContainerStyle with a HorizontalContentAlignment setter makes the trick. I.e.:
<ListView x:Name="questionsView" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="BlueViolet">
<Grid HorizontalAlignment="Stretch" Margin="0">
<TextBlock Text="{Binding}" />
<TextBlock HorizontalAlignment="Right">16 minutes ago</TextBlock>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
Set the item container's property of HorizontalContentAlignment to Stretch, try this
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
What is important here is the ScrollViewer.HorizontalScrollBarVisibility, TextWrapping and ItemContainerStyle with HorizontalContentAlignment. The rest is fluff.
<ListView VerticalAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Prop1}" TextWrapping="Wrap"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>

Windows Phone 8 xaml textblock binding format

I would like to format a textblock which is bound to a value, to show "R" before the actual value, is this possible, cause I cannot directly change the value?
Thank you
<ListBox x:Name="lstbundleListbox"
Foreground="White"
Height="320"
HorizontalAlignment="Center">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment"
Value="Center" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding name}"
TextWrapping="Wrap"
HorizontalAlignment="Center" />
<TextBlock Text="{Binding cost}"
TextWrapping="Wrap"
HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListBox>
So I basically want the textblock to show R(cost)
use Run
<TextBlock>
<Run Text="R" />
<Run Text="{Binding cost}" />
</TextBlock>
or use StringFormat
<TextBlock Text="{Binding cost, StringFormat=R{0}}" />
i think this can be done by
<StackPanel Orientation Horizontal>
<TextBlock Text="R(" />
<TextBlock Text="{Binding cost}"/>
<TextBlock Text=")" />
</StackPanel>
distance between them can be set by setting padding of the textblocks...

How do I say .ToString() in XAML?

The following code gives me the error (cannot add type Object to Stackpanel).
How can I say .ToString() in XAML?
<Window.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox x:Name="theCustomers"/>
</Grid>
binding in code-behind with ADO.NET Entity Framework:
MainEntities db = new MainEntities();
var customers = from c in db.CustomersSet
select c;
theCustomers.ItemsSource = customers;
You need to set the property ContentTemplate, not Content.
Try:
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Path=LastName}"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
See this article