Call Method on event in xaml in Xamarin Forms - xaml

In WPF I call my Load method like so(using my MainViewModel in the DataContext):
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded" >
<i:InvokeCommandAction Command="{Binding LoadCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
How can I do something similar in Xamarin Forms? Maybe on the Appearing event? Something like this, except I'm not sure where to go from here.
<ContentPage.Triggers>
<EventTrigger Event="Appearing">
</EventTrigger>
</ContentPage.Triggers>

You need to write TriggerAction for that.
Xaml Usage
<ContentPage.Triggers>
<EventTrigger Event="Appearing">
<local:DummyTriggerAction/>
</EventTrigger>
</ContentPage.Triggers>
Trigger Action Class:
public class DummyTriggerAction : TriggerAction<ContentPage>
{
protected override void Invoke (ContentPage page)
{
//do whatever you want
}
}

Related

Interaction Trigger before selectionChanged of ListPicker in Windows Phone 8

I have a issue when trigger comes in ViewModel the SelectedItem(parameter) comes the previously selected Item. I need the newly selected item as parameter on selectionChanged.
I am new in WP8. Below is the code
<toolkit:ListPicker Header="Background"
ExpansionMode="FullscreenOnly"
Template="{StaticResource ListPickerControlTemplate}"
VerticalAlignment="Top"
ItemsSource="{Binding Path=Buildings.ObjectList}"
Margin="0"
x:Name="buldings"
Padding="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding Path=BuildingSelectionCommand}"
CommandParameter="{Binding Path=SelectedItem, ElementName=buldings}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Thanks
Vinod
Normally should you get the currently SelectionItem passed as parameter to your Command. Since the event is written in past tense, so that you should get the currently SelectedItem and not the previously one.
What you can try is to add a binding for the SelectedItem to your ListPicker and omit passing the SelectedItem to your Command as parameter.
<toolkit:ListPicker SelectedItem="{Binding SelectedBuilding, Mode=TwoWay}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding Path=BuildingSelectionCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</toolkit:ListPicker>
Your command then needs to access the property SelectedBuilding to execute
public class BuildingSelectionCommand{
// a reference to your ViewModel that contains the SelectedBuilding-Property
public BuildingsViewModel ViewModel {
get;
set;
}
public bool CanExecute(object parameter) {
return ViewModel.SelectedBuilding != null;
}
public void Execute(object parameter){
var selectedItem = ViewModel.SelectedBuilding;
// execute command logic with selectedItem
}
}
The code can be diffrent on your side, cause it depends on how you have implemented your ViewModel and Command, but i think you should get it.
Another way without using an EventTrigger, is to execute the command directly in your SelectedBuilding-Property.
public Building SelectBuilding{
get {
return _selectedBuilding
}
set{
_selectedBuilding = value;
RaisePropertyChanged("SelectedBuilding");
if (BuildingSelectionCommand.CanExecute(_selectedBuilding)) {
BuildingSelectionCommand.Execute(_selectedBuilding);
}
}
XAML:
<i:EventTrigger EventName="SelectionChanged">
<command:EventToCommand Command="{Binding BuildingSelectionCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
Command:
RelayCommand<SelectionChangedEventArgs> BuildingSelectionCommand { get; set; }
BuildingSelectionCommand = new RelayCommand<SelectionChangedEventArgs>(async (args) => { });
You just missed the "PassEventArgsToCommand". Make sure your command has a SelectionChangedEventArgs.
The simple way to solve it is to use
SelectedItem="{Binding SelectedBuilding, Mode=TwoWay}"
as Jehof suggested and get rid of all the "<i:" trigger settings but simply handle the change in the SelectedBuilding property setter and call a method instead of using commands to wrap a method call. You are not gaining anything with a command since you are not even using CanExecute here, but simply adding more code.

Alternative to Triggers on WP8

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>

how to trigger xaml code from Class in WPF?

It works fine:
<Button Width="100" Height="30" Content="Click Me!">
<Button.ToolTip>
<Border Margin="-4,0,-4,-3" Padding="10" Background="Silver">
<Border.BitmapEffect>
<OuterGlowBitmapEffect></OuterGlowBitmapEffect>
</Border.BitmapEffect>
<Label>Nice tooltip</Label>
</Border>
</Button.ToolTip>
</Button>
However, I would like the code to revoke when there is a condition. For example:
if(str=="aaa")
MessageBox.Show("All will be o'kay");
else
{
//I would like this code to revoke
/* <Border.BitmapEffect>
<OuterGlowBitmapEffect></OuterGlowBitmapEffect>
</Border.BitmapEffect>
*/
}
How to do it?
Just create a property which raises notification . You can implement INotifyPropertyChanged Interface. Change value of property in code and bind it with xaml.

Binding events to buttons in an ItemsControl

I have a windows phone 7 app with some xaml that looks like:
<Grid x:Name="ContentGrid" Grid.Row="1">
<ItemsControl x:Name="MyView" ItemTemplate="{StaticResource MyInner}"/>
</Grid>
The item template here looks like:
<DataTemplate x:Key="MyInner">
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{StaticResource MyInner_Item}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
And finally, the MyInner_Item template looks like:
<DataTemplate x:Key="MyInner_Item">
<Button x:Name="MyButton">
<Button.Template>
<ControlTemplate>
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="myborder">
<Image Source="{Binding Path=ImageUri}" Width="{Binding Path=Width}" Height="{Binding Path=Height}" Stretch="Fill" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
So, it's an ItemsControl, which contains an ItemsControl, which contains buttons. This essentially creates a 2D array of buttons.
What I want to do is add an event handler to the Click event of the buttons.
Here's the catch: the code that sits behind this is written in F#. I can't, to the best of my knowledge, specify my event handler in the XAML, as F# doesn't talk to WPF in any nice way. So I need to add my event handler(s) manually in code.
Is there an easy way of doing this?
Currently, I have some F# which looks like:
let myView : ItemsControl = this?MyView
do myView.ItemsSource <- viewModel.BoardData
Here, the BoardData is a list of lists.
I was wondering if it's possible to loop through the controls in the ItemsControl, to add my event handlers? I'm having a bit of trouble doing this though. For example, in the following:
let container = myView.ItemContainerGenerator.ContainerFromItem(myView.Items.[0])
...sets container to null. In fact, all the methods I've tried from myView.ItemContainerGenerator returns null.
So, how should I go about attaching my event handler, so that I can respond to the buttons being clicked?
I have not done any Windows 7 Phone development, but I have done plenty of XAML + Silverlight development with C# and now I'm getting into doing some F# development. The approach I would take is by not using event handler's at all. Since you are using a button, make a class that derives from ICommand and add that type as a public property on your ViewModel so you could bind it to the Command property of the button. The benefits of using the ICommand interface over event handlers is that you could also have a condition on when the button is enabled to do the action.
Also, take notice that when you are doing binding expressions within (i.e. ItemTemplate) items in an ItemsControl control, the scope of what properties you can bind to are reduced to the properties of the current item. So all of the properties of the ViewModel are out of scope, unless you specify it fully i.e. <Button Command={Binding Source=ViewModel, Path=Property1.Property2.etc} />. Let me know if this helped.

eventocommand not working

I am making one application in MVVM using Galasoft MVVM Light toolkit. However i can't make EventToCommand make it work with Telerik Context Menu. Here is my code :-
<ListBox x:Name="lstPhotoAlbums" ItemsSource="{Binding AlbumsCollection}"
Margin="3,0" Grid.Row="1" ItemsPanel="{StaticResource wrapPanelItemsPanelTemplate}"
ItemTemplate="{StaticResource ListboxPhotosDataTemplate}"
ItemContainerStyle="{StaticResource ListboxPhotoAlbumsContainerStyle}" Height="500" HorizontalAlignment="Left" VerticalAlignment="Top" Width="178">
<telerik:RadContextMenu.ContextMenu>
<telerik:RadContextMenu x:Name="albumsCtxMenu">
<telerik:RadMenuItem Header="Delete" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding DeleteAlbumCommand}" CommandParameter="{Binding SelectedItem, ElementName=lstPhotoAlbums}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadMenuItem>
</telerik:RadContextMenu>
</telerik:RadContextMenu.ContextMenu>
</ListBox>
I do hit the breakpoint in my viewmodel. However the command parameter is always null. Any ideas where i am wrong?
Thanks in advance :)
As this is an old post, you might have found the answer to your question. However, as I was trying to do the same, I did not find a precis answer to this and if others are looking for the same, I hope this might help them.
You will need to remove the CommandParameter argument from your EventToCommand and change it to this:
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding DeleteAlbumCommand}" PassEventArgsToCommand="True" />
Your RelayCommand in your ViewModel or whereever you are implementing your RelayCommand would have to look something like this:
RelayCommand<EventArgs> DeleteAlbumCommand = new RelayCommand<EventArgs>(CallbackMethod);
CallbackMethod should then look something like this:
private void CallbackMethod(EventArgs eventArgs)
{
...
}
Hope this will help.