UWP Scrolling ListView on touchscreen doesn't work - c#

I'm trying to design an UWP App for a tablet and one of the elements I'm using is a ListView. When I'm scrolling with a mouse inside the ListView it works, but if I'm trying to scroll on a touchscreen the ListView automatically snaps back to the default position. How can I solve this problem?
<ListView x:Name="PlayerListBox" HorizontalAlignment="Left" Grid.Column="0" VerticalAlignment="Top" Width="404" ScrollViewer.VerticalScrollBarVisibility="Hidden" Height="620" Margin="-3,0,0,0">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="FontSize" Value="24"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimation Duration="0" To="#0078D7" Storyboard.TargetProperty="(ListViewItem.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="Content1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<TextBlock x:Name="listItem1" TextWrapping="WrapWholeWords" />
<ContentPresenter x:Name="Content1" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>

Related

How to keep the ToggleButton status after re-enable

I want to keep the ToggleButton status after re-enable the ToggleButton.But It keep turning off.
Here is my ToggleButton when the Ellipse is actived:
When the ToggleLock is turned on:
After unlocking:
It's wrong color.It have to turn to green color.
My code and Style:
<!--EllipseToggleButton Style-->
<Style TargetType="ToggleButton"
x:Key="EllipseToggleButton">
<Setter Property="Margin"
Value="20 10 0 10" />
<Setter Property="Height"
Value="30" />
<Setter Property="VerticalAlignment"
Value="Top" />
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid Name="contain">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="icon"
Storyboard.TargetProperty="(Path.Fill).(Color)"
To="#3D727272"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimation x:Name="IconCheckedColorAni"
Storyboard.TargetName="icon" Duration="0"
Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)"
To="#FF68E80F" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse Name="icon"
Height="24"
Width="24"
Stretch="Uniform"
VerticalAlignment="Center"
Cursor="Hand"
Fill="{TemplateBinding Background}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
MainWindow:
<StackPanel Orientation="Horizontal">
<ToggleButton x:Name="ToggleLock"
Content="Lock"
Width="100"
Margin="20 10 0 10"
VerticalAlignment="Top"
Height="30" />
<ToggleButton Style="{StaticResource EllipseToggleButton}"
IsEnabled="{Binding ElementName=ToggleLock, Path=IsChecked, Converter={StaticResource InBConv}}"
Background="Red" />
</StackPanel>
Converter:
class InvertBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is bool)
{
return !(bool)value;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
The ToggleButton does retain its IsChecked value while it is disabled. When it is re-enabled, however, the visuals don't match: When you un-toggle the lock, you activate the CommonStates.Normal visual state group, which, near as I can tell, resets the default value on the Ellipse named icon :
Fill="{TemplateBinding Background}"
...making it red. You'll find you need to click the ellipsis twice in order to make it green again.
Since the ellipsis toggle button doesn't change its IsChecked value, the CheckedStates visual state storyboards aren't invoked.
I haven't found any way to fix this in XAML (tried reordering triggers, writing out all states explicitly and so on), but you can work around it by forcing an IsChecked state change from code-behind:
<StackPanel Orientation="Horizontal">
<ToggleButton x:Name="ToggleLock"
Content="Lock"
Width="100"
Margin="20 10 0 10"
VerticalAlignment="Top"
Height="30"
Checked="OnChecked"
Unchecked="OnChecked" />
<ToggleButton
x:Name="toggleButton"
Style="{StaticResource EllipseToggleButton}"
IsEnabled="{Binding ElementName=ToggleLock, Path=IsChecked, Converter={StaticResource InBConv}}"
Background="Red" />
</StackPanel>
...with the following event handler:
private void OnChecked(object sender, RoutedEventArgs e)
{
bool? isChecked = this.toggleButton.IsChecked;
toggleButton.IsChecked = null;
toggleButton.IsChecked = isChecked;
}
I don't know that this is the best possible solution, but it does work, and may serve as a starting point for further investigation.
I think the source of your problem is using the same element for 2 different VisualStateGroup. As you can see here there is an element named "DisabledVisualElement" to handle "Disabled" VisualState that is separate from the element that handles "CheckStates" VisualStateGroup.
Following that, I added another ellipse named "iconDisabled" to the template that has Opacity="0" and its value changes to "1" in "Disabled" VisualState. Also, I added Opacity="1" to your "icon" and it will change to "0" in "Disabled" VisualState.
Here is your modified style code:
<Style TargetType="ToggleButton"
x:Key="EllipseToggleButton">
<Setter Property="Margin"
Value="20 10 0 10" />
<Setter Property="Height"
Value="30" />
<Setter Property="VerticalAlignment"
Value="Top" />
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid Name="contain">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0"
Storyboard.TargetName="iconDisable"
Storyboard.TargetProperty="Opacity" To="1" />
<DoubleAnimation Duration="0"
Storyboard.TargetName="icon"
Storyboard.TargetProperty="Opacity" To="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimation x:Name="IconCheckedColorAni"
Storyboard.TargetName="icon" Duration="0"
Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)"
To="#FF68E80F" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<ColorAnimation x:Name="IconUncheckedColorAni"
Storyboard.TargetName="icon" Duration="0"
Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)"
To="Red" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse Name="icon"
Height="24"
Width="24"
Opacity="1"
Stretch="Uniform"
VerticalAlignment="Center"
Cursor="Hand"
Fill="{TemplateBinding Background}" />
<Ellipse Name="iconDisable"
Height="24"
Width="24"
Opacity="0"
Stretch="Uniform"
VerticalAlignment="Center"
Cursor="Hand"
Fill="#3D727272" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Other parts of the code are the same as you wrote in question post.
I'm using IsHitTestVisible instead of IsEnabled.
Here is the way I fixed my issue:
<ToggleButton x:Name="ToggleLock"
IsChecked="{Binding OptionLocked}"
Content="Lock"
Width="100"
Margin="20 10 0 10"
VerticalAlignment="Top"
Height="30" />
<ToggleButton x:Name="toggleButton"
IsChecked="{Binding EllipseChecked}"
Style="{StaticResource EllipseToggleButton}"
IsHitTestVisible ="{Binding OptionLocked, Converter={StaticResource InvertBoolConv}}"/>
I having another issue.I can't set background color to Gray when the ToggleLock is turning on.At least it's working.I will accept it if no more answer come in a few days.
I want to say thank Petter Hesselberg and TheSETJ.
Finally I have fixed it.Here is a new ControlTemplate:
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimation x:Name="IconCheckedColorAni"
Storyboard.TargetName="icon"
Duration="0"
Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse Name="icon"
Height="24"
Width="24"
Stretch="Uniform"
VerticalAlignment="Center"
Cursor="Hand"
Fill="{TemplateBinding Background}"
Visibility="Visible" />
<Ellipse Name="iconDisable"
Height="24"
Width="24"
Stretch="Uniform"
VerticalAlignment="Center"
Cursor="Hand"
IsHitTestVisible="{TemplateBinding IsHitTestVisible}"
Fill="3D727272"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsHitTestVisible">
<Trigger.Value>
<sys:Boolean>False</sys:Boolean>
</Trigger.Value>
<Setter TargetName="iconDisable"
Property="Visibility"
Value="Visible" />
<Setter TargetName="icon"
Property="Visibility"
Value="Collapsed" />
</Trigger>
<Trigger Property="IsHitTestVisible">
<Trigger.Value>
<sys:Boolean>True</sys:Boolean>
</Trigger.Value>
<Setter TargetName="iconDisable"
Property="Visibility"
Value="Collapsed" />
<Setter TargetName="icon"
Property="Visibility"
Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
And MainWindow.xaml:
<ToggleButton x:Name="ToggleLock"
IsChecked="{Binding OptionLocked}"
Content="Lock"
Width="100"
Margin="20 10 0 10"
VerticalAlignment="Top"
Height="30" />
<ToggleButton x:Name="toggleButton"
IsChecked="{Binding EllipseChecked}"
Style="{StaticResource EllipseToggleButton}"
IsHitTestVisible ="{Binding OptionLocked, Converter={StaticResource InvertBoolConv}}"/>

