Alternative to Triggers on WP8 - xaml

I've read that Triggers are not supported in XAML for WP8. What's the alternative approach? I wanted to use a trigger to change the background image of a button when tapped.

You could, potentially just attach an event handler for the "Tap" event for the image. Without code examples, I'm not too sure how much I can help; however, I've pasted some code below:
XAML
<Image Source="/Assets/awesomeImg.png" Tap="AwesomeImg_Tap"/>
Code Behind (C#)
private void AwesomeImg_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
YourImageName.ImageSource = //code here to URI of image
}
Hope this helps!

Please try this.
Windows phone triggers msdn
Here I binded the image data trigger with my Boolean property , when the Boolean property is changed it will trigger and the setter will fire. Make sure you properties are implemented with INofityPropertyChanged
xmlns:ec="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" x:Class="XXX_XXXX"
<Image Source="/Assets/Images/Tick.png"
Stretch="None"
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<interactivity:Interaction.Triggers>
<ec:DataTrigger Binding="{Binding IsTapped}" Value="True">
<ec:ChangePropertyAction PropertyName="Source">
<ec:ChangePropertyAction.Value>
<BitmapImage UriSource="/Assets/Images/Close.png"/>
</ec:ChangePropertyAction.Value>
</ec:ChangePropertyAction>
</ec:DataTrigger>
</interactivity:Interaction.Triggers>
</Image>

Related

Weird ImageButton's behavior on ListView

ImageButtons on a ListView is giving me a headache. Take a look at the gif here.
As you can see, the ImageButtons (3 vertical dots on the right of every ListView row) which were hidden gets super small as the ListView is scrolled up and down.
This is the corresponding XAML:
<ImageButton
Source="more_options"
HorizontalOptions="End"
WidthRequest="21"
BackgroundColor="Transparent"
Clicked="OnMoreOptionsTapped"
CommandParameter="{Binding .}"
Grid.Column="2"
Grid.Row="0"/>
Full XAML is here. ImageButton is at line 56.
I'm doing something wrong? How can I fix this?
Also, I know I could use just an Image with a TapGestureRecognizer but that's being a big issue for me, because I need access to the Image element to get it's coordinates and spawn the menu on the right location. Doing that with an ImageButton is a piece of cake, but it's not so easy with a TapGestureRecognizer. I did something like this:
XAML
<Image
Source="more_options"
Aspect="AspectFit"
HorizontalOptions="End"
WidthRequest="21"
BackgroundColor="Transparent"
Grid.Column="2"
Grid.Row="0">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnMoreOptionsTapped"
CommandParameter="{Binding .}"/>
</Image.GestureRecognizers>
</Image>
Code-behind:
private void OnMoreOptionsTapped(object sender, TappedEventArgs args)
{
var tapGesture = sender as TapGestureRecognizer;
var button = tapGesture.Parent as Image;
...
}
Basically, with an ImageButton element, the object sender is an ImageButton element, but with an Image, the object sender is a TapGestureRecognizer and I can't find a way to get the Image parent while I have only the TapGestureRecognizer child. Also, tapGesture.Parent is null and tapGesture.Parent.Parent is null too. I've tried both.
So:
ImageButtons on ListView are bugging out hard. Anyone have a fix?
Anyone could tell me how to get the Image parent having only the child TapGestureRecognizer?
I believe answering any of those two questions would solve my problem hehe.
Also, this is one of my first experiences asking questions here, I beg your pardon if I did something wrong.
Thanks all :)
The reason behind your issue is a bug that is currently in the xamarin listview which can be found here :
https://github.com/xamarin/Xamarin.Forms/issues/5200
Solution is to downgrade to v3.4 for now until we get an intimate from XF side
Goodluck revert if you have queries

How to implement text boxes with multiple options like people app at runtime in uwp app?

I am developing a UWP app and I have to make a control like in the People app for Windows 10.
I am currently trying this
<StackPanel x:Name="stp">
<Button Content="Button 1" x:Name="btnAction1">
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem Text="Action 1" Click="MenuFlyoutItem_Click">
</MenuFlyoutItem>
</MenuFlyout>
</Button.Flyout>
</Button>
</StackPanel>
and in c#
private void MenuFlyoutItem_Click(object sender, RoutedEventArgs e)
{
btnAction1.Margin = new Thickness(0, 10, 0, 0);
stp.Children.Add(new TextBox() { Name = "newTxtBox", Text="Tushar"});
}
But this will end up handling UI too much with no animation at all. I want to give an option to the user to remove this dynamically created control.
After that I would want something like this:Dynamically adding textboxes with animation and option to close
Can anybody please help?
Thanks in advance.
Check the documentation of Flyout and use the LightDismissOverlayMode property to suit your scenario. If any particular UI specific implementation required, post a screenshot.

