This question already has an answer here:
Binding UWP Page Loading/ Loaded to command with MVVM
(1 answer)
Closed 5 years ago.
I would like to bind any UI-Event directly to a command in my ViewModel.
Is there a way to do that in UWP?
I'm using the UWP Community Toolkit and would like to bind the Hamburger-Menu-Item-Click to an command.
Thanks
Tobias
Ok I found the solution for that.
You can find it here: Behaviors in UWP (Event trigger command error
I will repeat my steps here:
1 - Install Package
Install-Package Microsoft.Xaml.Behaviors.Uwp.Managed
2 - Include references to you view
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
3- Add the command to your ViewModel
public DelegateCommand MenuItemCommand { get; set; }
public void InitCommands()
{
MenuItemCommand = new DelegateCommand(MenuItemClicked);
}
private void MenuItemClicked()
{
//do something when clicked
}
4 - Bind the Click-Event of the menuitem to the command in the view (see the i:...-tag)
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<controls:HamburgerMenu x:Name="HamburgerMenuControl"
PaneBackground="Black"
Foreground="White"
ItemTemplate="{StaticResource DefaultTemplate}"
OptionsItemTemplate="{StaticResource DefaultTemplate}"
ItemsSource="{Binding MenuItems}"
OptionsItemsSource="{Binding MenuOptionItems}"
>
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ItemClick">
<core:InvokeCommandAction Command="{Binding MenuItemCommand}"></core:InvokeCommandAction>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
<Frame x:Name="ContentFrame"/>
</controls:HamburgerMenu>
</Grid>
when I know click the menu-item it
Related
This question already has answers here:
Pass an incoming variable with WPF by the user used in a class c#
(2 answers)
Closed 4 years ago.
I have a project with WPF when i introduce a UrlTxt in textbox with name txtCmdUrl
This is my code XAML station.xaml
<UserControl .....>
<Grid x:Name="GridGlobal">
<DockPanel Background="White" Margin="5" >
<StackPanel DockPanel.Dock="Left" HorizontalAlignment="Left" Orientation="Horizontal" Margin="10 0 10 0">
<StackPanel Orientation="Horizontal">
**<TextBox x:Name="txtCommandeUrl" Width="500"
Height="24" VerticalAlignment="Center" />**
<mui:ModernButton x:Name="btnSave" Content="{x:Static
p:Resources.Link_Save_Link}" Click="BtnSave_Click"
VerticalAlignment="Center" Command="{Binding
NextCommand, Mode=TwoWay}" IsEnabled="{Binding
NextEnabled}"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
And in my code behind i used my click button with this code
private string txtUrlStation = "";
//BtnSave_Click
private void BtnSave_Click(object sender, RoutedEventArgs e)
{
try
{
txtUrlStation = txtCommandeUrl.Text;
MessageBox.Show(txtSave);
}
catch
{
}
}
I want to use my variable txtCommandeUrl for another file.xaml exemple station2.xaml in the code behind also.
Who can to help me in this small problem and Thanks
There are several ways to accomplish this sort of thing. Which is best depends on exactly what you want to do.
Here are some you could use:
PRISM eventaggregator or Mvvmlight messenger to send the new value from one to the other as it changes. https://social.technet.microsoft.com/wiki/contents/articles/26070.communicating-between-classes.aspx
Move your property to a static method on a static class which anything can then reference. Making it a "global".
Move your property to an instance class which you then pass round directly from one to another.
Move your property to an instance class which you then pass round indirectly using dependency injection from one to another.
Make it a public property and pass a reference from your first window/whatever to the next. This is more applicable to where the second is a child of the first because you're creating a dependency.
I need to open a new view (item details) on mouse double click in ListView in UWP using MVVM. In WPF I used a command with a parameter and EventTrigger but Microsoft does not recommended to use it in UWP:
Triggers, EventTrigger, Actions and BeginStoryboard are not commonly used. These API mainly exist for compatibility in XAML originally used for Microsoft Silverlight...For events in control templates, use visual states and VisualStateManager.
As I understood it is used when you need to change visual state of the control but I need to open a new view.
How can I use VisualStateManager for my purpose?
There is how my XAML looked in WPF:
<ListBox x:Name="PersonsListControl" Grid.RowSpan="3" Grid.Row="0" Grid.Column="2"
ItemsSource="{Binding Path=PersonsProvider}"
ItemsPanel="{StaticResource PersonsListPanelTemplate}"
ItemTemplate="{StaticResource PersonsListItemTemplate}"
SelectedItem="{Binding SelectedPerson}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction
Command="{Binding GetPersonDetailsCommand}"
CommandParameter="{Binding SelectedPerson}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
In UWP you can use {x:Bind ...} :
<ListBox ...
DoubleTapped="{x:Bind HandleDoubleTapped}" />
And in your ViewModel just create a method :
public void HandleDoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
// your logic
}
References :
DoubleTapped
ListBox
EDIT:
#JörgenSigvardsson pointed out that x:Bind do not bind directly to the DataContext and you should create a proxy property/properties to access particular data from your page.
More on that can be read here
I'm trying to use Caliburn Micro and MVVM for a menu. I'm currently using the Ribbon controls located in System.Windows.Controls.Ribbon. Binding the click event using x:Name works ok for regular buttons in a tab, but the menu items in RibbonApplicationMenu does not work. Is that a bug or do I have to do some extra work in the bootstrapper class to make sure that CM finds the RibbonApplicationMenuItems? I'm on CM v2.0.1.
Some example here:
XAML:
<Ribbon x:Name="Ribbon" >
<Ribbon.ApplicationMenu>
<RibbonApplicationMenu KeyTip="F">
<RibbonApplicationMenuItem Header="{Binding NewText}" x:Name="AppNew" />
</RibbonApplicationMenu>
</Ribbon.ApplicationMenu>
<RibbonTab Header="{Binding OverviewTabText}" >
<RibbonGroup x:Name="MainGroupOverview" Header="{Binding MainGroupText}">
<RibbonButton Label="{Binding NewText}" x:Name="AppNewOverview" />
</RibbonGroup>
</RibbonTab>
</Ribbon>
And in ViewModel class:
public void AppNew()
{
//this will not be called
New();
}
public void AppNewOverview()
{
//this works just fine
New();
}
Still digging on this but for the name attributed doesn't seem to work for anything, actually mocked up a sample on my end. cm:Message.Attach="[Event Click]=[Action NewApp()]" works. Actually strange and you might want to drop by the GitHub repo and fill out if this might actually be an issue. –
I have encountered a rather strange problem using the GalaSoft - MVVM Light Toolkit in a Windows Phone 8 project.
Suddenly (after merging some stuff) all my EventToCommand calls are not working anymore. They worked before. I already tried to remove the MvvmLight toolkit and reference it again with Nuget, but the result stays the same.
One example:
MainMenuPage.xaml
<phone:PhoneApplicationPage
...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:commands="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
....>
<phone:PhoneApplicationPage.DataContext >
<Binding Source="{StaticResource MainMenuViewModel}"/>
</phone:PhoneApplicationPage.DataContext>
<!-- catch back key press -->
<i:Interaction.Triggers>
<i:EventTrigger EventName="BackKeyPress">
<commands:EventToCommand
Command="{Binding BackKeyPressCommand}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
MainMenuViewModel.cs
// back key press command
public RelayCommand<object> BackKeyPressCommand { get; set; }
public MainMenuViewModel()
{
BackKeyPressCommand = new RelayCommand<object>(
BackKeyPress,
(o) => true
);
...
}
private void BackKeyPress(Object o)
{
// handle back key press
}
This worked perfectly before, but now the BackKeyPress(Object o) Method never gets called anymore.
This happens for all EventToComamnd calls.
If I remove the xmlns tags, Resharper suggests to add this:
xmlns:command="http://www.galasoft.ch/mvvmlight"
Result of that:
The name "EventToCommand" does not exist in the namespace "http://www.galasoft.ch/mvvmlight"
Anyone encountered a similar problem or has an idea what could have caused this?
These namespaces are correct.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:commands="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
But your PhoneApplicationPage has wrong DataContext.
DataContext="{Binding Path=MainMenuViewModel, Source={StaticResource Locator}}"
MainMenuViewModel is property in the ViewModelLocator:
public MainMenuViewModel MainMenuViewModel
{
get
{
return ServiceLocator.Current.GetInstance<MainMenuViewModel>();
}
}
Btw the argument of BackKeyPress is CancelEventArgs. You should use:
public RelayCommand<CancelEventArgs> BackKeyPressCommand { get; private set; }
this.BackKeyPressCommand = new RelayCommand<CancelEventArgs>(this.BackKeyPress)
private void BackKeyPress(CancelEventArgs e)
{
}
Windows Phone 8.1
Windows 8.1 Behavior SDK: How to use InvokeAction with InputConverter to pass arguments to a Command
Microsoft has developed it's own EventToCommand functionality. It's located in Behaviors SDK. Someone on stackoverflow told to get this SDK via Nuget. If you can't find the package in NuGet - get it in Add reference dialog.
(My add reference dialog may differs from original because of Productivity Power Tools extension)
Here is example of simple usage:
<ListBox ItemsSource="{Binding Persons, Mode=OneWay}"
SelectedItem="{Binding SelectedPerson, Mode=TwoWay}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding DisplayPersonCommand}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ListBox>
My problem is similar to the one described in this question:
WPF MVVM Button Control Binding in DataTemplate
Here is my XAML:
<Window x:Class="MissileSharp.Launcher.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MissileSharp Launcher" Height="350" Width="525">
<Grid>
<!-- when I put the button here (outside the list), the binding works -->
<!--<Button Content="test" Command="{Binding Path=FireCommand}" />-->
<ListBox ItemsSource="{Binding CommandSets}">
<ListBox.ItemTemplate>
<DataTemplate>
<!-- I need the button here (inside the list), and here the binding does NOT work -->
<Button Content="{Binding}" Command="{Binding Path=FireCommand}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
It's just a ListBox, bound to an ObservableCollection<string> named CommandSets (which is in the ViewModel).
This binding works (it displays a button for each item in the collection).
Now I want to bind the button to a command (FireCommand), which is also in the ViewModel.
Here's the relevant part of the ViewModel:
public class MainWindowViewModel : INotifyPropertyChanged
{
public ICommand FireCommand { get; set; }
public ObservableCollection<string> CommandSets { get; set; }
public MainWindowViewModel()
{
this.FireCommand = new RelayCommand(new Action<object>(this.FireMissile));
}
private void FireMissile(Object obj)
{
System.Windows.MessageBox.Show("fire");
}
}
The binding of this button does NOT work.
From what I've understood from the question I linked above, the binding doesn't work because:
(correct me if I'm wrong)
The button is inside the ListBox, so it only "knows" the binding of the ListBox (the ObservableCollection, in this case), but not the binding of the main window
I'm trying to bind to a command in the main ViewModel of the main window (which the button doesn't "know")
The command itself is definitely correct, because when I put the button outside the ListBox (see the XAML above for an example), the binding works and the command is executed.
Apparently, I "just" need to tell the button to bind to the main ViewModel of the form.
But I'm not able to figure out the right XAML syntax.
I tried several approaches that I found after some googling, but none of them worked for me:
<Button Content="{Binding}" Command="{Binding RelativeSource={RelativeSource Window}, Path=DataContext.FireCommand}" />
<Button Content="{Binding}" Command="{Binding Path=FireCommand, Source={StaticResource MainWindow}}" />
<Button Content="{Binding}" Command="{Binding Path=FireCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
Could someone please:
give me the proper XAML to bind the button inside the ListBox to a command in the form's MainViewModel?
point me to a link where this advanced binding stuff is explained in a way that a WPF/MVVM beginner can understand?
I'm feeling like I'm just copying and pasting arcane XAML incantations, and so far I don't have any clue (and can't find any good documentation) how I would figure out by myself in which cases I'd need RelativeSource or StaticResource or whatever instead of a "normal" binding.
It's:
{Binding DataContext.FireCommand,
RelativeSource={RelativeSource AncestorType=ListBox}}
No need to walk up to the root unless you actually change the DataContext along the way, but as the ListBox seems to bind to a property on the main VM this should be enough.
The only thing i recommend reading is the Data Binding Overview, and the Binding class documentation (including its properties).
Also here is a short explanation on how bindings are constructed: A binding consists of a source and a Path relative to that source, by default the source is the current DataContext. Sources that can be set explicitly are: Source, ElementName & RelativeSource. Setting any of those will override the DataContext as source.
So if you use a source like RelativeSource and want to access something in the DataContext on that level the DataContext needs to appear in the Path.
This may be considered unrelated by most, but this search is only 1 of 3 results that you'll find searching for data binding commands to controls inside a data template--as it relates to Xamarin Forms. So, maybe it'll help someone now-a-days.
Like me you may wonder how to bind commands inside a BindableLayout. Credit jesulink2514 for answering this at Xamarin Forums, where it's probably overlooked by many because of all the comments. Here's his solution, but I'm including the link below:
<ContenPage x:Name="MainPage">
<ListView Grid.Row="1"
ItemsSource="{Binding Customers}"
VerticalOptions="Fill"
x:Name="ListviewCustomer">
<ListView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Property}"/>
<Button Command="{Binding BindingContext.ItemCommand, Source={x:Reference MainPage}}"
CommandParameter="{Binding .}">Click me</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
https://forums.xamarin.com/discussion/comment/217355/#Comment_217355