XAML Windows Phone 8.1 Button should change backgroundImage - xaml

I know this kind of question have been asked a lot. But I couldn't solve it by my own.
The challenge to achieve is a simple button without any styling except a changing background image for several states (default, pressed and hover).
The code I've done so far is in my App.xaml file:
<Style x:Key="likeActionButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="HoverBackground"
Storyboard.TargetProperty = "Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="PressedBackground"
Storyboard.TargetProperty = "Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border>
<Grid>
<Image Source="Assets/ActionsIcons/like-action.png"></Image>
<Image x:Name="HoverBackground" Source="Assets/ActionsIcons/like-action-onHover.png" Visibility="Collapsed"></Image>
<Image x:Name="PressedBackground" Source="Assets/ActionsIcons/like-action-on-pressed.png" Visibility="Collapsed"></Image>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
[Calling the button style from somewhere]
<Button Style="{StaticResource likeActionButton}"/>
So this XAML code seems to do nothing because there is no image at all..
Cheers,
Chris

It looks like an initial slash is needed to accurately path the location of the image because the image is not relative to the current xaml path.
Change
Source="Assets/ActionsIcons/like-action-on-pressed.png"
to the root of the package with
Source="/Assets/ActionsIcons/like-action-on-pressed.png"
It does not look likes these are dynamic databound images. Dynamic images need ms-appx:/// because they are not declared in xaml and need a special nomenclature to be properly pathed.
I believe the advice to add ms-appx:/// works because it is providing a proper path which can be resolved, but is superfluous if a / is just added to the path.
For a better understanding read How to load file resources (XAML) (Windows)

Related

MouseOver ContentPresenter XAML Style

I need to change colour of mouseover/pointover of content presenter but my style does not work.
Someone help me?
Thanks
<Style x:Key="Test" TargetType="ContentPresenter">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ColorTest}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ColorTest}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Style>
I do not believe this is possible. Visual States are published by specific controls, and ContentPresenter represents something that could be any kind of control or arbitrarily complex tree of elements.
You can use the subsections in Control Styles and Templates to get an idea of which Visual States are valid for each control, but as you see these are specific for the control in question, and not every state is always supported.
Your style could be amended to use Triggers, such as <Trigger Property="IsMouseOver" Value="True">, but then you could only provide setters for properties of ContentPresenter, and Foreground is not one of those.
Update
However, as TextBlock.Foreground is an attached property, you can make the Trigger solution work in your specific example, and including complex control contents. Please note this won't work for all properties however.
<Grid>
<Grid.Resources>
<ControlTemplate TargetType="Button" x:Key="ButtonControlTemplate">
<ContentPresenter />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="TextBlock.Foreground" Value="Red" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="TextBlock.Foreground" Value="Blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Grid.Resources>
<Button Template="{StaticResource ButtonControlTemplate}" Content="Test" />
</Grid>

Windows Store Apps: change the background of GridViewItem on PointerOver

I have a gridview thats' bound to the following model
class Item
{
string Title;
string ImagePath
string ImagePathPressed;
}
where ImagePath & ImagePathPressed are paths to images within the app.
now I want my grid View Item to change it's background when the mouse is over from the value in ImagePath to that in ImagePathPressed
how to achive this ?
it would be better if you make these variables as properties and also implement INotifyPropertyChanged on your class. And on your mouseOver event of gridView change the ImagePath to that of ImagePathPressed it will reflect the change in ImagePath.i think on your mouseover event you can get the on which item is your mouse pointer reside.
Following this link to get guideline to implement Style for GridViewItem
http://msdn.microsoft.com/en-us/library/windows/apps/jj709915.aspx
You should implement your class members as Bindable Properties then implement PointerOver state as guideline in above link.
I suggest that you should create two images (one for normal state and other one for hover state)
For example:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<Border x:Name="OuterContainer">
<Grid>
<Image x:Name="NormalImage" Source="{Binding ImagePath}"/>
<Image x:Name="PressImage" Source="{Binding ImagePathPressed}" Opacity="0"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PressImage"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="1" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">...
OK, I got it
I implemented a control template like this:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<Border x:Name="OuterContainer" Tag={Binding}>
<Border.Resources>
<!-- Define brush resources for both states-->
<ImageBrush x:Key="MouseOverBrush" ImageSource="{Binding Tag.ImagePathPressed, ElementName=OuterContainer}" Stretch="None" />
<ImageBrush x:Key="DefaultBrush" ImageSource="{Binding Tag.ImagePath, ElementName=OuterContainer}" Stretch="None" />
</Border.Resources>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ReorderHintContent" >
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource MouseOverBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
.
.
.
<Grid x:Name="ReorderHintContent" Tag="{Binding}" DataContext="{Binding}" >
<Grid.Background>
<!-- Default background-->
<ImageBrush x:Name="BGBrush" ImageSource="{Binding Tag.ImagePath, ElementName=ReorderHintContent}" Stretch="None" Opacity="0" />
</Grid.Background>
I had to set the Tag for both the border and the Grid in order to have access to the properties of the model

Changing text color for selected ListViewItem in metro UI application