Using x:Bind inside the GridView's ItemTemplate layout User Control in UWP

In the Universal Windows Platform API, how do I use x:Bind inside of a User Control (intended to be the layout for a GridView's ItemTemplate) to bind to instance properties of a GridView's ItemSource?
Background
I'm trying to re-create the layout found in Windows 10 stock apps like Sports, News, Money, etc.
I'm using a two GridViews for the main area of the app; one for "featured articles" (2 large photos w/ headlines) and one for all the other articles (smaller photos w/ headlines).
I'm able to bind to a data source that I supply in the code behind (a List where NewsItem is a POCO with a Image and Headline property) Here's the pertinent parts of the MainPage.xaml:
<Page ...
xmlns:data="using:NewsApp.Models" />
....
<GridView Name="FeaturedItems" Grid.Row="0">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:NewsItem">
<Grid Name="mainPanel" HorizontalAlignment="Stretch" Width="500" >
<Image Source="{x:Bind Image}" HorizontalAlignment="Stretch" />
<TextBlock Text="{x:Bind Headline}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
....
The Image and Headline bind just fine (even though they've not been styled correctly). However, instead I think I need to bind to a User Control to get the styling options I want, control over resizing esp. when using Visual State Triggers and to simplify the XAML in general (at least, this was the technique suggested to me.)
So, I added a new User Control to the project (FeaturedItemControl.xaml), and copied in the DataTemplate's child Grid:
<UserControl ... >
<Grid Name="mainPanel" HorizontalAlignment="Stretch" Width="500" >
<Image Source="{x:Bind Image}" HorizontalAlignment="Stretch" />
<TextBlock Text="{x:Bind Headline}" />
</Grid>
</UserControl>
And then back in the MainPage.xaml, I change the DataTemplate to reference the new FeaturedItemControl:
<GridView Name="FeaturedItems" Grid.Row="0">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:NewsItem">
<local:FeaturedItemControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
However, I get the error message for both Image and Headline properties: Invalid binding path 'Headline': Property 'Headline' can't be found on type 'FeaturedItemControl'.
I've tried a few things but am flailing just throwing code at the problem without understanding what I'm doing. Any help would be greatly appreciated.
Thank you for your kind attention.
Using Depechie's answer, I formulated this little cheat cheat for posterity:
Do note that you MUST use this technique to utilize the VisualStateManager with items inside your data bound controls' (GridView, ListView) data templates.
1) Create a User Control.
2) Cut the content of the DataTemplate in your page and paste it into the User Control replacing the template's Grid.
3) Reference the User Control from inside the Data Template:
4) Modify the contents of the User Control changing x:Bind statements to utilize object.property notation:
<UserControl>
<StackPanel>
<Image Source="{x:Bind NewsItem.LeadPhoto}" />
<TextBlock Text="{x:Bind NewsItem.Headline}" />
<TextBlock Text="{x:Bind NewsItem.Subhead}" />
</StackPanel>
</UserControl>
5) Add this in the User Control's Code Behind:
public Models.NewsItem NewsItem { get { return this.DataContext as Models.NewsItem; } }
public ContactTemplate()
{
this.InitializeComponent();
this.DataContextChanged += (s, e) => Bindings.Update();
}
Well it's possible to use x:Bind in user controls, but you'll need to add some extra code behind.
I encountered the same problem in my project, you can see the result here : https://github.com/AppCreativity/Kliva/tree/master/src/Kliva/Controls
So what you need to do is, create a property in the code behind of your user control that points to the correct DataContext.
If you do that, you can use properties of that DataContext in the xaml of your control: for example:
Do note that in the constructor of your control you do need to add: DataContextChanged += (sender, args) => this.Bindings.Update(); because the datacontext will change depending on the page where your control is used!
Then on the page where you are placing this control, you'll also need to do the same to enable the x:bind to work.
You'll see this in my example on the MainPage.DeviceFamily-Mobile.xaml and MainPage.xaml.cs files.
Hope this helps.
x:Bind isn't really hierarchical like Binding/DataContext is. Additionally when you're not directly inside a DataTemplate (such as inside your user control) the object that x:Bind tries to use is 'this' rather than 'this.DataContext'. My current line of thinking on how to solve this sort of issue is to try not to use UserControls anywhere. Instead preferring DataTemplates contained within a ResourceDictionary. There are some pretty strong caveats to this approach though, you will for example crash the xaml compiler if you use x:Bind inside a data template that was created from the ResourceDictionary item template (add new item). you can find a pretty complete example here https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlBind its important to note in the sample where they show the ResourceDictionary being used that its not actually just a ResourceDictionary.xaml its also a ResourceDictionary.xaml.cs (this is where the generated code from x:Bind ends up)
Another option is to add Headline and Image as properties on your user control and x:Bind them from the template, then inside the user control x:Bind as you are currently doing, but now the x:Bind generated path 'this.Headline' will exist. Unfortunately the order things are actually bound means that the x:Bind's you have inside your user control will have to be OneWay rather than the default OneTime. this is because x:Bind OneTime does the bind inside the InitializeComponent call, and any set of properties/DataContext stuff doesn't get done until after that has already run.
So to sum this up, you have two options, use data templates everywhere, or bind to properties that are directly on the user control.