Change the ListBox Item Border Color

I have list box with style added to it.
Here is my code:
<!-- Style for list item selector -->
<Style x:Key="ListItemSelectorStyle" TargetType="ListBoxItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property ="Foreground" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="ListBoxItem" Background="{TemplateBinding Background}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ListItemBorder" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="#c9ebf2" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ListItemBorder" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="#c9ebf2" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ListItemBorder" BorderBrush="Transparent" Background="#e3e8f0">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock
Name="textBlock"
Text="{Binding Path=answerText}"
HorizontalAlignment="Stretch"
Padding="10,25,10,25"
MinHeight="80"
VerticalAlignment="Center"
TextAlignment="Center"
Style="{StaticResource TextStyle}"
Foreground="Black"/>
<Image Name="ImageBlock"
Grid.Row="0"
Width="Auto"
Height="Auto"
Stretch="UniformToFill"
Source="{Binding answerImage}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="1,1,1,1"/>
</Grid>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My List box :
<ListBox Name="listBox"
HorizontalAlignment="Stretch"
ItemContainerStyle="{StaticResource ListItemSelectorStyle}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
SelectionChanged="ListBoxClicked"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Here i have added two colors one for default item color "#e3e8f0" and one is Selected item and MouseOver color "#c9ebf2" in my style
Now I have a button and its click event in my .CS file Now when i click on that the Selected item and MouseOver color "#c9ebf2" should be changed to Green color,
How to acheive this ?
You have given #c9ebf2 color for both mouseover and selected state in your style. Change your color for selected state.

