Handle MainWindow events in ViewModel - WPF - wpf

I want to handle Windows event like Closing, SourceInitialized in my viewModel. I don't want to handle them in my code behind. How can I do that?
Thanks in advance.

Simply use EventToCommand.
ViewModel:
public ICommand WindowClosing
{
get
{
return new RelayCommand<CancelEventArgs>(
(args) =>{
});
}
}
and in XAML:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<command:EventToCommand Command="{Binding WindowClosing}" />
</i:EventTrigger>
</i:Interaction.Triggers>

Related

Disable button when move mouse out of control

Say I have a Telerik RadGridView, outside there is a button. When the mouse is clicking row in the RadGridView, the button is enabled. If the mouse moves outside the RadGridView, then the button is disabled.
My code is
rgv_LostFocus(object sender, eventArgs e)
{
// do something
MyViewModel.IsButtonEnabled = false;
}
However I don't want to use code behind. Maybe using behavior?
You could use an interaction trigger from System.Windows.Interactivity and a ChangedPropertyAction from Microsoft.Expression.Interactions.dll:
<telerik:RadGridView xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<ei:ChangePropertyAction TargetObject="{Binding}" TargetName="IsButtonEnabled" Value="false" />
</i:EventTrigger>
</i:Interaction.Triggers>
...
</telerik:RadGridView>
Please refer to this blog post for information about how to handle events in a MVVM application.
Per #mm8 hint.
<telerik:RadGridView xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding LostFocusCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadGridView>
Then in ViewModel,
public DelegateCommand LostFocusCommand = new DelegateCommand(RadGridViewLostFocus);
In the method 'RadGridViewLostFocus' set the bool property as false;
private void RadGridViewLostFocus()
{
IsButtonEnabled = false;
}

WPF how to binding an attached event to viewmodel?

<TreeView x:Name="TestTree"
ItemsSource="{Binding Children}"
ItemTemplateSelector="{StaticResource TemplateSelector}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="TreeViewItem.Seleted">
<i:InvokeCommandAction
Command="{Binding SelectedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TreeView>
As above codes mentioned, I wanna get the selected treeviewitem data from the view, while the binding event TreeViewItem.Seleted which is an attached event(member event is okay) cannot be received in the viewmodel. How to binding an attached event to viewmodel?
then, you won't get TreeViewItem event in the TreeView ? you need a custom item template. I do it like this on a datagrid with MVVMLight (but no item)
</DataGrid.Columns>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick" >
<command:EventToCommand Command="{Binding Path=OpenEquipementCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="SelectionChanged">
<command:EventToCommand Command="{Binding Path=SelectionChangedCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
so i think you must do
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged" >
<command:EventToCommand Command="{Binding Path=SelectionChangedCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
Why don't just use plain old eventhandler?
<TreeView x:Name="TreeView1" SelectedItemChanged="TreeView_SelectedItemChanged" />
public partial class MainWindow : Window
{
MainWindowViewModel ViewModel => (MainWindowViewModel) DataContext;
private void TreeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var element = (FrameworkElement)sender;
var item = element.DataContext;
ViewModel.SelectionChangedCommand.Invoke(item);
//alternativelly:
ViewModel.SelectedItem = TreeView1.SelectedItem;
}
}
Just because WPF support binding, it does not mean you have to use it everywhere even if it's very complicated. The code I've written is not violation of MVVM.
If you have a good reason to avoid code behind, you may implement this eventhandler in a custom behavior implemented as attached property, so it would look like this:
<TreeView local:TreeViewBehavior.SelectionChangedCommand="{Binding SelectionChangedCommand}" />

How to use LostFocus as a Command in WPF

I am trying to use LostFocus event as Command in DataGridTextColumn and can't find an example on how to use it in WPF.
Can anyone help me use it as I am new to WPF.
Thank you.
My xaml looks like:
`
The c# code:
public partial class Myogg : UserControl {
MyLogg _viewModel;
public MyLogg()
{
InitializeComponent();
_viewModel = new MyLoggUCViewModel();
DataContext = _viewModel;
}
}`
you can use interaction triggers to do this ..
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding Path=LostFocusCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>

WPF XAML ListView MouseOverItem

Do you know is it possible to get element on MouseOver from ListView in WPF using XAML?
I would like to bind mouse over element to command parameter.
What should I type in Path ?
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding SetOnMousePlayerCommand}"
CommandParameter="{Binding ElementName=leftPlayersListViewGame, Path=XXX}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Probably I have to do it in another way ? Could you tell my how ?
if you are looking to access the Event Args here how you should proceed:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<command:EventToCommand Command="{Binding Mode=OneWay,Path=MouseEnterCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
private RelayCommand<MouseEventArgs> _mouseEnterCommand;
public RelayCommand<MouseEventArgs> MouseEnterCommand
{
get
{
return _mouseEnterCommand
?? (_mouseEnterCommand= new RelayCommand<MouseEventArgs>(
(s) =>
{
//your logic
}));
}
}
but if you are looking for the sender of the Event, so here is your answer Pal :
Passing event args and sender to the RelayCommand

EventTrigger not firing for Loaded event of UserControl

I have a UserControl with the following event trigger:
<UserControl x:Class="TestApp.Views.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding OnLoadedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
It is being set via the constructor of the UserControl (please ignore the ServiceLocator ..this is just a quick prototype):
public MyUserControl()
{
InitializeComponent();
DataContext = ServiceLocator.Current.GetInstance<DirectorySearchViewModel>();
}
In my view-model I have the following:
public ICommand OnLoadedCommand { get; private set; }
public MyUserControl()
{
OnLoadedCommand = new DelegateCommand(OnLoaded);
}
public void OnLoaded()
{
}
OnLoaded never gets called. If I change the EventName to say ..MouseDown, then it works but it just won't work for Loaded
Pretty sure it's a stupid mistake (swear I've done this a million times before in the past) but can't seem to figure it out right now
public MyUserControl()
{
DataContext = ServiceLocator.Current.GetInstance<DirectorySearchViewModel>();
InitializeComponent();
}
The Aristocrats.
For anyone else that stumbles across this you can do it without code behind like this:
<UserControl x:Class="TestApp.Views.MyUserControl"
... etc...
x:Name="theControl"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction
Command="{Binding ElementName=theControl, Path=OnLoadedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>

Resources