Automatic Scrolling in a Silverlight List Box with Custom Template - silverlight

I have ListBox with custom template, how do programmatically scroll it down to bottom?
Automatic Scrolling in a Silverlight List Box describes method of scrolling to bottom of ListBox. Unfortunately this method does not work with ListBox with custom style template.
Have anyone success to scroll ListBox with custom style?
Problem code:
<Grid.Resources>
<Style x:Key="HorizontalWrapListBox" TargetType="ListBox">
<Style.Setters>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Grid.Resources>
<ListBox x:Name="MyListBox" Margin="0,0,-12,0" ItemsSource="{Binding Items}"
Style="{StaticResource HorizontalWrapListBox}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Height="78">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap"
Margin="12,-6,12,0"
Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

You need to keep correct naming of your template parts and this could just start working. The ScrollViewer should be named x:Name="ScrollViewer". Check
ListBox Styles and Templates,
Customizing the Appearance of an Existing Control by Using a ControlTemplate,
TemplatePartAttribute

Related

WPF - Move ListView.GroupStyle to external XAML

After several hours I gave up.
I have the following ListView (in Grid) with GroupStyle defined inside of it.
I want to take it out somehow and put it in a Template or Style (I'm confused) and then add it to my main Style of the ListView (ListViewSimpleStyle).
This way it will be reusable in other places instead of copy-paste it every time.
How do I do it?
<ListView Name="LvDataBinding" Grid.Row="0"
Style="{StaticResource ListViewSimpleStyle}">
<!-- Define the grouping-->
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontSize="12" Text="{Binding Name}"
Foreground="{StaticResource GrayForgroundBrush}"></TextBlock>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
Thanks
Groupstyle is style of Groupbox so we need to edit style of Groupbox and I have changed GroupBox HeaderTemplate as you want to change HeaderTemplate of GroupStyle.
Visit this:http://msdn.microsoft.com/en-us/library/ms754027(v=vs.90).aspx
and Add GroupBox With Its style in your own listview template style i.e ListViewSimpleStyle
<Style x:Key="ListViewSimpleStyle" TargetType="ListView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<Grid Background="AliceBlue" >
<GroupBox>
<GroupBox.Style>
<Style TargetType="GroupBox">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock FontSize="12" Text="{Binding Name}" Foreground="{StaticResource GrayForgroundBrush}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupBox.Style>
</GroupBox>
<ItemsPresenter></ItemsPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Need multiple styles dependent on Listboxitem

i have a Listbox, which stores two different object types, based on the same baseclass. (e.g. BaseObject = baseclass and the children of it: CustomPath and CustomImage)
The Datasource:
ObservableCollection<BattlegroundBaseObject> _baseObjectCollection;
public ObservableCollection<BattlegroundBaseObject> BaseObjectCollection
{
get { return _baseObjectCollection?? (_baseObjectCollection= new ObservableCollection<BaseObject>()); }
}
The Listbox databinding: <ListBox ItemsSource="{Binding BaseObjectCollection}"
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" x:Name="ListBoxPathLineStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem" x:Name="BattlegroundObjectControlTemplate">
<Path Stroke="{Binding ObjectColor}" StrokeThickness="{Binding StrokeThickness}" Data="{Binding PathGeometryData}" x:Name="PathLine" Opacity="{Binding Opacity}">
</Path>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Effect" TargetName="PathLine">
<Setter.Value>
<DropShadowEffect Color="CornflowerBlue" ShadowDepth="3" BlurRadius="10" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
I want to add to the ControlTemplate where the Path is, also a Image and to differ it by type or a property. doesnt matter.
anyone any ideas?
You can add to ListBox resources DataTemplate for each type.
In my example classes Car and Motorbike derived from Vehicle class.
<ListBox x:Name="listBox">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:Car}">
<StackPanel Background="Red">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Motorbike}">
<StackPanel Background="Orange">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.Resources>
</ListBox>
EDIT:
You can add style for ListBoxItem to resources:
<ListBox x:Name="listBox">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="CornflowerBlue" ShadowDepth="3" BlurRadius="10" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate DataType="{x:Type local:Car}">
<StackPanel Background="Red">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Motorbike}">
<StackPanel Background="Orange">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.Resources>
</ListBox>
You could define some DataTemplates for your different classes. They determine how the classes are displayed. I've been using them to display derived classes differently when working with a collection of the base class.
<DataTemplate DataType="{x:Type CustomPath}">
<TextBlock Text="This is a CustomPath"/>
</DataTemplate>
<DataTemplate DataType="{x:Type CustomImage}">
<TextBlock Text="This is a CustomImage"/>
</DataTemplate>
At the moment you are changing the style of the controls that WPF is using to render your bound data. A better way to do this is to provide WPF with a way of generating the correct controls. Ignore the ListBoxItem and use DataTemplates for your actual objects.
First you need to tell the Window or control how to find your types.
<Window or UserControl
...
xmlns:model="clr-namespace:yourNamespace"
>
Then you can provide WPF with a way to show your objects e.g.
<DataTemplate TargetType="{x:Type model:CustomPath}">
<Path Stroke="{Binding ObjectColor}" StrokeThickness="{Binding StrokeThickness}"
Data="{Binding PathGeometryData}" x:Name="PathLine" Opacity="{Binding Opacity}"/>
<!-- maybe use a binding from the Path.Effect back to the IsSelected and ValueConverters
to re-apply the selection effect-->
</DataTemplate>
<DataTemplate TargetType="{x:Type model:CustomImage}">
<Image Src="{Binding SomeProperty}" />
</DataTemplate>
Now all you need to do is to make these available to the ListBox in some way. Almost every element in WPF can have .Resources added to it, so you could choose to do these across the entire window
<Window ...>
<Window.Resources>
<DataTemplate .../>
<DataTemplate .../>
</Window.Resources>
...
<ListBox .../>
</Window>
or you can apply it more locally
<Window ...>
...
<ListBox>
<ListBox.Resources>
<DataTemplate .../>
<DataTemplate .../>
</ListBox.Resources>
</ListBox>
</Window>
And this way your listbox definition can become much neater too, e.g. if you are using Window.Resources
<ListBox ItemsSource="{Binding BaseObjectCollection}"/>