Only highlight currently selected item in ListBox

I have a ListBox being populated with images from isolated storage. The user is allowed to select the image to perform some action upon it. To notify the user of the currently selected image in the list, I simply have placed a border around the selected item. However, when a new image is selected in the list, the border is placed around that image as well, so now both images have a border. I would like to find a way to remove the previously selected image's border so that only the currently selected image is highlighted.
What I have so far is as follows:
MainPage.xaml
<ListBox x:Name="Recent" ItemsSource="{Binding Pictures}" Margin="8"
SelectionChanged="recent_SelectionChanged" toolkit:TiltEffect.IsTiltEnabled="True">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border>
<Image x:Name="recentImage" Source="{Binding Source}" Margin="12" Width="115"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
MainPage.xaml.cs
private void recent_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Place border round currently selected image
var lb = sender as ListBox;
var lbi = lb.ItemContainerGenerator.ContainerFromItem(lb.SelectedItem) as ListBoxItem;
lbi.BorderThickness = new Thickness(2, 2, 2, 2);
lbi.BorderBrush = new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"]);
//Where and how to remove border from previously selected image?
}
So, I am not sure of what exactly to do to accomplish this. How might I detect the previously selected image item in the ListBox, or determine which item has the border and remove it before adding the border to the currently selected item? Any thoughts or references?
You need just edit ItemContainer style of your ListBox.
Like this:
<phone:PhoneApplicationPage.Resources>
<Style x:Key="MyStyle" TargetType="ListBoxItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property ="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot" Background="{TemplateBinding Background}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="ContentContainer" Storyboard.TargetProperty="Opacity" Duration="0" To=".5" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="brd"
Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="2" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="brd" CornerRadius="10" BorderBrush="White" Width="Auto" BorderThickness="{TemplateBinding BorderThickness}">
<Image x:Name="recentImage" Source="{Binding Source}" Margin="12" Width="115"/>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</phone:PhoneApplicationPage.Resources>
And your ListBox will be:
<ListBox x:Name="Recent" ItemsSource="{Binding Pictures}" Margin="8"
SelectionChanged="recent_SelectionChanged" toolkit:TiltEffect.IsTiltEnabled="True" ItemContainerStyle="{StaticResource MyStyle}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
Instead of highlighting selected item from code behind, why not set style for selected item in client side.
What I mean to say is, you can use <Style.Triggers> to set the style for selected item in your listbox. (Assuming only one item can be selected at a time)
Sample code- (this sets background of selected item to white . You can apply your style here)
<Style x:Name="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="Selector.IsSelected" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
You may do something like this. (This is just a skeleton. you will have to implement the class properly)
public class MyImage
{
public string ImagePath { get; set; }
public bool IsSelected { get; set; }
}
Set a collection of this class as the source of your listbox.
When you select an item Mark
IsSelected=true;
Remember this property should be "false" for all unselected items.
Now your borders visibility can be set based on IsSelected property.Hope this helps.

How to solve: the attachable property triggers was not found in style in a Grid Application

