WPF Metro Styling ListBox - wpf

I'm having a problem styling my ListBox selection background.
I used ListView originally, it was less problematic with styling but moving this to Silverlight app, I found out that it doesn't have ListView so I just used ListBox.
I want my app to be easily ported in Silverlight and also in Windows Phone so I used ListBox and now am having a trouble with the style.
My Metro app has Dark theme and I have custom ListBoxItem but am not sure why when I clicked on it, it looks like this
originally when using ListView, it looks like this
adding background color in my custom ItemsTemplate make it look this
How do I get rid of that White background and also restyle the item when hovered because it looks like this
this my XAML for listbox so far
<ListBox Grid.Row="3" Name="lvSubmeters" VerticalAlignment="Top" HorizontalAlignment="Stretch" SelectedItem="{Binding Path=SelectedListViewItem, Mode=TwoWay}" SelectedIndex="{Binding Path=SelectedListViewIndex, Mode=TwoWay}" ItemTemplate="{StaticResource SubmeterItems}" ItemsSource="{Binding Path=Store.AllItems}" Background="{x:Null}" Foreground="White">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Margin" Value="0" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
and also if you want my custom ItemsTemplate
<DataTemplate x:Name="SubmeterItems">
<Grid VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin="5,5,5,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="166"/>
<ColumnDefinition Width="100*"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" VerticalAlignment="Top">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Top" Text="{Binding MeterID}" FontSize="24" FontWeight="Bold" Foreground="#FF429AA3" />
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Top" Text="{Binding Fullname}" FontSize="16" />
</StackPanel>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Height="95">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Top" Text=" " FontSize="24" FontWeight="Bold" Foreground="#FF429AA3" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="29*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Grid.Column="0" VerticalAlignment="Top" Text="Last Reading:" FontSize="14" Margin="0,0,5,5" />
<TextBlock Grid.Column="0" VerticalAlignment="Top" Text="New Reading:" FontSize="14" Margin="0,0,5,5" />
<TextBlock Grid.Column="0" VerticalAlignment="Top" Text="KW/H Used:" FontSize="14" Margin="0,0,5,5" />
</StackPanel>
<StackPanel Grid.Column="1">
<TextBlock Grid.Column="1" VerticalAlignment="Top" Text="{Binding LastReading}" FontSize="14" Margin="0,0,5,5" FontWeight="Bold" />
<TextBlock Grid.Column="1" VerticalAlignment="Top" Text="{Binding NewReading}" FontSize="14" Margin="0,0,5,5" FontWeight="Bold" />
<TextBlock Grid.Column="1" VerticalAlignment="Top" Text="{Binding KwHUsed}" FontSize="14" Margin="0,0,5,5" FontWeight="Bold" />
</StackPanel>
</Grid>
</StackPanel>
<StackPanel Grid.Column="2" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Background="Black">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Top" Text="{Binding KwhUsedAmount}" FontSize="20" FontWeight="Bold" Foreground="Red" TextAlignment="Right" Margin="0,0,5,0" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Top" Text="+" FontSize="20" Foreground="#99FF0000" TextAlignment="Right" Margin="0,0,5,0"/>
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Top" Text="{Binding AdditionalCharges}" FontSize="20" Foreground="#99FF0000" TextAlignment="Right" Margin="0,0,5,0"/>
</StackPanel>
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Top" Text="{Binding TotalAmount}" FontSize="34" FontWeight="Bold" Foreground="Green" TextAlignment="Right" Margin="0,0,5,0" />
</StackPanel>
</Grid>
</DataTemplate>
I tried taking this to Blend 4 but I can't find the way to do it.

It looks to me like your screenshots from above don't quite match the XAML that you've provided, however I think I can answer your questions.
For the white border around each item - From the way that the border changes to Purple when the item is selected, you can tell that it is part of the ItemContainer (because that is what gets selected). The ItemContainer will contain the Content of each ListBoxItem. The Content is rendered using the DataTemple (or ItemTemplate property). In your DataTemplate, you have a margin of 5 around the topmost grid, meaning that when the Content is rendered using that DataTemplate, there will be a margin around the outside of the content. That seems to be what you're getting with your white border around each item, so I'm pretty sure that's what is going on. Get rid of the margin in the top most grid of the DataTemplate, and the white border will be gone. If this isn't correct, please provide more complete XAML example (including the parent XAML element of the Listbox) because the xaml above, on its own, does not yield a white border when the Window background is Black.
Changing the colors/style of the ListBoxItem is pretty easy, and there are several ways to do it. The easiest way (in my opinion) is to add a trigger to the ItemContainerStyle that adjusts the background color on MouseOver. Here is a simple example, extending your existing ItemContainerStyle (triggers can be much more advanced, if you wish):
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Margin" Value="5" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
Hope that helps.

Related

VirtualizingPanel not Virtualizing using WPF XAML [duplicate]

This question already has answers here:
Virtualizing WPF Wrap Panel Issue
(3 answers)
Is there a virtualizing WrapPanel for WPF available? Commercial or free ones
(2 answers)
Virtualizing WrapPanel as ListView's ItemsTemplate
(3 answers)
Closed 4 years ago.
So no matter how hard I try I can't get virtualization in my view to work.
When I scroll through my Listbox, the items always keep populating from the top and carry on right to the bottom, rather than rendering what is on screen and just a bit above and bellow.
Any help would be very much appreciated.
Bellow is the code for the Viewbox. A point of note:
I am using a Viewbox inside a ListBox and a grid inside the ViewBox. This is because my items populate in a similar way to text with word warping turned on - it populates horizontally until the width, then moves on to the next line.
My items in the ListBox are scalable, and there position in the view changes dynamically depending on the scale size, whilst also, the TextBlocks text dose not scale.
Not sure if that effects virtualization in a way I am unaware.
If that is not clear, I apologise and am happy to answer any questions. Thanks for your time:
<ListBox x:Name="LibraryBox"
Grid.Column="1"
Grid.Row="0"
Grid.RowSpan="4"
Margin="0,-5,0,-10"
BorderBrush="Transparent"
Background="#1e1e1e"
ItemsSource="{Binding}"
ItemContainerStyle="{StaticResource ListBoxItemStyle}"
IsSynchronizedWithCurrentItem="True"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.IsContainerVirtualizable="True"
VirtualizingPanel.VirtualizationMode="Standard"
ScrollViewer.IsDeferredScrollingEnabled="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionMode="Extended"
SelectionChanged="LibraryBox_SelectionChanged"
MouseDoubleClick="LibraryBox_MouseDoubleClick">
<ListBox.Resources>
<!--#region scrollbar style-->
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="#990000"/>
<Setter Property="Width" Value="25"/>
</Style>
<!--#endregion-->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Red"/>
</ListBox.Resources>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Edit" Click="ContextMenuItemEdit_Click"/>
<MenuItem Header="ComicVine Scraper" Click="MenuItemScraper_Click"/>
<Separator/>
<MenuItem Header="Delete" Click="ContextMenuItemDelete_Click"/>
</ContextMenu>
</ListBox.ContextMenu>
<!--#region Group Style-->
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"
FontWeight="Bold"
Foreground="#dbdbdb"
FontSize="16"
FontFamily="Cordia New"
VerticalAlignment="Bottom" />
<TextBlock Text="{Binding ItemCount}"
FontSize="16"
Foreground="#dbdbdb"
FontStyle="Italic"
Margin="10,0,0,0"
FontFamily="Cordia New"
VerticalAlignment="Bottom" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
<!--#endregion-->
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Viewbox Height="100" Width="70" Margin="2">
<Viewbox.LayoutTransform>
<ScaleTransform ScaleX="{Binding Value, ElementName=ZoomSlider}"
ScaleY="{Binding Value, ElementName=ZoomSlider}"/>
</Viewbox.LayoutTransform>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="32"/>
</Grid.ColumnDefinitions>
<!--This is for thumbnails-->
<Image x:Name="coverImage"
Grid.Column="0"
Grid.Row="0"
Source="{Binding CoverPath, Converter={StaticResource UriToBitmapConverter}, IsAsync=True}"/>
<Rectangle x:Name="ReadMarkerBottom"
Grid.Column="1"
Grid.Row="1"
Margin="-16,0,0,0"
Fill="#fff"
Width="32"
Height="32"
Loaded="CoverImage_Loaded"/>
<Rectangle x:Name="ReadMarkerTop"
Grid.Column="1"
Grid.Row="1"
Margin="-16,0,0,0"
Fill="#000"
Width="30"
Height="30"
Loaded="CoverImage_Loaded"/>
</Grid>
</Viewbox>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="Text_Loaded"
FontFamily="Cordia New"
FontWeight="Bold">
</TextBlock>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="IssueNumer_Loaded"
FontFamily="Cordia New"/>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="CountStack_Loaded"
FontFamily="Cordia New"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
The answer is, as Clemens pointed out, "The ItemsPanel must support virtualization. WrapPanel does not."

Modifying TabControl's header

So I'm adding my views directly to the TabControl's Items collection at runtime (instead of creating TabItems around them and addings those TabItems to TabControl). The views expose a property (wrapper around a ViewModel property of the same name) named HasChanges that I want to bind to TabItem's Header to show a Asterisk (*) sign to identify tabs with unsaved changes, just like VS does. I have already tried using DataTemplates but am having trouble accessing the view object in the DataTemplate. What's the correct way of doing this? Here's one of my several attempts:
<TabControl.ItemTemplate>
<DataTemplate DataType="UserControl">
<StackPanel Orientation="Horizontal" Margin="0" Height="22">
<TextBlock VerticalAlignment="Center" Text="{Binding HeaderText, RelativeSource={RelativeSource AncestorType=UserControl}}" />
<TextBlock Text="*" Visibility="{Binding HasChanges, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource B2VConverter}}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
Note that I'm trying two different binding methods for the two TextBlocks, none of which is working. My views inherit from UserControl and expose properties HasChanges and HeaderText.
OK. I solved it myself. For anyone else trying to implement a VS-like Close button and unsaved changes asterisk, here's the template:
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0" Height="22">
<TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType=TabItem}, Path=Content.HeaderText}" />
<TextBlock Text=" *" ToolTip="Has unsaved changes" Visibility="{Binding Content.DataContext.HasChanges, RelativeSource={RelativeSource AncestorType=TabItem}, Converter={StaticResource B2VConverter}}" />
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Width="18" Height="18"
Margin="6,0,0,0" Padding="0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Center"
Command="{Binding DataContext.TabClosingCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"
VerticalAlignment="Center" Focusable="False">
<Grid Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Line StrokeThickness="3" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Stroke="Gray" X1="1" Y1="1" X2="9" Y2="9" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Line StrokeThickness="3" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Stroke="Gray" X1="1" Y1="9" X2="9" Y2="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Button>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
Results in an elegant drawing-based button with a flat-look. Your View must implement Boolean HasChanges and HeaderText properties, plus you need to define a BooleanToVisibilityConverter in your resources section, named B2VConverter.

List of groups of data with multiple interactive UI elements

