Metro App Change ListView Selected Item Content Foreground - xaml

I have a ListView and modified it's DataTemplate with 2 TextBlocks.
The first TextBlock contains a Heading, the second a Sub-Heading.
I style the 2 TextBlocks with different colours.
Here's an example of the ListViewItem in Normal view.
Here's an example of the ListViewItem in Selected view.
So my question is how do I change the Foreground colours of the TextBlocks in Selected views? Hoping to do this in the xaml. I've tried setting different brushes, which work for items that haven't explicitly been styled.
Not sure how to handle this scenario.

You can use visual states.
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock x:Name="txtOne" Grid.Row="0" Foreground="Green"/>
<TextBlock x:Name="txtTwo" Grid.Row="1" Foreground="Gray"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="txtOne" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="txtTwo" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Yellow"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

You don't need to play with the visual state.
In your ResourceDictionary, set a value for these brushes "ListBoxItemSelectedBackgroundThemeBrush", "ListBoxItemSelectedPointerOverBackgroundThemeBrush", "ListBoxFocusBackgroundThemeBrush". It will override the default brushes of your application.
Example:
<!-- Overrides default ListBox brushes -->
<SolidColorBrush x:Key="ListBoxItemSelectedBackgroundThemeBrush" Color="{StaticResource GreenColor}" />
<SolidColorBrush x:Key="ListBoxItemSelectedPointerOverBackgroundThemeBrush" Color="{StaticResource LightGreenColor}" />
<SolidColorBrush x:Key="ListBoxFocusBackgroundThemeBrush" Color="Transparent" />
Here is a usefull link when developping in WinRt, which references the brushes name, for the default controls of winRt.
WinRt default brushes names and values

Thanks to some researching and thinking out of the box, found a suitable solution that works:
Metro App ListView SelectedItem Selected VisualState
I can see this being handy for a couple of other scenarios as well.

Related

VisualStateManager not working inside Button.ContentTemplate UWP

I have been struggling with this for a few days now unable to find solution after lot of effort. This is the code where I'm facing the issue. SO I have a ItemsControl where each element is Button and each Button has an Image and TextBlock. On hovering over Button I could see the Background of Button being changed to Red as expected. But I'm unable to change the Foreground of TextBlock to Green. Any help in this regard is highly appreciated
<ControlTemplate x:Key="ButtonTemplate" TargetType="ContentControl">
<Grid Background="Transparent" x:Name="Mini">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="Mini.Background" Value="Red" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="MiniContent" />
</Grid>
</ControlTemplate>
<DataTemplate x:Key="ListItemTemplate" x:DataType="local:DataModel">
<Button
Template="{StaticResource ButtonTemplate}">
<Button.ContentTemplate>
<DataTemplate x:DataType="local:DataModel">
<UserControl>
<Grid >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="Value.Foreground" Value="Green" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="Value"
Foreground="Yellow"
Text="{x:Bind DisplayName, Mode=OneWay}"/>
<Image
Width="16"
Source="{x:Bind ImageBitmap, Mode=OneWay}"/>
</Grid>
</UserControl>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</DataTemplate>
<ItemsControl
ItemTemplate="{StaticResource ListItemTemplate}"
ItemsSource="{x:Bind DataModelVector, Mode=OneWay}" />
You need something to actually transition between the VisualStates, the PointerOver state isn't triggered automatically. The easiest way would be to factor the content of your DataTemplate into its own file (UserControl with markup and code-behind) and handle pointer events in code to transition between visual states using VisualStateManager.GoToState.
You could also create a reusable "StateTrigger" for transitioning any control into a "PointerOver" visual state, but often some code-behind is simpler.

UWP ListviewItem Customize Pointer Events preserving Drag & Drop functionality