Horizontal RadioButtons in ListBox

In WPF I am trying to binding radio buttons to a property in the ViewModel such as this SO answer https://stackoverflow.com/a/2285732
Everything works fine, except that the Buttons are stacked Vertically. Now, this seems an easy fix, just modify the ItemsPanelTemplate.
Here's my code:
<ListBox ItemsSource="{Binding ItemOptions}" SelectedItem="{Binding SelectedOption}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}" >
<RadioButton Content="{TemplateBinding Content}"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
However, the items remain stacked vertically. Any ideas why this has no effect on the orientation of the ListBox?
Try this:
<ListBox.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer x:Name="scrollviewer"
HorizontalScrollBarVisibility="Visible" CanContentScroll="False">
<StackPanel IsItemsHost="True" Orientation="Horizontal" />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
I tried to get this working with the ItemsPanelTemplate, as you did, without success. This worked great for me.
Regards
Here is a basic example without styling. Note that the WrapPanel handles the layout.
<ListBox Margin="0,10,0,0"
ItemsSource="{StaticResource Orders}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding CustomerName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Data with the model defined in code behind.
<Page.Resources>
<model:Orders x:Key="Orders">
<model:Order CustomerName="Alpha"
OrderId="997"
InProgress="True" />
<model:Order CustomerName="Beta"
OrderId="998"
InProgress="False" />
<model:Order CustomerName="Omega"
OrderId="999"
InProgress="True" />
<model:Order CustomerName="Zeta"
OrderId="1000"
InProgress="False" />
</model:Orders>
</Page.Resources>
Result

HeaderTemplate with multiple items

I'm trying to write a HeaderTemplate for an extender. So far, I've noticed all the examples use the {Binding} keyword to get the data from the header. However, what happens if there are multiple controls within the Header? How do I specify that those controls should be inserted at a specific location?
<Window.Resources>
<Style x:Key="ExpanderStyle" TargetType="{x:Type Expander}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<!-- what do I put in here? -->
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Expander Style="{StaticResource ExpanderStyle}">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock>Some Text</TextBlock>
<TextBlock Text="{Binding SomeBinding}" />
<Button />
</StackPanel>
</Expander.Header>
<Image Source="https://www.google.com/logos/2012/steno12-hp.jpg" />
</Expander>
Should I be moving my binding into the HeaderTemplate in the style and just overwriting whatever the Header in the Expander is?
You can use ContentPresenter to insert whatever the usual content would be into your Template
For example:
<Style x:Key="ExpanderStyle" TargetType="{x:Type Expander}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<Border BorderBrush="Blue" BorderThickness="2">
<ContentPresenter />
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Header's property Content could contain only one object.
If you merge these object in one panel:
<StackPanel>
<TextBlock>Some Text</TextBlock>
<TextBlock Text="{Binding SomeBinding}" />
<Button />
</StackPanel>
then in template you could use {binding}

WPF Using styles to change a ListBox WrapPannel to a ListBox StackPanel

I want to change a listview with a wrappanel inside into a listivew with a stackpanel inside, basically to switch between a "small image view" and a "details view".
Not sure the best way to do it though. What I have so far:
<UserControl.Resources>
<Style x:Key="ListBoxWrap" TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListBoxList" TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<ListBox Style="{StaticResource ListBoxList}" Name="lstContacts" Background="White" Margin="7,0,7,7" Grid.Row="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Border CornerRadius="4" Margin="5">
<StackPanel>
<TextBlock Text="{Binding FullName}" Margin="5,3,5,0" />
<TextBlock Text="{Binding Title}" Margin="5,0,5,3" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
You should use a ListView for that, then you just need to swap out the ListView.View to change the appearance, the GridView already is a details-view, then you only need to create a view for the thumbnails.
To do so subclass ViewBase, there is an example in the documentation; creating a simple thumbnail view should not be very hard.
This approach has the advantage that it fully encapsulates the display-logic, so you should not need to swap out properties like ItemTemplate in addition to the panel.
You could also use a ItemTemplateSelector to modify the template based on a specific value change which could be (event) triggered by a mouse-over or click event.
All of this code would reside in the xaml and you would not need to create a separate class or custom control.

Resources