How to get things together?
I'm working on Windows 8 metro application that contains ListView. My listview contains TextBlocks.
Something like this:
MyPage.xaml:
<DataTemplate x:Key="ListViewItemTemplate">
<StackPanel>
<TextBlock Text="{Binding Goal, Mode=OneWay}"/>
</StackPanel>
</DataTemplate>
<ListView x:Name="ChainsList"
ItemsSource="{Binding Chains}"
SelectedItem="{Binding Path=SelectedChain, Mode=TwoWay}"
ItemTemplate="{StaticResource ListViewItemTemplate}"
ItemContainerStyle="{StaticResource ChainsListViewItemStyle}">
</ListView>
I don't like default ListView colors for selected/deselected items, so in Designer mode I selected "Edit additional templates/Edit generated item container" and created own copy of ListViewItem style within StandardStyles.xml:
<Style x:Key="ChainsListViewItemStyle" TargetType="ListViewItem">
<!-- a lot of setters goes here -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border x:Name="OuterContainer">
<!-- description of visual states goes here (I changed some colors) -->
<Grid x:Name="ReorderHintContent" Background="Transparent">
<!-- List view item structure details goes here -->
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now I want to change text color of my list view items depending on selection. If item selected TextBlock's color should be black. If item not selected - white.
AND HERE IS A QUESTION: where should I put logic for chaning TextBlock color? If somewhere in StandardStyles.xml then how I would assign it to TextBlock? If somewhere in list view item template then how should I get selection state?
EDITED:
Try adding these animations to the SelectionStates VisualStateGroup in your ChainsListViewItemStyle style:
<VisualState x:Name="Unselected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="Black"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedSwiping">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="Black"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="Black"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>

WP7 - set button Background and BorderBrush in addition to Foreground color on click

There are a few questions out here which involve settings a Button background color on click.
Those questions used this as the solution:
<phone:PhoneApplicationPage ...>
<phone:PhoneApplicationPage.Resources>
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ColorAnimation Duration="0" To="Cyan" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="ButtonBackground" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" Margin="{StaticResource PhoneTouchTargetOverhang}" Background="Black">
<ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
<Button Content="Button" Style="{StaticResource ButtonStyle1}"/>
</Grid>
</phone:PhoneApplicationPage>
I'm looking to use this template to also set the BorderBrush and Foreground colors, but my tweaking this XAML has only ended up with bad effects.
[Note: the behavior is that when I set the colors in codebehind, they don't take effect when my app is run, because the colors are overridden by the style.]
If you're tweaking XAML manually - You're doing it wrong.
Don't fight the Zen of XAML, flow with it. Embrace Expression Blend into your development workflow for all GUI design, or be prepared for the untold horrors of manual XAML editing.
Specifically for VisualStateManagerm manually editing XAML makes absolutely no sense as it was designed by the Silverlight Team so it could be optimally used from Expression Blend.
I strongly suggest you spend 30 minutes watching these 4 "How Do I?" VSM videos by Steve White # http://expression.microsoft.com/en-us/cc643423.aspx
These 4 videos helped me a lot in the early days of working on VSM to understand how to use VSM and how to best articulate my UI logic into Visual States.
In Expression Blend getting the background colour to change on Click is as simple as:
Drag & drop a new button in Expression Blend.
Right click and "Edit Template --> Edit Copy".
Choose the "Pressed" VSM state from the "States" pane.
Change the background colour of "ButtonBackground".
Check this discussion:
Setting a background property from a storyboard
and also
Button Styles and Templates

How do I make a simple image-based button with visual states in Silverlight 3?

At my previous company, we created our RIAs using Flex with graphical assets created in Flash. In Flash, you could simply lay out your graphics for different states, i.e. rollover, disabled.
Now, I'm working on a Silverlight 3 project. I've been given a bunch of images that need to serve as the graphics for buttons that have a rollover, pressed, and normal state. I cannot figure out how to simply create buttons with different images for different visual states in Visual Studio 2008 or Expression Blend 3.
Here's where I am currently. My button is defined like this in the XAML:
<Button Style="{StaticResource MyButton}"/>
The MyButton style appears as follows:
<Style x:Key="MyButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image Source="/Assets/Graphics/mybtn_up.png" Width="54" Height="24">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Image>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I cannot figure out how to assign a different template to different states, nor how to change the image's source based on which state I'm in. How do I do this? Also, if you know of any good documentation that describes how styles work in Silverlight, that would be great. All of the search results I can come up with are frustratingly unhelpful.
Edit:
I found a way to change the image via storyboards like this:
<Style x:Key="MyButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image Source="/Assets/Graphics/mybtn_up.png"
Width="54" Height="24" x:Name="Image">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard Storyboard.TargetName="Image"
Storyboard.TargetProperty="Source">
<ObjectAnimationUsingKeyFrames>
<DiscreteObjectKeyFrame KeyTime="0" Value="/Assets/Graphics/mybtn_over.png"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard Storyboard.TargetName="Image"
Storyboard.TargetProperty="Source">
<ObjectAnimationUsingKeyFrames>
<DiscreteObjectKeyFrame KeyTime="0" Value="/Assets/Graphics/mybtn_active.png"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Image>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, this seems like a strange way of doing things to me. Is there a more standard way of accomplishing this?
I guess what I did is the way to do it, given how nobody has chimed in. Will just have to accept this as the answer.