Following this question, I'm with the same and other doubts.
Like the user #fipcurren88 I were using Buttons inside ListView ItemTemplate to customize the behavior of pointer events (Pointer Over and Pressed). This is the way I usually do it until I found Drag and Drop didn't work and using a Button inside a ItemTemplate is the wrong approach (like #Filip Skakun mentioned in the same question).
Removing the custom Button and using Itemtemplate directly with the content I want (an Image for example - the custom Button content) I didn't knew how to set the background colors for other states (pointer over and pressed for example). I found out the solution using ListViewItemPresenter in the ItemContainerStyle were I can set different backgrounds to each Pointer Event.
But, I lost the PointerDownThemeAnimation on the Item and I don't know how to get it back. Using a Button is easy, but it affects the Drag and Drop functionality.
This is the Problem Number 1.
This works with simple Items (a single Image), but imagine I have a more complex Item (a Image, a Grid and a TextBlock inside the Grid). I want to change the Grid Background (or the Textblock Foreground) while Pointer is over and/or while the pressed event.
In this case I know the ListViewItemPresenter solution will not work. I need a more specific way to define the different states (VisualStateManager, Common States). Using a custom Button will affect the Drag and Drop functionality (the starting point of the other thread).
What can I do?!
Let's call this Problem Number 2.
Any UWP/XAML Expert that can clear me mind? Thank you.
These requests can all be done in the xaml code by modifying the ListViewItem styles and templates, and doing this will not affect the Drag and Drop function of ListView.
For your both questions, you can copy the style of x:Key="ListViewItemExpanded" into your Page.Resource and remove the x:Key="ListViewItemExpanded", so will this style be applied to all the ListViewItems in your page.
If you have Grid, Image, and TextBlock together in an item, you can set ListView like this:
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Height="100" Width="100" Grid.Column="0"
Source="{Binding image}" />
<TextBlock Grid.Column="1" FontSize="20" Text="{Binding txt}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Then if you want to change the background of the item and the the foreground of your text when your item is in PointerOver or Pressed state, you just need to find this two VisualStates in the style and for example modify them like this:
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="Blue" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Blue" />
</ObjectAnimationUsingKeyFrames>
<PointerDownThemeAnimation TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
By doing this, the Background targets the background of the whole item, not just the Grid. The Grid will adapt to the controls inside it even you set HorizontalAlignment="Stretch" to the Grid by default, this is because by default it uses ContentPresent like this:
<ContentPresenter x:Name="ContentPresenter"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}" />
If you change the HorizontalAlignment and VerticalAlignment properties in the style to Stretch, your Grid in the DateTemplate will fill the whole item. In this scenario, changing the Background of BorderBackground and the Foreground of ContentPresenter in the visual state can still work.

GridView's ItemContainerStyle and selection states

I'm trying to change the appearance of gridview items when they are selected.
(Before, I used a trick with an IsSelected property in the ViewModel object bound to the containing grid and a bool-to-color converter, but I recognize that it is bad)
To do so, I do:
<GridView ItemContainerStyle="{StaticResource GridViewItemContainerStyle}" ...> ...
and
<Style x:Key="GridViewItemContainerStyle" TargetType="GridViewItem">
<Setter Property="Background" Value="Red" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Background)" Storyboard.TargetName="itemGrid">
<DiscreteObjectKeyFrame KeyTime="0" Value="Black"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="UnselectedSwiping"/>
<VisualState x:Name="UnselectedPointerOver"/>
<VisualState x:Name="Selecting"/>
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Background)" Storyboard.TargetName="itemGrid">
<DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedSwiping"/>
<VisualState x:Name="Unselecting"/>
<VisualState x:Name="Unselected"/>
<VisualState x:Name="SelectedUnfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid ... x:Name="itemGrid">
<!-- HERE MY DATA TEMPLATE -->
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When I run the app, the items are Black (as in the "normal" state). But selecting them does not turn them into White. Where am I wrong?
Moreover, it there a way to set "ItemContainerStyle" without having it to "overwrite" the "ItemTemplate" ???
You DataTemplate should be inside the ItemTemplate property of the GridView element in your page's XAML. Make a separate XAML file (ResourceDictionary), for example CustomStyles.xaml. Reference it in App.xaml like this:
<Application.Resources>
<!-- Application-specific resources -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="PathToCustomStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
You can find on MSDN the default template for GridViewItem (http://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj709915.aspx), under the Default style section (second, longer XAML).
Copy that and paste it into CustomStyles.xaml. Just give it some key like:
<Style TargetType="GridViewItem" x:Key="CustomGridViewItemStyleWithWhiteSelectionBackground">...
As you can see, Selected visual state changes the opacity of three targets, SelectionBackground, SelectedBorder and SelectedCheckMark. So, these elements are not visible in Normal state because their opacity is zero. Find those three elements down below, and change their properties if needed. For the background change the Fill property of the SelectionBackground rectangle:
<Rectangle x:Name="SelectionBackground"
Margin="4"
Fill="White"
Opacity="0" />
Now, when the selection occurs, this element's opacity will be changed to 1 and since you set it's Fill to be white, the background of the selected item will be white. And don't forget to reference this style in the definition of the GridView:
<GridView ItemContainerStyle="{StaticResource CustomGridViewItemStyleWithWhiteSelectionBackground}" ...>
<GridView.ItemTemplate>
<DataTemplate>
...define your template here...
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Edit:
This is the expanded style XAML, probably more suitable for some more complicated style changes. If you want to change only the background, you should take the first style from that MSDN link above under the Default style section, and just edit this (and give it some style key, so you don't overwrite the default one):
SelectedBackground="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}"

Slider component in WP8 won't move

I have a Slider component in my WP7 and WP8 app. In WP7, the Slider moves according to its Scheduler, but in WP8, it simply just won't move.
The Slider is styled, and I know there is some changes in WP8. First of all, what exactly are those changes and what do I change in code? The documentation from Microsoft is poor. Anyone got an idea of what this can be, maybe other than the changes from Microsoft?
And even if I set the default value to something, the thumb will always be in its starting position. I can't move it either.
For me, this applies to a various different styles, e.g. from Mifrosofts own Slider Styles and Templates.
This one has a template:
<Slider x:Name="Slider" IsHitTestVisible="true" Value="{Binding SliderValue, Mode=TwoWay}" Maximum="100" VerticalAlignment="Center" Margin="0,24,0,0" Template="{StaticResource SliderControlTemplate1}" />
Here is the template:
<ControlTemplate x:Key="SliderControlTemplate1" TargetType="Slider">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="0.1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HorizontalTrack"/>
<DoubleAnimation Duration="0" To="0.1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VerticalTrack"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="HorizontalFill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="VerticalFill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="HorizontalTemplate" Margin="{StaticResource PhoneHorizontalMargin}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="12"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="HorizontalFill" Fill="{TemplateBinding Foreground}" Height="12" IsHitTestVisible="False" Margin="0"/>
<Rectangle x:Name="HorizontalTrack" Grid.Column="2" Fill="{TemplateBinding Background}" Height="12" IsHitTestVisible="False" Margin="0" Opacity="0.2"/>
<RepeatButton x:Name="HorizontalTrackLargeChangeDecreaseRepeatButton" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}"/>
<RepeatButton x:Name="HorizontalTrackLargeChangeIncreaseRepeatButton" Grid.Column="2" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}"/>
<Thumb x:Name="HorizontalCenterElement" Grid.Column="1" Height="12" Margin="0" Width="12">
<Thumb.Template>
<ControlTemplate>
<Grid ManipulationDelta="ProgressBarManipulationDelta" Width="46" Height="46" VerticalAlignment="Center" HorizontalAlignment="Center">
<Image Source="/slider.png"/>
</Grid>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
</Grid>
</ControlTemplate>
And I have tried a corresponding Style. What could be the problem? Should I use Style or Template? Both acts equally for me now..
Had the same issue. Before WP8, we had edited a copy of its original style and modified it to our purposes. Later, when upgrading the project to WP8 this modified style from WP7 caused the slider not getting updated anymore as the style has changed since. Removing the style fixed it. In case the modifications are still needed, you should get the original style from WP8's slider component.