I'm using Visual Studio 11 in Windows8. And setting the data trigger in a Grid Application (Metro) shows me this error in XAML:
the attachable property triggers was not found in style
<Image Stretch="UniformToFill">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{Binding Image}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Image}" Value="{x:Null}">
<Setter Property="Source" Value="Images/Default.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Why show me this?
Triggers aren't supported in Windows 8 Metro style apps. I'd suggest you write a converter which will replace null value with the default one.
you can use VisualState instead of object.Triggers in Windows 8 Here is the code
<ControlTemplate TargetType="Button">
<VisualStateGroup.Transitions>
<!--Take one half second to transition to the PointerOver state.-->
<VisualTransition To="PointerOver"
GeneratedDuration="0:0:0.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ButtonBrush"
Storyboard.TargetProperty="Color" To="Red" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Background>
<SolidColorBrush x:Name="ButtonBrush" Color="Green"/>
</Grid.Background>
</Grid>
</ControlTemplate>

WP7 ListBox ItemContainerStyle XAML disabled not working

I have the following style and list box:
<Style x:Key="LwHListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Padding" Value="24, 0, 24, 0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot" BorderBrush="#FFCCCCCC" BorderThickness="0, 0, 0, 1" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Duration="0" To=".5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentContainer"/>
<DoubleAnimation Duration="0" To="0.6" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="LayoutRoot" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ListBox x:Name="lbxContainer" Height="Auto" Width="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" VerticalAlignment="Top" ItemContainerStyle="{StaticResource LwHListBoxItemStyle}" />
I used Expression Blend to create the style. I want the ListBoxItem to have a 60% opacity when disabled. I'm populating the ListBox programatically with ListBoxItems that have their IsEnabled property set based on certain criteria. I've stepped through the debugger and confirmed that the ListBoxItems do have IsEnabled = false, so my conclusion is that there must be something wrong with my xaml. Is there something I'm missing or doing wrong that is causing the items to not become opaque when disabled?
The ListBox is on a white background and has black text as the content. The opacity should make it gray. If I add opacity to the normal visual state, it shows up as intended for the normal state, but also for the Disabled state. I know the disabled items are actually disabled because I can't click on them. I figured that the code below would show normal state as opaque but disabled items without opacity.
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Duration="0" To="0.6" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="LayoutRoot" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
Update: I'm pretty sure there is something wrong with my disabled state. Nothing I add in the disabled state takes hold, even if I change the background to blue. I am creating ListBoxItems programatically and setting the content property to a user control I have created. Could this be causing problems? It doesn't make sense to me because I can set the normal state with 60% opacity and it works, so why wouldn't the disabled state?
You should not be using a ContentControl inside your control template. You should be using a ContentPresenter instead. You can run into weird issues by having a ContentControl displaying the content of another ContentControl.
Aside from that, the ListBoxItem will only go into the "Disabled" state, if the ListBoxItem.Content is not a Control. If the ListBoxItem.Content is a Control, then it will transition to the "Normal" state even if ListBoxItem.IsEnabled is false.
You've created a style for the ListBoxItem, but not for the ListBox itself. And you don't have to, necessarily. The problem is that by default the ListBox has a white background.
So the first step is to set the ListBox background to Transparent like this...
<ListBox x:Name="lbxContainer" Background="Transparent" Height="Auto" Width="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" VerticalAlignment="Top" ItemContainerStyle="{StaticResource LwHListBoxItemStyle}" />
Then I just made a couple changes to your ListBoxItem style...
<Style x:Key="LwHListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Padding" Value="24, 0, 24, 0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot" BorderBrush="#FFCCCCCC" Background="{TemplateBinding Background}" BorderThickness="0, 0, 0, 1" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="0.6" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="LayoutRoot" />
<DoubleAnimation Duration="0" To="0.6" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentContainer"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And now as long as the container around the ListBox is not white, then a disabled ListBoxItem should appear translucent thanks to the Opacity setting.
For example...
<Grid Background="Black">
<ListBox x:Name="lbxContainer" Background="Transparent" Height="Auto" Width="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" VerticalAlignment="Top" ItemContainerStyle="{StaticResource LwHListBoxItemStyle}">
<ListBoxItem Content="enabled a" />
<ListBoxItem Content="disabled b" IsEnabled="False"/>
<ListBoxItem Content="enabled c"/>
</ListBox>
</Grid>
Will look like this...

Categories