How to enable scrolling when listbox is disabled in Silverlight? - silverlight

I want to disable listbox (not allow user to selected) but scrollable in Silverlight, how can I do that?

How about not using a ListBox. Despite it being the defacto means for displaying a list of items the true purpose of the ListBox is to select something from a list.
A scrollable list can be delivered by styleing the ItemsControl like this:-
<Grid.Resources>
<Style x:Key="ScrollableItemsControl" TargetType="ItemsControl">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Border CornerRadius="2" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="0" TabNavigation="{TemplateBinding TabNavigation}">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
Now you apply this style to an ItemsControl:-
<ItemsControl Style="{StaticResource ScrollableItemsControl}" ItemsSource="{Binding SomeData}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SomeProperty}" Margin="5" />
<TextBlock Text="{Binding SomeOtherProperty}" Margin="5" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This is a scrollable list but with none of the selection semanitics of the ListBox. Note there are fewer intermediatory elements in the visual tree doing this way than fiddling around with the ListBox control.
Edit
In light of your comment there is an easy way to toggle the selection behaviour of a ListBox without disabling it. You disable the ListBoxItems it contains instead.
<Grid.Resources>
<Style x:Key="DisabledItem" TargetType="ListBoxItem">
<Setter Property="IsEnabled" Value="False" />
</Style>
</Grid.Resources>
<ListBox x:Name="lst" ItemsSource="{StaticResource TestData}" ItemContainerStyle="{StaticResource DisabledItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="5" />
<TextBlock Text="{Binding Age}" Margin="5" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this case the ListBox starts of with disabled items. Scrolling however is still possible. But the items appear dimmed and there is no hover or selected highlighting going on.
The code below is able to toggle the "disabled" state on and off.
private void Button_Click(object sender, RoutedEventArgs e)
{
if (lst.ItemContainerStyle == null)
lst.ItemContainerStyle = (Style)LayoutRoot.Resources["DisabledItem"];
else
lst.ItemContainerStyle = null;
}

Related

Apply style to child content in WPF XAML with a template

I'm using a ListViewto display a menu. I want to apply a style to all ListViewItem. So far I have succeeded in one part of the concern but I would like to improve to avoid code replication. Here where I am :
<Window.Resources>
<Style x:Key="_listViewItemStyle" TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd"
...
</Border>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And then use the style like that :
<ListView x:Name="_listViewMenu"
Background="Transparent"
BorderBrush="Transparent"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListViewItem Style="{StaticResource _listViewItemStyle}">
<StackPanel Orientation="Horizontal"
Width="230"
Margin="10,0,0,0">
<Image Width="30"
Source="Images/Settings.png"
Stretch="Uniform"/>
<TextBlock Text="Paramètres"
Margin="25,0,0,0"
Style="{StaticResource _fontStyle}"/>
</StackPanel>
</ListViewItem>
</ListView>
As you can see there are some stuff that I imagine I can avoid to duplicate if I have 50 ListViewItems, let's say :
<StackPanel Orientation="Horizontal"
Width="230"
Margin="10,0,0,0">
or
<Image Width="30"
...
Stretch="Uniform"/>
etc...
How to include in the style _listViewItemStyle all required properties to format StackPanel, Image, textbox, etc... of the ListViewItem?
Thanks.
You can define a class which has necessary properties and use it as item type of collection for ItemsSource which may be in view (xaml or code behind). Such class would be as follows.
public class SourceItem
{
public string? ImagePath { get; init; }
public string? Text { get; init; }
}
Then, if you just want to show items, ItemsControl would be suffice. I don't know how you intend to use Triggers though.
<ItemsControl Background="Blue" HorizontalAlignment="Left">
<local:SourceItem ImagePath="Images/Settings.png" Text="Paramètres"/>
...
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border x:Name="Bd">
<StackPanel Orientation="Horizontal"
Width="230"
Margin="10,0,0,0">
<Image Width="30"
Source="{Binding ImagePath, Mode=OneTime}"
Stretch="Uniform"/>
<TextBlock Text="{Binding Text, Mode=OneTime}"
Margin="25,0,0,0"
Style="{StaticResource _fontStyle}"/>
</StackPanel>
</Border>
<DataTemplate.Triggers>
...
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In addition to the answer from #emoacht, you will need the following InputBindings:
<Border.InputBindings>
<MouseBinding Command="{Binding ItemCommand}" MouseAction="LeftClick"/>
</Border.InputBindings>

Both 'ItemTemplate' and 'ItemTemplateSelector' are set; 'ItemTemplateSelector' will be ignored

