How to use LostFocus as a Command in WPF - 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>

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;
}

Handle MainWindow events in ViewModel - 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>

PropertyChanged event on viewmodel property

i'm trying to Raise a PropertyChanged event on a Property in my ViewModel
using interaction triggers .
CS :
public string MyContentProperty
{
get { return "I Was Raised From an outside Source !";}
}
XAML :
<Button Content="{Binding MyContentProperty}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Button.Click">
< .... what needs to be done ?>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
of course if there was any doubt for this question you have references to
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
at your disposal , thanks in advance .
You can use a normal command or Expression Blend's CallMethodAction, InvokeCommandAction or ChangePropertyAction.
Here are four ways to do what you want:
<Button Content="Button" Height="23" Width="100" Command="{Binding RaiseItCmd}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding RaiseItCmd}"/>
<ei:CallMethodAction MethodName="RaiseIt" TargetObject="{Binding}"/>
<ei:ChangePropertyAction Value=""
PropertyName="MyContentProperty" TargetObject="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Here I'm using MVVM Light's ViewModelBase:
using System.Windows.Input;
using GalaSoft.MvvmLight;
using Microsoft.Expression.Interactivity.Core;
public class ViewModel : ViewModelBase
{
public ViewModel()
{
RaiseItCmd = new ActionCommand(this.RaiseIt);
}
public string MyContentProperty
{
get
{
return "property";
}
set
{
this.RaiseIt();
}
}
public void RaiseIt()
{
RaisePropertyChanged("MyContentProperty");
}
public ICommand RaiseItCmd { get; private set; }
}

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>

How to fire event from button inside datagrid in silverlight and MVVM

I have button at first column in datagrid. I am using MVVM and try to bind Command to Command in ViewModel but when I click button in each row, it don't work (It don't call Command in ViewModel) but if I move that button out of datagrid it's working properly.
How can I fire event from button inside datagrid in MVVM?
Update 1:
XAML's code is:
<datagrid:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<Button x:Name="button" Content="View" Margin="5" DataContext="{StaticResource XDataContext}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ViewOrganizationCommand}"
CommandParameter="{Binding ElementName=dtgOrganizations, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</DataTemplate>
</datagrid:DataGridTemplateColumn.CellTemplate>
ViewModel's code is:
public ViewModelCommand ViewOrganizationCommand { get; set; }
Instead of using EventTrigger, why not simply bind to Button.Command directly, like so?
<Button
...other properties...
Command="{Binding ViewOrganizationsCommand}"
CommandParameter="{Binding}"/>
That will bind the command, and set the CommandParameter to the DataContext of the Button, which presumably is a good thing to bind the parameter to. If it's not, just bind CommandParameter to something else that helps you uniquely identify the specific row being clicked on.
This article brings the solution with DataContextProxy. Applying this solution makes possible to write a button code like Austin Lamb's answer.
The command binding using the Event Trigger looks fine (This is how i always do it),
But I suspect that your command is never assigned to (You are using Automatic Properties)
I usually do it like this:
private ViewModelCommand viewOrganizationCommand;
public ViewModelCommand ViewOrganizationCommand
{
get
{
if (viewOrganizationCommand == null)
viewOrganizationCommand = new ViewModelCommand(Action, CanDoIt);
return viewOrganizationCommand;
}
}
try setting you Button's DataContext to the StackPanel and set the Command and CommandParameter of the Button.
<datagrid:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center" DataContext="{StaticResource XDataContext}">
<Button x:Name="button" Content="View" Margin="5" Command="{Binding ViewOrganizationCommand}" CommandParameter="{Binding ElementName=dtgOrganizations, Path=SelectedItem}" >
</Button>
</StackPanel>
</DataTemplate>
</datagrid:DataGridTemplateColumn.CellTemplate>
I solved this problem by use EventToCommand behavior in MVVMLight Toolkit
Each row of the DataGrid has it's DataContext set to that object. If the ItemSource for the grid is an ObservableCollection, each row's DataContext is the Organization object.
There are two ways to handle this.
Create a wrapping or extension ViewModel that exposes the command. Then the command should fire.Here is some psuedo code.
public class OrganizationExtensionViewModel
{
<summary>
/// Private currentOrginization property.
/// </summary>
private Organization currentOrginization;
public Organization CurrentOrganization
{
get
{
return this.currentOrginization;
}
set
{
if (this.currentOrginization != value)
{
this.currentOrginization = value;
this.RaisePropertyChanged("CurrentOrganization");
}
}
}
public ViewModelCommand ViewOrganizationCommand { get; set; }
public OrganizationExtensionViewModel(Organization o)
{
this.CurrentOrganization = o;
this.ViewOrganizationCommand = new ViewModelCommand(this.ViewOrgnaizationClicked);
}
}
Define the ViewModel in the xaml as a StaticResource and refer to it as the binding path.
...
In the grid
<Button x:Name="button" Content="View" Margin="5" Command="{Binding ViewOrganizationCommand, Source={StaticResource viewModel}}" />

Resources