I'm currently working on a WPF application, it's my first so I'm learning as I go.
The basics are fine but I've hit a problem with what I'm trying to do at the moment. There seem to be tons of ways that might work but I'm pretty sure that I'm going down the path of making it harder than it needs to be.
What I need is some guidance on the simplest way to implement a piece of UI.
I'm using c# 4, wpf and the MVVM pattern.
The data I'm wanting to display looks like this:
obj1 ----< obj2 ----< obj3
i.e. a single obj1 has many obj2's which has many (specifically 1-3) obj3's
On my screen, I want to see a list/datagrid type view of the obj2 elements with the associated obj3 elements nested underneath.
The obj2 elements need to show a few text values and a check box (that will fire the appropriate command in the view model when toggled).
The obj3 elements need to show an image, possibly some text and be clickable (again, firing the appropriate command to the view model).
At first I looked at creating a custom control for the obj3 element, a custom control based on ItemsControl for a list of obj3 elements, another custom control for the obj2 element and finally another custom control to display a list of obj2 elements.
However, a little way in, I've got the feeling that I've massively over-complicated it.
Can I just use user controls? Do I even need them at all or can I just use the regular List control with a template?
Some pointers would be very welcome.
Thanks.
I spent quite some time getting this working as I wanted so thought I'd share...
The answer turned out to be a nested list control with data templates and associated view models for the items in each list. The list control is so much more flexible in WPF than Winforms that you can do pretty much anything with it.
I've found many different things that have helped on many different sites but the core details came from Dr.WPF: http://drwpf.com/blog/category/collections/
I won't post all the code as it's rather long. The core of it though is to first setup the list view in the user control:
<ListView Name="list" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" Focusable="False"
IsSynchronizedWithCurrentItem="True" ItemsPanel="{StaticResource VerticalItemsPanel}"
ItemContainerStyle="{StaticResource Obj2ContainerStyle}" ItemsSource="{Binding Obj2List}">
</ListView>
The keys things here are the ItemsPanel and ItemContainerStyle. These define the properties of the panel that contains all list items and the style for each list item respectively.
They are contained in the resources for the user control.
<ItemsPanelTemplate x:Key="VerticalItemsPanel">
<StackPanel Orientation="Vertical" Focusable="False" HorizontalAlignment="Stretch" />
</ItemsPanelTemplate>
<Style x:Key="Obj2ContainerStyle" TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Enabled}" Value="False">
<Setter Property="Background" Value="LightSalmon"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Enabled}" Value="True">
<Setter Property="Background" Value="PaleGreen"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
I also have the data templates. The first tells the system to use the second for displaying objects of type Obj2ViewModel
<DataTemplate DataType="{x:Type src:Obj2ViewModel}">
<ContentControl x:Name="Obj2Host" Focusable="False" Content="{Binding}"
ContentTemplate="{StaticResource Obj2ViewTemplate}" />
</DataTemplate>
<DataTemplate x:Key="Obj2ViewTemplate">
<DataTemplate.Resources>
<ItemsPanelTemplate x:Key="HorizontalItemsPanel">
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
<Style x:Key="Obj3ContainerStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Rectangle StrokeThickness="1" Stroke="#FF000000" Margin="0" />
<ContentPresenter x:Name="ContentHost" Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="LabelStyle" TargetType="{x:Type Label}">
<Setter Property="Padding" Value="0,0,4,0" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style x:Key="DataStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Padding" Value="0,0,4,0" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</DataTemplate.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{StaticResource Label1Text}" Style="{StaticResource LabelStyle}"/>
<Label Grid.Row="1" Grid.Column="0" Content="{StaticResource Label2Text}" Style="{StaticResource LabelStyle}"/>
<Label Grid.Row="2" Grid.Column="0" Content="{StaticResource Label3Text}" Style="{StaticResource LabelStyle}"/>
<Label Grid.Row="3" Grid.Column="0" Content="{StaticResource Label4Text}" Style="{StaticResource LabelStyle}"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Property1}" Style="{StaticResource DataStyle}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Property2}" Style="{StaticResource DataStyle}"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Property3}" Style="{StaticResource DataStyle}"/>
<TextBlock Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Property4}" Style="{StaticResource DataStyle}"/>
<ListView Grid.Row="0" Grid.RowSpan="3" Grid.Column="2" Name="Obj3List"
HorizontalAlignment="Right" VerticalAlignment="Center"
IsSynchronizedWithCurrentItem="True"
ItemsPanel="{StaticResource HorizontalItemsPanel}"
ItemsSource="{Binding Obj3s}"
ItemContainerStyle="{StaticResource Obj3ContainerStyle}"
BorderThickness="0"
Background="Transparent">
</ListView>
<CheckBox Grid.Row="0" Grid.RowSpan="4" Grid.Column="3" VerticalAlignment="Center"
IsChecked="{Binding Property5}" IsEnabled="{Binding NotExpired}" >
</CheckBox>
<Image Grid.Row="0" Grid.RowSpan="4" Grid.Column="4" Source="{StaticResource DeleteIcon}" Stretch="None">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<cmd:EventToCommand PassEventArgsToCommand="False" Command="{Binding DeleteObj2Command, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
</Grid>
</DataTemplate>
The second data template above contains another list view. This one containing Obj3 items.
The style for these is specified within the DataTemplate's resources section.
Finally, the User control's resources also contains the data templates for the Obj3 elements:
<DataTemplate DataType="{x:Type src:Obj3ViewModel}">
<ContentControl x:Name="Obj3Host" Focusable="False" Content="{Binding}"
ContentTemplate="{StaticResource Obj3ViewTemplate}" />
</DataTemplate>
<DataTemplate x:Key="Obj3ViewTemplate">
<Image Source="{Binding Image}" Stretch="None">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<cmd:EventToCommand PassEventArgsToCommand="False" Command="{Binding ToggleEnabledCommand, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
</DataTemplate>
Note that the EventToCommand stuff is thanks to the MVVM Light toolkit. It's not a standard .NET thing.

How to show a divider between items in a ListBox?

