I am trying to create a different template for a list view item when it is selected, however I couldn't find anything about doing this.
What is the best way to select a template based on whether the listview item is selected or not?
What is the best way to select a template based on whether the listview item is selected or not?
Changing the default template and customize animation inside VisualState is the right way.
Copy and paste the default ListViewItem styles and templates in your project, see here
Change the brush in the Selected and PointerOverSelected visual states:
SystemControlHighlightListAccentLowBrush in the Selected visual state:
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentLowBrush}" />
</ObjectAnimationUsingKeyFrames>
Change to:
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
SystemControlHighlightListAccentMediumBrush in the PointerOverSelected visual state:
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
Change to:
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
Screenshot:
Check my completed sample here
-----Update(09/27/2016)-----
How would I use this to change the DataTemplate of a ListBoxItem when it's selected
If you need to switch DataTemplate, you might change it from code behind.
1) Append a DataTeemplate in the page's resource:
<Page.Resources>
<DataTemplate x:Key="dataTemplate1">
<StackPanel Orientation="Horizontal">
<TextBlock Text="->" />
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Page.Resources>
2) Add handler for SelectionChanged event:
<ListView SelectionChanged="ListView_SelectionChanged">
<ListView.Items>
<ListViewItem Content="One"></ListViewItem>
<ListViewItem Content="Two"></ListViewItem>
<ListViewItem Content="Three"></ListViewItem>
</ListView.Items>
</ListView>
3) Change DataTemplate from code behind
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Assign DataTemplate for selected items
foreach (var item in e.AddedItems)
{
ListViewItem _lvi = item as ListViewItem;
_lvi.ContentTemplate = (DataTemplate)this.Resources["dataTemplate1"];
}
//Remove DataTemplate for unselected items
foreach (var item in e.RemovedItems)
{
ListViewItem _lvi = item as ListViewItem;
_lvi.ContentTemplate = null;
}
}
Have updated my demo: LINK
Related
I have a Grid which should be collapsed by default it is in A xaml file.
Another Button in Grid in another xaml file.When clcik button Grid should be enabled.
How to achieve this I have Tried this can you please help
<Grid Visibility={Binding Visibilityproperty}/>
<Button Content="A" Command={Binding VisibilityCommand"}/>
In button command i have written the logic to enable the visibilityproperty to visible
But grid is not at all visible if i do like this
Better solution in MVVM pattern is welcomed
<Button Content="Button!">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.Target="{x:Reference dataGrid}"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0"
Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
{x:Reference dataGrid} references a DataGrid with the name dataGrid, alternatively you could just use Storyboard.TargetName. You would normally use the Storyboard.Target property if you do binding or references to resources.
I want to change the default text style (foreground color, font weight, etc) for pivot item header text when the header is selected.
E.g., if I have the following:
<Pivot>
<PivotItem Header="One"></PivotItem>
<PivotItem Header="Two"></PivotItem>
</Pivot>
I want the selected pivot item to be bolded when selected and/or change the foreground color (or maybe put the text in a border, etc). I don't want to change the default style for the unselected items.
Thanx,
The XAML framework offers many ways to customize the appearance of your apps. Styles let you set control properties and reuse those settings for a consistent appearance across multiple controls. You create a control template when you want to customize a control's visual structure and visual behavior.
You don't need to put the text of pivot header in a border, edit the Style for PivotHeaderItem would be a good choice, and you can add this style to the Resources of the Page.
Resources are typically definitions of some object that you expect to use more than once.
There is a default PivotHeaderItem styles and templates, you can copy it and add this to you page resources just like this:
<Page
x:Class="..."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Style TargetType="PivotHeaderItem">
...
</Style>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
...
</Grid>
</Page>
Now if you want to change the foreground of the text in header when the item is selected, you can edit the <VisualState x:Name="Selected"> like this:
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
If you want to change the text of header to be bold, you can edit above VisualState like this:
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="FontWeight">
<DiscreteObjectKeyFrame KeyTime="0" Value="Bold" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
You can leave other VisualStates as defalut, if you just want to change the style when the item is selected.
In XAML
<Pivot SelectionChanged="Pivot_SelectionChanged">
<PivotItem>
<PivotItem.Header>
<TextBlock Text="One"></TextBlock>
</PivotItem.Header>
</PivotItem>
<PivotItem>
<PivotItem.Header>
<TextBlock Text="Two"></TextBlock>
</PivotItem.Header>
</PivotItem>
</Pivot>
In C#
private void Pivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Pivot pivot = sender as Pivot;
PivotItem pivotItemSelected = ((PivotItem) ((Pivot) sender).SelectedItem);
for (int i = 0; i < pivot.Items.Count; i++)
{
PivotItem pivotItem = pivot.Items[i] as PivotItem;
TextBlock tb = pivotItem.Header as TextBlock;
if (pivotItem == pivotItemSelected)
{
//Style
tb.Foreground = new SolidColorBrush(Colors.Blue);
}
else
{
tb.Foreground = new SolidColorBrush(Colors.Black);
}
}
}
I hope this can help you
How to customize the view of item that was selected in ListBox control? In my case I want to define the color of background of selected item.
Thank you!
Try this
private void listLocs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBoxItem myitem = listLocs.SelectedItem as ListBoxItem;
SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(255,255,0,0));
myitem.Background = brush;
}
More details from:
How can I change selected item's background color in Windows Phone?
You can accomplish this by styling the ListBoxItem with the ItemContainerStyle property of the ListBox. Use the following steps
In Visual Studio (or Blend) open the page (xaml) with your ListBox on it.
View the design.
Right click the ListBox and select Edit Additional Templates -> Edit Generated Item Container (ItemContainerStyle)
Select a name a location for this style
In the selection states add a new animation for background.
So, your Storyboard would change from:
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
To:
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
below i have a control template that comprises of two text box. The control template is used as a grid's cell display template and the datacontext is a bindinglist of my model object (which implement INotifyPropertyChanged). The second text box is initially Collapsed. However when "Ask" and "Bid" price updates happen, i want to 'flash" this text box by toggling visibility for about 1 second.
The problem i'm seeing is that on initial load of the form, i do see the 2nd text box flash, but after that...nothing. Interestingly if i click on a cell grid (which activates the edit template) then click out of the cell (which reverts back to the display template, which is the template shown below), the 2nd textbox then flashes.
Can anyone see an issue why the 2nd textbox would not 'flash' when AskPrice or BidPrice changes? I do see that the converter is being invoked as expected, but the update is not triggering the storyboard animation.
<Style x:Key="PriceSpreadAlertStyle" TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed" />
<Setter Property="Background" Value="Red" />
<Style.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated" >
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00.2" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.4" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.6" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.8" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:01.0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:01.2" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="QuoteDisplayTemplate" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding QuotePrice}" />
<TextBlock Style="{StaticResource PriceSpreadAlertStyle}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource AskBidToSpreadConverter}">
<Binding Path="AskPrice" UpdateSourceTrigger="PropertyChanged" NotifyOnTargetUpdated="True" />
<Binding Path="BidPrice" UpdateSourceTrigger="PropertyChanged" NotifyOnTargetUpdated="True" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</ControlTemplate>
Check to see that its 'getting' your value in the code behind when you do a NotifyPropertyChanged.
For the same reason, check for any binding expression errors when you initially start up.
Also, you could try changing the binding modes to oneway, I didn't think so but they could be getting set to a onetime binding preventing it from handling the changed event.
EDIT:
Have you tried using the SourceUpdated RoutedEvent instead of the TargetUpdated?
The solution that i found was to move 'NotifyOnTargetUpdated="True"' from the Binding element to the MultiBinding element.
I would like to have an item's width shrink on a click of a button.
Right now I have two objects basically, when you click the button on objectA, a storyboard starts that rotates it around the x-axis and collapses it. Then it shows objectB by setting it's visibility to visible and rotates it around into view.
All I want to add is setting the width smaller while the storyboard is happening to objectA and objectB and then setting it back to normal at the end of the storyboard.
I tried setting the Thickness but I got a compile-time error complaining that it was readonly.
<ObjectAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="objectA"
Storyboard.TargetProperty="(UIElement.Margin)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Thickness Left="10" Right="10"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
I have a simple layout for now...
Here is my UI XAML:
<StackPanel>
<Border x:Name="objectA" BorderBrush="Blue" BorderThickness="1" Height="100" Width="100">
<StackPanel>
<TextBox Margin="10"></TextBox>
<Button Width="50" x:Name="btn1" Content="Flip" Click="btn1_Click"/>
</StackPanel>
<Border.Projection>
<PlaneProjection RotationX="0"></PlaneProjection>
</Border.Projection>
</Border>
<Border Visibility="Collapsed" x:Name="objectB" BorderBrush="Red" BorderThickness="1" Height="100" Width="100">
<StackPanel>
<TextBox Margin="10"></TextBox>
<Button Width="50" x:Name="btn2" Content="Flip" Click="btn2_Click"/>
</StackPanel>
<Border.Projection>
<PlaneProjection RotationX="90"></PlaneProjection>
</Border.Projection>
</Border>
Here is the storyboard...
<Storyboard x:Name="Storyboardtest">
<DoubleAnimation BeginTime="00:00:00"
Storyboard.TargetName="objectA"
Storyboard.TargetProperty="(UIElement.Projection).(RotationX)"
From="0" To="-90">
</DoubleAnimation>
<ObjectAnimationUsingKeyFrames
BeginTime="00:00:01"
Storyboard.TargetName="objectA"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
BeginTime="00:00:01"
Storyboard.TargetName="objectB"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="00:00:01"
Storyboard.TargetName="objectB"
Storyboard.TargetProperty="(UIElement.Projection).(RotationX)"
From="90" To="0">
</DoubleAnimation>
</Storyboard>
If it is just the visual width you want to affect, add the following to your storyboard. It will give the appearance of the controls moving into the distance and back as it flips:
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="objectA">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="objectB">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
you will also need to add the following as I used Expression blend to add the animation and it adds any required elements automatically:
<Border x:Name="objectA" BorderBrush="Blue" BorderThickness="1" Height="100" Width="100" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<CompositeTransform/>
</Border.RenderTransform>
[Snip]
<Border Visibility="Collapsed" x:Name="objectB" BorderBrush="Red" BorderThickness="1" Height="100" Width="100" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<CompositeTransform/>
</Border.RenderTransform>
The problem is that both the Width and Margin properties are not DependencyProperties so they can not be animated. On workaround method to accomplish this involves adding some custom DependencyProperties to your user control code-behind which can be hooked up to the storyboard and can in turn manipulate the actual properties of the objects.
For example you could add this DependencyProperty to your UserControl which basically allow the setting of the Width property of object A:
public static readonly DependencyProperty ObjectWidthProperty = DependencyProperty.Register(
"ObjectWidth",
typeof(double),
typeof(MainPage),
new PropertyMetadata(50.0, new PropertyChangedCallback(OnObjectWidthChanged)));
public double ObjectWidth
{
get { return (double)GetValue(ObjectWidthProperty); }
set { SetValue(ObjectWidthProperty, value); }
}
private static void OnObjectWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MainPage)d).OnObjectWidthChanged(e);
}
private void OnObjectWidthChanged(DependencyPropertyChangedEventArgs e)
{
this.objectA.Width = this.ObjectWidth;
}
You could then add the following to your storyboard which would animate the width of objectA from 50 pixels down to 0:
<DoubleAnimation BeginTime="00:00:00"
Storyboard.TargetName="MyControl"
Storyboard.TargetProperty="ObjectWidth"
From="50" To="0"/>
The would also require you to add x:Name="MyControl" to your top-level UserControl. It's a little bit hacky, but it works to animate some of the underlying properties of elements that don't happen to be DependencyPropertys.