Start An Event After Scrolling

I'm new to Windows Phone apps development, and I've created a scrolling menu using the following xaml code :
<ScrollViewer HorizontalAlignment="Left" Margin="18,0,0,0" Name="scrollViewer1" VerticalAlignment="Top" Width="450" HorizontalScrollBarVisibility="Auto" Grid.Row="1">
<StackPanel Height="Auto" Name="stackPanel1" Width="Auto">
<Button Height="620" FontSize="120" Name="gotoGmail" Width="Auto">Gmail</Button>
<Button Height="620" FontSize="120" Name="gotoYahoo" Width="Auto">Yahoo</Button>
</StackPanel>
</ScrollViewer>
I'd like to know whether it's possible to start an event once the user scrolls the menu from one button to another. If it is possible, i'd be grateful if you could explain how. If it's not , i'd like to hear about how could I do it using different tools rather than ScrollViewer. Thanks in advance !
There's no "Scrolled" event on the ScrollViewer, but what you can do is two-way bind a property to VerticalOffset. That lets you trigger an event/command from your view/viewmodel when the scroll changes.
Something like this:
<ScrollViewer VerticalOffset="{Binding VerticalOffset,Mode=TwoWay}" ...
And then in the data context:
public double VerticalOffset
{
get { return _verticalOffset; }
set
{
_verticalOffset = value;
// call "on scroll changed" actions here
}
}
private double _verticalOffset = 0;
how could I do it using different tools rather than ScrollViewer
You can of course make a scrolling menu using other approaches. I'll bet there is some nifty approach you could figure, using the WinRT transitions/animations stuff, but I'm not familiar enough with those to say. Here are some others (not sure which would be best/easiest for your scenario):
Probably using Canvas would be a quick-and-dirty way to do it (just set up buttons that set off Canvas.Left and Canvas.Top animations).
Extending ItemsControl along with a custom ControlTemplate would be a good approach if you want to create a re-usable component.
I like extending Panel, but you have to do the animations manually using a DispatcherTimer, and you have to lay out the buttons yourself using Measure and Arrange.

Animation when add or remove item from GridView XAML

How create own animation when item add or remove from GridView? For example change colour from dark to light.
If Item is a Grid:
<Grid.Transitions>
--> There can be only predefinied *ThemeTransitions?
</Grid.Transitions>
Is other way to do this?
Tim is correct that the Transitions are pre-defined at this point. However, you should be able to achieve your scenario using Storyboard. There are probably several ways to do this, e.g. retemplating GridViewItem and adding new "Loading"/"Unloading" visual states. Here is a simple way to achieve your scenario by putting a Storyboard in the ItemTemplate:
MainPage.xaml:
<GridView x:Name="MyGV">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Loaded="Grid_Loaded" x:Name="TemplateRoot" Opacity="0" Background="White">
<Grid.Resources>
<Storyboard x:Key="LoadedStoryboard">
<DoubleAnimation Storyboard.TargetName="TemplateRoot"
Storyboard.TargetProperty="Opacity"
BeginTime="0:0:1"
Duration="0:0:5"
To="1" />
</Storyboard>
</Grid.Resources>
<TextBlock Text="{Binding}" FontSize="24" Foreground="Black" Margin="40" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
MainPage.xaml.cs:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
Storyboard sb = ((Grid)sender).Resources["LoadedStoryboard"] as Storyboard;
sb.Begin();
}
Example source code is hosted here:
https://github.com/finnigantime/Samples/tree/master/examples/Win8Xaml/GridViewItemLoadedUnloadedAnimations
What if the set that is used as the GridView's ItemsSource was an ObservableCollection and your code behind listened for changes from that collection? Then from the code behind you could control animations.
Correct, there can only be pre-defined transitions. The transition model is not exposed publically at this time.
The rows added to the "parent" ListView of a GridView could be fed in several ways, but often are bound to a ObservableCollection of something.
The columns of the GridView are governed with a ObservableCollection, as well, so the context should be pretty similar.
I published an article on how to manage the columns' management (with animation) just some days ago. Perhaps could help you.
http://highfieldtales.wordpress.com/2013/08/08/hacking-the-wpf-gridview-adding-the-animation/
UPDATE: pardon me, but I realized later that you meant the XAML for Store apps. My reference is for WPF, instead.