Windows 8 metro app XAML - make a custom button blinks when clicked?

so from this free software, I could make myself my own metro button as seen below:
the icon is white though, so may not see it properly, and I put it in my Grid (written in XAML) here:
Still it is technically an image, so I made it into Button, here's a code of transformed image into button:
<Button x:Name="Button_CreateAccount" Content="" HorizontalAlignment="Center" Height="65" Margin="0" Style="{StaticResource Button_CreateAccount}" Width="65" Click="Button_CreateAccount_Clicked"/>
see I name it "Button_CreateAccount", add a Clicked event handler "Button_CreateAccount_Clicked", and using a custom style "{StaticResource Button_CreateAccount}"
it works as I expected, but unlike any other button, it won't blink when pressed and release the blink when released, maybe because it is technically an image. So I reckon I could programmatically make it "blinked" when being pressed by changing its style. Here's the unedited style added automatically by Blend in Visual Studio 2012:
<Style x:Key="Button_CreateAccount" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
<VisualState x:Name="PointerOver"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="PointerFocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image Source="Assets/Icons_White/add_user.png" Stretch="Fill"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, I do not speak XAML language :( I don't have any idea how to simply change the color of the background of the image once being pressed. Any help would be deeply appreciated, thanks!
First, you should make the image have a transparent Background and not a green background. After that do not use your style and change your button to be this
<Button x:Name="Button_CreateAccount" HorizontalAlignment="Center"
Height="65" Margin="0" Width="65" Click="Button_CreateAccount_Clicked"
Background="Green">
<Image Source="Assets/Icons_White/add_user.png" Stretch="Fill"/>
</Button>
From here you will start to see the color changing when you press. If you want to change what the color is then give the button a new style. The best way is to use Visual Studio or Blend and right click the Button (in design view or in the document outline) and select Edit Template -> Edit a copy...
Change the colors within the Pressed VisualState to change the color when the button is pressed.
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Blue"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ButtonPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>