I see many win store apps have this but I couldn't figure out how it's done. Where basically I have TextBlock and it is pressable, by pressing on it something happens. How do you achieve this? Below is what I saw but it doesn't work.
<Grid x:Name="TitleGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Storyboard x:Name="TitlePressAnimation">
<PointerDownThemeAnimation Storyboard.TargetName="TitlePanel" AutoReverse="True" />
</Storyboard>
</Grid.Resources>
<StackPanel x:ConnectionId='4' x:Name="TitlePanel" Orientation="Horizontal" Margin="120,0,0,0">
<TextBlock x:Name="TitleTextBlock" Text="{Binding DisplayName}" Style="{StaticResource TitleStyle}"/>
</StackPanel>
</Grid>
open your app in blend. Click on textblock you have created and click on 'event handlers for selected item'. its located on the top righthand corner beside 'Name'.
now find a property called 'Tapped'. enter any name there such as 'tap' and doule click. this will create and open the function in c# page. Enter code which you want to be executed there.
here is the function created.
private void Tap(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
// Add code here you want to execute when textblock is clicked.
}
Related
I use LongListSelector to render my db items, Item_SelectionChanged - is default procedure when I click any item. I need to place extra button on LongListSelector item, with different "click" method. But doing this way every time I execute OtherClickOption code it also triggers Item_SelectionChanged as well. Is it possible to prevent this event?
<phone:LongListSelector
x:Name="ItemsLongListSelector"
SelectionChanged="Item_SelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="73"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding ItemText}"/>
<Button Grid.Column="1" Click="OtherClickOption" />
......
First, remove the SelectionChanged event from the LongListSelector. Then add something like a transparent grid to your DataTemplate covering the UI other than the Button and add a Tapped event handler to it where you execute the code you used to execute in the SelectionChanged event handler (modified of course).
My requirement: when tapped on the border in ListViewItem(DataTemplate) an overlay should appear on top of it with animation.
In my listview data template I defined a visual state at the root. I want to goto the visual state when user taps on the border. I have tried following xaml but it is not working
<DataTemplate x:Key="MyTemplate">
<Grid Background="{Binding ItemBackground}"
Margin="0,0,0,5" Height="auto">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup >
<VisualState x:Name="OverlayState">
<Storyboard >
<DoubleAnimation Storyboard.TargetName="checkedBorder"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Height="auto" Margin="14,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="55"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<!--Image Section" -->
<Grid Height="108" Margin="0,8,0,0" VerticalAlignment="Top">
<Grid Margin="0">
<Border HorizontalAlignment="Left" Margin="0" VerticalAlignment="Bottom" Width="98" Height="98" CacheMode="BitmapCache" CornerRadius="30">
<Border.Background>
<ImageBrush ImageSource="{Binding ImageSource}" Stretch="Fill"></ImageBrush>
</Border.Background>
<i:Interaction.Behaviors>
<icore:EventTriggerBehavior EventName="Tapped">
<icore:GoToStateAction StateName="OverlayState" TargetObject="{Binding ElementName=checkedBorder}"></icore:GoToStateAction>
</icore:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Border>
<!-- Overlay Border -->
<Border HorizontalAlignment="Left" Opacity="0" x:Name="checkedBorder" Margin="0" Background="#99000000" VerticalAlignment="Bottom"
Width="98" Height="98" CacheMode="BitmapCache" CornerRadius="30">
</Border>
</Grid>
</Grid>
</Grid>
</Grid>
</DataTemplate>
This question is more complex than I initially thought.
First, let's correct a few issues in your xaml code.
The following line needs to be removed. It's like saying 'go find a state named OverlayState on the checkedBorder element'. Clearly that state is not on that element. Also, changing the ElementName binding to point to the top level Grid (where the visual state group is) won't work either, I will explain why later.
TargetObject="{Binding ElementName=checkedBorder}"
You should always give your VisualStateGroup a name, like this -
<VisualStateGroup x:Name="MyStates">
You need to set IsHitTestVisible to False on your overlay Border, otherwise the Border with image background will not be able to receive the Tapped event because it's sitting behind the overlay one.
I thought it should be good to go. However, if you run the app now, you will get an unhandled exception saying
Target does not define any VisualStateGroups.
If you add back the TargetObject ElementName binding and change it to point to the top level Grid, the exception will go away but the visual state is not called.
TargetObject="{Binding ElementName=myFirstLevelGridWhereTheVSGroupIs}"
This is because a normal VisualStateManager only works for Controls not FrameworkElements since your Grid is not a type of Control.
In a WP Silverlight app, it's fairly simple to fix. All you need to do is to add a built-in CustomVisualStateManager which allows you to pass in a FrameworkElement on top of the VisualStateGroups definition. But such class doesn't exist in WinRT.
I asked a question about this a while ago and eventually came up with an answer.
Include this class into your project, and add the reference in your xaml code, just before your VisualStateGroups definition.
<VisualStateManager.CustomVisualStateManager>
<local:ExtendedVisualStateManager />
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MyStates">
<VisualState x:Name="OverlayState">
Lastly, because unlike the GoToStateAction in Silverlight app, the WinRT's GoToStateAction doesn't handle CustomVisualStateManager, you will have to create a custom GoToStateAction too.
public class ExtendedGoToStateAction : DependencyObject, IAction
{
public string StateName
{
get { return (string)GetValue(StateNameProperty); }
set { SetValue(StateNameProperty, value); }
}
public static readonly DependencyProperty StateNameProperty =
DependencyProperty.Register("StateName", typeof(string), typeof(ExtendedGoToStateAction), new PropertyMetadata(string.Empty));
public bool UseTransitions
{
get { return (bool)GetValue(UseTransitionsProperty); }
set { SetValue(UseTransitionsProperty, value); }
}
public static readonly DependencyProperty UseTransitionsProperty =
DependencyProperty.Register("UseTransitions", typeof(bool), typeof(ExtendedGoToStateAction), new PropertyMetadata(false));
public object Execute(object sender, object parameter)
{
return ExtendedVisualStateManager.GoToElementState((FrameworkElement)sender, this.StateName, this.UseTransitions);
}
}
And replace the built-in one with this.
<i:Interaction.Behaviors>
<iCore:EventTriggerBehavior EventName="Tapped">
<local:ExtendedGoToStateAction StateName="OverlayState"/>
</Core:EventTriggerBehavior>
You should be able to see the animation working now. :)
In my application, I am having a ListView. ListView lists a set of images.
So when the application is running, and when that page is loaded, a list of images are shown.
<ListView ItemsSource="{Binding imageLists}" Background="Red" Tapped="ListView_Tapped">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="Green">
<Image Source="{Binding imagePath}" CacheMode="BitmapCache" Stretch="UniformToFill"/>
<StackPanel Name="imageTitle" Visibility="Collapsed" Background="Blue"
HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Foreground="White" Text="Dumy Image Title" FontSize="10"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As you can see from the code, I have one image & stackpanel inside the listview. And the stackpanel's visibility has been set to collapsed for convenience.
The StackPanel imageTitle resides inside the ListView. Stackpanel contains a TextBlock housing the images name. For now it's dumy text.
On Tapping any image in the list, I am trying to make the stackPanel visible.
The Code Behind:
private void ListView_Tapped(object sender, TappedRoutedEventArgs e)
{
imageTitle.Visibility = Windows.UI.Xaml.Visibility.Visible;
}
Since the stackpanel is inside the listview & I am trying to make it visible on the tap event of the listview, I am not able to acheive the needed result. I know my code is wrong.
If I specify the stackpanel outside the listview, I can make it visible using the code I gave inside the ListView_Tapped function. But even in that case, I need to show the stackpanel (name of the image I clicked) inside the listview item (image I clicked).
Any help??
Can this be achieved using only XAML?
Here's a pure xaml way.
Rather than changing the Visibility of the imageTitle (not a great UX), let's change its Opacity to make its appearing more interesting.
First we need to create a storyboard inside this data template. This storyboard will fade in the imageTitle in 400ms.
And then we drag a ControlStoryboard behavior from Expression Blend's Asset panel onto the top level Grid. Basically we want the storyboard to fire off when this Grid is tapped.
Please see below code for reference.
<DataTemplate x:Key="GroupTemplate">
<Grid Background="Green">
<Grid.Resources>
<Storyboard x:Name="ShowImageTitleStoryboard">
<DoubleAnimation Duration="0:0:0.4" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="imageTitle"/>
</Storyboard>
</Grid.Resources>
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Tapped">
<Media:ControlStoryboardAction Storyboard="{StaticResource ShowImageTitleStoryboard}"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<Image Source="{Binding Image}" CacheMode="BitmapCache" Stretch="UniformToFill"/>
<StackPanel x:Name="imageTitle" Background="Blue"
HorizontalAlignment="Center" VerticalAlignment="Center" Opacity="0">
<TextBlock Foreground="White" Text="Dumy Image Title" FontSize="10"/>
</StackPanel>
</Grid>
</DataTemplate>
Apart from JustinXL's answer it can also be done by using ChangePropertyAction. Also pure XAML:
<DataTemplate>
<Grid Background="Green">
<Image Source="{Binding imagePath}" CacheMode="BitmapCache" Stretch="UniformToFill">
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="Tapped">
<ic:ChangePropertyAction TargetObject="{Binding ElementName=imageTitle}" PropertyName="Visibility" Value="Visible"/>
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Image>
<StackPanel Name="imageTitle" Visibility="Collapsed" Background="Blue"
HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Foreground="White" Text="Dumy Image Title" FontSize="10"/>
</StackPanel>
</Grid>
</DataTemplate>
It's just another way to change a property - JustinXL's answer will provide nice animation with opacity, which will look much better.
I dunno why you specifically want to handle the scenario using XAML. For the Microsoft's recommended MVVM model you should bind a property to your element field and then you can write a converter for the same to return back "Visible" or "Collapse".
I am using Long List Selector in my app, I have made groups and group headers in it.
Now, I am adding a button in the group header and want the button to open new page.
But, when I click on the button it navigates to new page as well as opens the "Jump List". I don't want the jump list when I click the button.
I have found this link, but, here is no clear answer.
Is there any way to disable the "tap" event on "group header" and call when needed?
My code is:
xaml:
<DataTemplate x:Key="groupHeaderTemplate">
<Border HorizontalAlignment="Stretch" Height="70" Background="{Binding Converter={StaticResource BackgroundConverter}}" Margin="6">
<Grid HorizontalAlignment="Stretch" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Title}"
FontSize="40" Padding="6"
VerticalAlignment="Center"
Foreground="{Binding Converter={StaticResource ForegroundConverter}}" />
<Button Content="addNew" Name="addNew_btn" Grid.Column="1" Click="addNew_btn_Click_1" Tag="{Binding transType}" />
</Grid>
</Border>
</DataTemplate>
CS:
private void addNew_btn_Click_1(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/Expense.xaml", UriKind.Relative));
}
If I understand right, you want to open the jump list when you tap outside the button and open another page when you tap on a button. To do that you can just register for the Tap event instead of click on the button and inside the Tap event handler set e.Handled = true; that will prevent the event to bubble and the the Jump list to open when pressing the button.
I am trying to get a listview to display a list of items made up of textblocks...
when the listview item is clicked i would like to show instead a list made up of textboxes...
Below is what i have come up with, it does not work.
I have two grids within the templates and was hoping to simply show and hide the grids depending on if the listview item is selected. Where have i gone wrong?
I ripped these visual states from the listview's template itself but i must admit im not sure how they work, or how they are meant to be triggered. Should there be some code behind to do this?
<ListView Grid.Row="2" ItemsSource="{Binding Lines}" HorizontalAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid Name="Readonly">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding One}" Grid.Column="0"/>
<TextBlock Text="{Binding Two}" Grid.Column="1"/>
</Grid>
<Grid Name="Editing" Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding One}" Grid.Column="0"/>
<TextBox Text="{Binding Two}" Grid.Column="1"/>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Editing" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Readonly" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Many thanks,
Kohan
You are setting the Storyboard Animation up outside the Items that are being rendered. The targets you are specifying are not only out of the scope of the outer page, but they potentially do not exist yet. As a result, the Storyboard cannot be setup when the page is rendered.
Here's what you want to do.
Create a user control that will represent the layout you want in your ListView item. When you define your ListView, be sure to include your UserControl in your DataTemplate, like this:
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<local:MyUserControl />
</DataTemplate>
</ListView.ItemTemplate>
</ListView.ItemsPanel>
</ListView>
Now, for the VisualStates. You need to set the states up inside the UserControl. That means a state for Edit and a state for View. A state needs to be localized like this. Think of the Button control. The states in a button are defined in each Button not some shared location.
When you are ready to change the state of one of the items, you need to wire it to your code behind. In your code behind, you need to loop through the items in your ListView and call a method you create, something like MakeStateEdit() and MakeStateView(). It will be your implementation of those methods that sets the states of the user control. The outside code just trusts it to happen.
This means you need to call VisualStateManager.GoToState(this, "Edit", true); (or whatever state you create) inside your UserControl, in the code-behind. Conversely you might set the "View" state when the MakeStateView() is called.
To iterate a ListView Items property, you need to use a technique like this (http://blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html). You'll find that once you start down this path, it really isn't very complicated. You might be disappointed that you can't do all of this in XAML. You can't. But it can be done!
Best of luck!
I don't know if visual state changes propagate, so maybe your solution should somehow work, but I would edit the visual states in the ListViewItem template instead (through ItemContainerStyle).