Following this question, I have another question about TreeView.
What I already have is a TreeViewwith HierarchicalDataTemplate, in which I can change the HierarchicalDataTemplate of level2 (like explained in the question and the answer).
What I want now, is to change the look of the expander of the Treeview. For this, I have defined a ControlTemplate named ctForTreeViewItem, and I use it like this:
<Window.Resources>
<ControlTemplate x:Key="ctForTreeViewItem"
TargetType="{x:Type TreeViewItem}">
<Expander IsExpanded="True"
Background="Grey"
BorderBrush="Transparent"
Foreground="White"
BorderThickness="1,1,1,3">
<Expander.Header>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
Name="Bd"
SnapsToDevicePixels="True"
Grid.Column="1">
<ContentPresenter Content="{TemplateBinding HeaderedContentControl.Header}"
ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
ContentStringFormat="{TemplateBinding HeaderedItemsControl.HeaderStringFormat}"
ContentSource="Header"
Name="PART_Header"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
</Expander.Header>
<Expander.Content>
<ItemsPresenter x:Name="ItemsHost" />
</Expander.Content>
</Expander>
</ControlTemplate>
<DataTemplate x:Key="Level3Template">
<Border Background="LightBlue">
<TextBlock Text="Level3"/>
</Border>
</DataTemplate>
<HierarchicalDataTemplate x:Key="Level2RedTemplate"
ItemsSource="{Binding Value}"
ItemTemplate="{StaticResource Level3Template}">
<Border Background="Red">
<TextBlock Text="Level2"/>
</Border>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="Level2YellowTemplate"
ItemsSource="{Binding Value}"
ItemTemplate="{StaticResource Level3Template}">
<Border Background="Yellow">
<TextBlock Text="Level2"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="Level1Template"
ItemsSource="{Binding Value}"
ItemTemplateSelector="{StaticResource MySelector}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Template"
Value="{StaticResource ctForTreeViewItem}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<Border Background="Green">
<TextBlock Text="Level1"/>
</Border>
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView Grid.Row="1"
Name="tv"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource Level1Template}">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Template"
Value="{StaticResource ctForTreeViewItem}" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
This works for Level1 as expected, so on Level 1, I have TreeViewItems with the defined ControlTemplate and the Correct HierarchicalDataTemplate.
However, it doesn't work on Level2, where I have an ItemTemplateSelector. At this position, I get this error: System.Windows.Data Error: 25 : Both 'ItemTemplate' and 'ItemTemplateSelector' are set; 'ItemTemplateSelector' will be ignored.
Is there any way, that I can assign a ControlTemplate to the TreeViewItems, while keeping the ItemTemplateSelector? Or even
Is there any other way, that I can change the style of the expander of the TreeView?
Your TreeViewItem ControlTemplate is broken. It ignores the data template selector because you explicitly override that by setting ContentTemplate on the ContentPresenter. That's similar to what's causing the (harmless) errors in your debug output stream as well: The level 2 templates inherit an ItemTemplateSelector from their ancestors, in the same way that if you set ItemContainerStyle once on the TreeView, it will be inherited by all children of the treeview unless some intervening child overrides it explicitly. No need to set it more than once. Because the level 2 templates inherit ItemTemplateSelector and override it with a different property, you get an error, but it's harmless.
I fixed the control template by changing the ContentPresenter for the Header to match the default TreeViewItem control template: I removed the Content, ContentTemplate, and ContentStringFormat attributes. The ContentPresenter has default behavior for all that stuff so you don't need to specify it explicitly.
<ContentPresenter
ContentSource="Header"
Name="PART_Header"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
/>
The template/template selector errors are harmless but I was able to silence them by setting ItemTemplateSelector explicitly to null on the level 2 hierarchical data templates:
<HierarchicalDataTemplate
x:Key="Level2RedTemplate"
ItemsSource="{Binding Value}"
ItemTemplateSelector="{x:Null}"
ItemTemplate="{StaticResource Level3Template}"
>
<Border Background="Red">
<TextBlock Text="Level2"/>
</Border>
</HierarchicalDataTemplate>

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

Automatic Scrolling in a Silverlight List Box with Custom Template

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

Horizontal Scrollbars on a Fluid Listbox

What I want: To get the darn horizontal scrollbar to appear. I will be editing it a bit just so i fits the rest of the app's style scheme, but not too much.
What I have
Here is the code for the listbox as of now. Everything runs perfectly except the scrollbars dont appear. You might say... "well you dont have a scrollviewer anywhere", but I have tried inserting a scrollviewer in numerous places and still no luck.
The Listbox Code:
<ListBox ItemsSource="{Binding Items}" ItemTemplate="{StaticResource itemsdatatemplate}" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" ItemsPanel="{StaticResource HorizontalListBoxTemplate}" ItemContainerStyle="{StaticResource TransparentListBox}" VerticalAlignment="Center" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
The 'TransparentListBox' (to shut-up the selected background color):
<Style x:Key="TransparentListBox" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Border x:Name="HoverBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<Border x:Name="SelectedBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<ContentPresenter></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Horizontal List Box (to make the listbox Horizontal, rather than standard vertical)
<ItemsPanelTemplate x:Key="HorizontalListBoxTemplate">
<StackPanel Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
The Datatemplate (to actually show the Items)
<DataTemplate x:Key="itemsdatatemplate">
<local:ListItemControl HorizontalAlignment="Left" VerticalAlignment="Top" DataContext="{Binding}"/>
</DataTemplate>
I have a feeling its going to be a simple addition, but Thanks in advance.
Update
It looks like the scrollbars now do appear with this:
<Style x:Key="ScrollingListBox" TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Visible">
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But they do not function accordingly. They feel... broken. However, if one was to define a static width (say 300) of the grid, then the ScrollViewer acts perfectly. Right now I have a completely fluid layout (meaning things stretch to fill), is this not acceptable for scrollviewers?
When you create your own template, you have to define the ScrollViewer in there and use an ItemPresenter instead of a ContentPresenter.
<Style x:Key="TransparentListBox" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Border x:Name="HoverBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<Border x:Name="SelectedBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Visible">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources