ListBox not using its ItemTemplate - wpf

What in the world is wrong with this ListBox? It is showing items as plain strings, not using the template I have provided:
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="20" Height="20" Fill="LightBlue" />
<TextBlock Text="{TemplateBinding Content}" Foreground="Red" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Items>
<ListBoxItem>html</ListBoxItem>
<ListBoxItem>head</ListBoxItem>
<ListBoxItem>body</ListBoxItem>
<ListBoxItem>table</ListBoxItem>
<ListBoxItem>tr</ListBoxItem>
<ListBoxItem>td</ListBoxItem>
</ListBox.Items>
</ListBox>

From the Remarks section in the ItemTemplate MSDN page:
When you set an ItemTemplate on an ItemsControl, the UI is generated
as follows (using the ListBox as an example):
1.During content generation, the ItemsPanel initiates a request for the ItemContainerGenerator to create a container for each data item.
For ListBox, the container is a ListBoxItem. The generator calls back
into the ItemsControl to prepare the container.
2.Part of the preparation involves the copying of the ItemTemplate of the ListBox to be the ContentTemplate of the ListBoxItem.
3.Similar to all ContentControl types, the ControlTemplate of a ListBoxItem contains a ContentPresenter. When the template is applied,
it creates a ContentPresenter whose ContentTemplate is bound to the
ContentTemplate of the ListBoxItem.
4.Finally, the ContentPresenter applies that ContentTemplate to itself, and that creates the UI.
These steps are apparently not executed when you create ListBoxItem instances directly in XAML. It is however not strictly necessary to bind the ItemSource property. You may also directly set items like this:
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="20" Height="20" Fill="LightBlue" />
<TextBlock Text="{TemplateBinding Content}" Foreground="Red" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Items>
<sys:String>html</sys:String>
<sys:String>head</sys:String>
<sys:String>body</sys:String>
<sys:String>table</sys:String>
<sys:String>tr</sys:String>
<sys:String>td</sys:String>
</ListBox.Items>
</ListBox>

public class MyViewModel
{
public List<String> Items
{
get { return new List<String> { "html", "head", "body","table","tr","td" }; }
}
}
//This can be done in the Loaded event of the page:
DataContext = new MyViewModel();
Your XAML
<ListBox Margin="20" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<Ellipse Width="20" Height="20" Fill="LightBlue" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Related

WPF binding to Visibility of an Itemtemplate of a Listview not working [duplicate]

This question already has an answer here:
How to use binding in the ListBox’s Items to the ViewModel’s properties
(1 answer)
Closed 4 years ago.
I am using WPF Prism.Mvvm.
I have a navigation bar on the side containing a Listview bound to an Itemssource. Those Items contain an image and the content. Now my goal is to collapse the content of the item so that my navigation control only shows the icons.
I have defined a Visibility binding, using this on some image outside of my Listview which works perfectly. But as soon as I try to use that exact binding on anything within the itemtemplate of the Listview, nothing happens.
The funny thing is, if I set the Visibility to Collapsed myself without a binding, it works again.
here is my View
<UserControl.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</ResourceDictionary>
[...]
<DockPanel >
<ContentControl DockPanel.Dock="Top">
<StackPanel>
<Button Margin="5,5,5,5" Style="{StaticResource MyButton}" Command="{Binding ExpandMenuCommand}" Content="Menu" HorizontalAlignment="Left" Width="43.017" />
<ListView BorderThickness="0" VerticalContentAlignment="Top" SelectionMode="Single" ItemsSource="{Binding MenuItems}" SelectedItem="{Binding SelectedItem}" Background="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Margin="0,10,0,10" Grid.Column="0" Source="{Binding ImageSource}" />
<TextBlock Visibility="{Binding Visibility, Converter={StaticResource booleanToVisibilityConverter}}" VerticalAlignment="Center" Margin="10,10,10,10" Grid.Column="1" Text="{Binding Content}" Background="Transparent" FontFamily="Arial" FontWeight="Bold" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</ContentControl>
<ContentControl DockPanel.Dock="Bottom">
<Grid>
<Image Visibility="{Binding Visibility, Converter={StaticResource booleanToVisibilityConverter}}" HorizontalAlignment="Center" Height="59" Margin="19,0,0,25" Width="182" Source="/ModuleA;component/Images/Logo.png" VerticalAlignment="Bottom" />
</Grid>
</ContentControl>
</DockPanel>
Now if I copy Visibility="{Binding Visibility, Converter={StaticResource booleanToVisibilityConverter}}" to ANYTHING above that Itemtemplate, say the Listview itself or the Stackpanel, it works like it does for the Image under the Listview. but the Textblock, or Image, or Grid itself within the Listview.ItemTemplate won't respond to my Binding. Setting it to Visibility="Collapsed"however works just as I intend it to work.
My Viewmodel:
private static bool _expanded = true;
private bool _visibility = _expanded;
public bool Visibility
{
get { return _visibility; }
set { SetProperty(ref _visibility, value); }
}
private void ExpandMenu()
{
_expanded = !_expanded;
Visibility = _expanded;
}
ListView.ItemTemplate is a template for MenuItem objects. I suppose Visibility isn't a property of MenuItem class, it belongs in another view model. So you need to bind it froma different DataContext:
<TextBlock Visibility="{Binding DataContext.Visibility,
Converter={StaticResource booleanToVisibilityConverter},
RelativeSource={RelativeSource AncestorType=ListView}}"
VerticalAlignment="Center"
Margin="10,10,10,10" Grid.Column="1"
Text="{Binding Content}"
Background="Transparent"
FontFamily="Arial"
FontWeight="Bold" />

WPF TabControl: ItemContainerStyle and ItemTemplateSelector

I am not able to find an answer to my question somewhere. Maybe you guys can help me.
I am using WPF and have a TabControl which uses an ItemTemplateSelector. The ItemsSource of the TabControl is an ObservableCollection of Strings. Based on the string, the template for the TabItem is choosen. Works fine so far.
Only problem I have now, is that I want to use a custom style on my TabItems. So I tried the ItemContainerStyle property, but this doesn't work. When I set the ItemContainerStyle, the ItemTemplateSelector doesn't fire anymore. I am not using a ContentTemplateSelector as I don't need this one on this solution as the content of the Tabs is always the same.
So my question is: How can I define the style of the TabItems, when I use an ItemTemplateSelector?
Here is some code:
TabControl on Usercontrol:
<TabControl TabStripPlacement="Right"
ItemsSource="{Binding loadedPalettes, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource StyleTabControl}"
ItemTemplateSelector="{StaticResource TabTemplateSelector}"
Height="Auto"
SelectionChanged="paletteSelectionChanged"
SelectedIndex="{Binding selPaletteIndex}"
Width="Auto"
Margin="0,5,0,0">
<TabControl.ContentTemplate>
<DataTemplate>
<local:tabDataGrid />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
TemplateSelector Class
Public Class SSITabTemplateSelector
Inherits DataTemplateSelector
Public Overrides Function SelectTemplate(item As Object, container As DependencyObject) As DataTemplate
Dim element As FrameworkElement
element = TryCast(container, FrameworkElement)
If element Is Nothing Then Return Nothing
If container Is Nothing Then Return Nothing
Select Case item
Case "Search"
Return TryCast(element.FindResource("searchTabItem"), DataTemplate)
'Case "TabSwitch"
' Return TryCast(element.FindResource("TextItem"), DataTemplate)
Case Else
Return TryCast(element.FindResource("normalTabItem"), DataTemplate)
End Select
Return Nothing
End Function
End Class
DataTemplates for the TabItems
<DataTemplate x:Key="normalTabItem">
<StackPanel Name="Panel"
Orientation="Horizontal">
<TextBlock Text="{Binding}"
Background="Transparent">
<TextBlock.LayoutTransform>
<RotateTransform Angle="270" />
</TextBlock.LayoutTransform>
</TextBlock>
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Content="{Binding Content}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="searchTabItem">
<StackPanel Name="Panel"
Orientation="Horizontal">
<TextBlock Text="blabla"
Background="AliceBlue">
<TextBlock.LayoutTransform>
<RotateTransform Angle="270" />
</TextBlock.LayoutTransform>
</TextBlock>
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Content="{Binding Content}" />
</StackPanel>
</DataTemplate>
Adding the answer, according the comment. You can write something like this.
<TabControl>
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Header" Value="MyHeader"/>
</Style>
</TabControl.Resources>
</TabControl>
Solution:
Yeah, it was that simple. bars222 had the right answer. Just use <TabControl.Resources> and add the styling.
Thanks!

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).

Silverlight pass DataContext to ConverterParameter?

How can I pass the DataContext of LayoutRoot to the converter of the ContentControl inside the ListBox items template?
<Grid x:Name="LayoutRoot"
Background="White"
DataContext="{Binding Source={StaticResource myViewModel}}">
<StackPanel HorizontalAlignment="Left"
Margin="6,6,0,394"
Orientation="Vertical"
Width="200"
d:LayoutOverrides="Height">
<ListBox x:Name="listBox2"
ItemsSource="{Binding MyCollection, Mode=TwoWay}"
VerticalAlignment="Top"
Height="400">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}"
ContentTemplate="{Binding Converter={StaticResource myConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Text="{Binding Value1, Mode=TwoWay}"/>
</StackPanel>
</Grid>
I want to be able to touch the objects inside the DataContext from within the Converter and use them for TwoWay binding on controls within the ListBox item's DataTemplate.
Any ideas? Any suggestions?
Thank you.
I just got the DataContext up to the converter using:
<ContentControl Content="{Binding}"
ContentTemplate="{Binding Converter={StaticResource stringToDataTemplateConverter}, ConverterParameter={StaticResource myViewModel}}" />
Now I have another problem my dynamic property binding is not working.
(sorry for my bad english)
I'm not sure about what you are trying to do here but with SL 5 you can use RelativeSource to get the DataContext:
{Binding DataContext,RelativeSource={RelativeSource AncestorLevel=1,AncestorType=Grid}}

Display list of usercontrols within itemtemplate next to other controls

I would like to display a list of usercontrols binded to a listbox
next to each usercontrol there should be a button
<ListBox ItemsSource="{Binding usercontrollist}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--usercontrol of the current binded items-->
<Button Content="x" HorizontalAlignment="Right"></Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
How can i do this in xaml code
Assuming usercontrollist is a collection of UserControl, then you should be able to do this:
<ContentControl Content="{Binding}" />

Resources