I am using a ListBox control in a Windows Phone 7 application, and I would like to show a divider/line between the list rows.
I have not been able to find any information about this, although many (not wp7) ListBox examples seem to have a divider.
Got inspired by NestorArturo and found out about the Border control.
It is very easy to wrap your ItemTemplate content in a Border control and specify the BorderThickness and BorderBrush. I went this way, because it doesn't require changes to my Grid in the ItemTemplate.
The Border control is described here: http://www.silverlightshow.net/items/Using-the-Border-control-in-Silverlight-2-Beta-1-.aspx.
Below you can see how I use it:
<ListBox Background="White" ItemsSource="{Binding Mode=OneWay, Path=MyPath}" Name="listName" SelectionChanged="listName_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
here --> <Border BorderThickness="0,10,0,10" BorderBrush="Black">
<Grid Width="auto" HorizontalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" FontSize="36" FontWeight="Bold" Grid.Column="0" Foreground="Black" Text="{Binding Path=Title}" Name="title"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Column="1" Foreground="Black" Text="{Binding Path=Location}" Name="location"/>
<Image VerticalAlignment="Center" Grid.Column="2" Width="48" Height="48" Source="ApplicationIcon.jpg"/>
</Grid>
and here --> </Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You can either change the ListBoxItem template, or, an easier approach is to change your ItemTemplate, You can simply add a divider within your ItemTemplate as follows:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<!-- your content goes here ... for example: -->
<TextBlock Text={Binding Path=InterestingThing}"/>
<!-- the divider -->
<Line X1="0" X2="200" Y1="0" Y2="0"
VerticalAlignment="Bottom"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>

Silverlight: how to modify the width of ListBox Items in response to user input?

I have a simple Silverlight 3 UserControl whose width increases or decreases based on user input.
The controls become more wide or more narrow as desired, except for the ListBox items. The ListBox Items grow horizontally to fit their content regardless of HorizontalContentAlignment being set to 'Stretch'.
Should I be able to set a property on ListBox.ItemContainerStyle to tell it to widen/narrow with the parent ListBox? There needs to be no horizontal scrolling within this Listbox.
Or is there a way to specify the ItemTemplate's StackPanel width that can be modified at runtime? I have bound this to a StaticResource, but do not understand whether I should be able to change the resource value. Can I create and bind to a DependencyProperty of the UserControl itself? I have not determined the syntax of this within the xaml.
code:
<UserControl x:Class="TheAssembly.GraphicViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:userControls="clr-namespace:TheAssembly"
xmlns:core="clr-namespace:System;assembly=mscorlib">
<UserControl.Resources>
<userControls:DictionaryAttributeConverter x:Name="MyDictionaryAttributeConverter" />
<core:Double x:Key="ListItemWidth">155</core:Double>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Width="175" >
<Border Style="{StaticResource DraggableWindowBorder}">
<StackPanel x:Name="RootStackPanel" Orientation="Vertical" HorizontalAlignment="Stretch">
<Border Background="Black" HorizontalAlignment="Stretch" Margin="0">
<TextBlock x:Name="Header" Foreground="White" FontSize="14" TextWrapping="Wrap" Margin="2,0,2,0"
Height="25" HorizontalAlignment="Left"
Text="{Binding HeaderText}"/>
</Border>
<TextBlock x:Name="Title" Style="{StaticResource GraphicViewerDetail}" FontSize="12" FontWeight="Medium" TextWrapping="Wrap"
Text="{Binding Title}" Margin="3,0,0,0" HorizontalAlignment="Left"/>
<ListBox x:Name="AttributeListBox" ItemsSource="{Binding Attributes}" BorderBrush="Red" HorizontalContentAlignment="Stretch"
Foreground="AntiqueWhite" Background="Transparent" IsEnabled="False" HorizontalAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0,-2,0,0"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="ListBoxItemStackPanel" HorizontalAlignment="Stretch" Orientation="Vertical" >
<TextBlock FontSize="10" Text="{Binding Key}" Foreground="White" FontWeight="Bold" HorizontalAlignment="Stretch"
Margin="2,0,0,0" TextWrapping="Wrap"/>
<TextBlock FontSize="10" Text="{Binding Value}" Foreground="White" Margin="6,-2,0,0" TextWrapping="Wrap"
HorizontalAlignment="Stretch" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Border>
</Grid>

Resources