Triggering events from View to ViewModel in WPF - c#

working in WPF with C# I am generating an event from a view MyView and what I need to do is to handle it in the associated view model class MyViewModel.
I am using caliburn.micro to solve and this is the code in synthesis:
<UserControl x:Class="MyView"
xmlns:cal="http://www.caliburnproject.org"
DataContext="MyViewModelInstance"
cal:Message.Attach="[Event CancelEvent]=[Action CancelButton_Click_MyViewModelHandler($source,$eventArgs)]">
<Grid>
<Button Click="CancelButton_Click"> </Button>
</Grid>
</UserControl>
In the code behind I handle the click event generating a CancelEvent:
public partial class MyView : UserControl
{
public event EventHandler CancelEvent;
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
if(CancelEvent!=null)
{
CancelEvent(sender,e);
}
}
}
In the class MyViewModel I defined the function
public void MyViewMOdelHandler(Object sender, EventArgs arg)
What I need to do is to handle the CancelEvent in MyViewModelInstance, using the code above results as no one is subscribed to the CancelEvent (CancelEvent == null) so that the CancelEvent handler in MyViewModelInstance is not invoked.
Does anybody know a solution to the problem? (caliburn is not mandatory)
Thanks in advance.
-Z-

I think the solution is easy. In your view:
<UserControl x:Class="MyView"
xmlns:cal="http://www.caliburnproject.org"
DataContext="YourViewModel"
<Grid>
<Button Click="CancelButton_Click" cal:Message.Attach="[Event Click]=[Action MyViewModelHandler($source,$eventArgs)]">> </Button>
</Grid>
CancelButton_Click in code behind can be removed.
In your viewmodel:
public class YourViewModel : PropertyChangedBase
{
public void MyViewModelHandler(Object sender, EventArgs arg)
{
}
}

Is there any reason you're not directly attaching the click event of the button? as that would be the simplest solution.
Looking at your example it would seem the Message.Attach is specifiing a method that doesn't exist.
If the method on the view model is
public void MyViewModelHandler(Object sender, EventArgs arg)
then the attach syntax would be
cal:Message.Attach="[Event CancelEvent]=[Action MyViewModelHandler($source,$eventArgs)]"

Related

How to reuse WPF custome window

I have created custome window (titlebar, min/max/ext buttons, own border for window manipulation and lots of styles and triggers).
There are 5 methods defined (which i would like to override):
From window markup:
SourceInitialized="Window_SourceInitialized"
Closing="Window_Closing"
From Titlebar buttons:
Exit_Click()
Max_Click()
Min_Click()
And at last I have DockPanel
<DockPanel Name="ClientArea"/>
In which I want to put my content
I have tried to add content from code:
BaseWindow editInterfaceWindow = new BaseWindow() { Owner = this };
editInterfaceWindow.DataContext = new EditInterface();
editInterfaceWindow.ShowDialog();
But this way some bindings stoped working and inside editInterfaceWindow I cant create another window this way because of Owner = this. There are also some problems with InitializeComponent() in constructor.
And ListView inside EditInterface UserControl <ListView Name="LBAvaliable" ItemsSource="{Binding AvaliableFaces, UpdateSourceTrigger=PropertyChanged}"> is not visible in code as LBAvaliable.
I have used that window few times, filling ClientArea with content by hand.
How should I create other windows, so that I can just inherit it or just define binding? So my XAML for every single window does not take ~1000 lines of code.
In the past I've used MVVMCross Framework and we never had to worry about this ourselves. Though this is not the best, here's an idea on what you can do.
Create a view model that can be overridden for your user control.
Set data templates.
Programmatically change the view model for your user control's main content and let data templates do the work for the UI.
View Model: Pre-defined 3 button actions ready for you to set/override.
public class MainUCViewModel : ViewModelBase
{
private Action<object> btnACommand;
private Action<object> btnBCommand;
private Action<object> btnCCommand;
private object ccVM;
public ViewModelBase CCVM
{
get { return this.ccVM; }
set
{
this.ccVM = value;
OnPropertyChanged(); // Notify View
}
}
public MainUCViewModel()
{
}
public RelayCommand BtnACommand
{
get { return new RelayCommand(btnACommand); }
}
public RelayCommand BtnBCommand
{
get { return new RelayCommand(btnBCommand); }
}
public RelayCommand BtnCCommand
{
get { return new RelayCommand(btnCCommand); }
}
public void SetBtnACommand(Action<object> action)
{
this.btnACommand = action;
}
public void SetBtnBCommand(Action<object> action)
{
this.btnBCommand = action;
}
public void SetBtnCCommand(Action<object> action)
{
this.btnCCommand = action;
}
}
View:
<UserControl x:Class="WpfApplication1.Views.UserControls.MainUC"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="750">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="45" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<StackPanel Orientation="Horizontal">
<Button Command="{Binding BtnACommand}" Width="100">
<TextBlock>A</TextBlock>
</Button>
<Rectangle Width="15" />
<Button Command="{Binding BtnBCommand}" Width="100">
<TextBlock>B</TextBlock>
</Button>
<Rectangle Width="15" />
<Button Command="{Binding BtnCCommand}" Width="100">
<TextBlock>C</TextBlock>
</Button>
</StackPanel>
</Grid>
<Grid Grid.Row="1">
<ContentControl x:Name="CCMain" Content="{Binding CCVM}"/>
</Grid>
</Grid>
</UserControl>
Look at Thinking with MVVM: Data Templates + ContentControl. Simply define the data template for your view model.
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModel:GeneralSettingsViewModel}">
<View:GeneralSettingsView/>
</DataTemplate
<DataTemplate DataType="{x:Type ViewModel:AdvancedSettingsViewModel}">
<View:AdvancedSettingsView/>
</DataTemplate>
</Window.Resources>
What I’m saying here is that GeneralSettingsViewModel should be
rendered using a GeneralSettingsView. That’s exactly what we need !
Because the Views are created using a DataTemplate, we do not need to
setup the DataContext, it will be automatically registered to the
templated object, the ViewModel.
There are two main approaches to your problem:
Inherited windows
Configurable windows
For approach 1, design your window and make the methods overrideable:
In base window xaml, assign the handlers and everything you want:
<Window x:Class="WpfTests.MainWindow"
...
SourceInitialized="Window_SourceInitialized">
In base window, define the handlers as protected virtual (or abstract, if you like to enforce their implementation)
public partial class MainWindow : Window
{
// ...
protected virtual void Window_SourceInitialized(object sender, EventArgs e)
{
}
// ...
}
Create derived windows
public class ExWindow : MainWindow
{
protected override void Window_SourceInitialized(object sender, EventArgs e)
{
// specialized code here
}
}
Change App.xaml to use Startup instead of StartupUri
<Application x:Class="WpfTests.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
And manually create your first window, chosing one of the inherited window classes
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
var window = new ExWindow();
window.Show();
}
}
The second approach - configurable windows - follows the same principle as a good user control design: The window/control properties are controlled by the creator instead of being controlled by the window/control itself.
So, instead of defining some event handler within the window code, just leave this exercise to the user, who hopefully knows what the window should do:
public partial class MainWindow : Window
{
// I don't care for SourceInitialized (also remove it from XAML)
}
In App.xaml or wherever a window is created:
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
var window = new MainWindow();
window.SourceInitialized += window_SourceInitialized;
window.Show();
}
void window_SourceInitialized(object sender, EventArgs e)
{
var window = sender as MainWindow;
// I know how to handle this event for this window instance
}
}

How can I modify from C# the value of an element which is define in a XAML DataTemplate?

I created a "WPF Application Project" in Visual Studio 2013.
I opened the "MainWindow.xaml" file and I wrote the following XAML code:
<Window x:Class="TestProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="AlphaDataTemplate">
<Label
Name="LabelInDataTemplate"
Content="Good morning!" />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentPresenter
Name="MyContentPresenter"
ContentTemplate="{StaticResource AlphaDataTemplate}" />
<Button
Name="MyButton"
Click="MyButton_OnClick"
Content="Change the content of the Label in the DataTemplate"
Width="320"
Height="30" />
</Grid>
In this XAML file I created a "DataTemplate" which corresponds to the key "AlphaDataTemplate". The DataTmplate contains just one label with the name "LabelInDataTemplate" where I have hardcoded the "Good morning!" string in the "Content" attribute of the label.
Then I use created a "ContentPresenter" with the name "MyContentPresenter" and I pass as content the "DataTemplate" I previously created (AlphaDataTemplate).
As next step, I created a "Button" with the name "MyButton" and I have set a "Click" event called "MyButton_OnClick"
So far so good...!
The question comes now and actually in C# in the code behind file "MainWindow.xaml.cs". See the code below:
using System.Windows;
namespace TestProject
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MyButton_OnClick(object sender, RoutedEventArgs e)
{
LabelInDataTemplate.Content = "Bye!"; // <-- Tha does not work.
}
}
}
In this C# code behind file you can see the definition of the "Click" (MyButton_OnClick) event of the Button (MyButton) which appears in XAML.
What I am trying to do in this "Click" event, is to change the value of the "Content" of the "Label" (LabelInDataTemplate) which is in the DataTemplate (AlphaDataTemplate).
Unfortunately, that does not work.
I cannot actually access the "Name" (LabelInDataTemplate) of the "Label", because it is contained in the "DataTemplate" (AlphaDataTemplate)
If anyone has any idea, how could I modify from C# the value of an element which is define in a XAML DataTemplate, please give me feedback. I would really appreciate it.
Thank you in advance.
I strongly oppose your method of changing the content of label via DataTemplate, However your requirement is possible, but very subtle.
Code
private void MyButton_OnClick(object sender, RoutedEventArgs e)
{
var alphaDataTemplate = this.Resources["AlphaDataTemplate"] as DataTemplate;
var label = alphaDataTemplate.FindName("LabelInDataTemplate", MyContentPresenter) as Label;
label.Content = "It Works";
}
Please learn MVVM and use proper DataBinding for this purpose. For sake of solving this problem:
Implement INotifyPropertyChanged interface on your Window class and Define string property like below
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public string _contentMsg;
public string ContentMsg
{
get { return _contentMsg; }
set
{
_contentMsg = value;
RaisePropertyChanged("ContentMsg");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propName)
{
if(PropertyChanged !=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
In your xaml bind the ContentPresenter and update your DataTemplate label like
<ContentPresenter
Name="MyContentPresenter"
Content = "{Binding ContentMsg}"
ContentTemplate="{StaticResource AlphaDataTemplate}" />
<DataTemplate x:Key="AlphaDataTemplate">
<Label
Name="LabelInDataTemplate"
Content="{Binding}" />
Now in click handler (I would use Commands here), set ContentMsg to whatever you want
private void MyButton_OnClick(object sender, RoutedEventArgs e)
{
ContentMsg = "Bye!";
}

Binding the Loaded event?

I am trying to display a login window once my MainWindow loads while sticking to the MVVM pattern. So I am trying to Bind my main windows Loaded event to an event in my viewmodel.
Here is what I have tried:
MainWindowView.xaml
<Window x:Class="ScrumManagementClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="ViewModel.MainWindowViewModel"
Loaded="{Binding ShowLogInWindow}">
<Grid>
</Grid>
</Window>
MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ScrumManagementClient.ViewModel
{
class MainWindowViewModel : ViewModelBase
{
public void ShowLogInWindow(object sender, EventArgs e)
{
int i = 0;
}
}
}
The error message I am getting is "Loaded="{Binding ShowLogInWindow}" is not valid. '{Binding ShowLogInWindow}' is not a valid event handler method name. Only instance methods on the generated or code-behind class are valid."
You're going to have to use the System.Windows.Interactivity dll.
Then add the namespace in your XAML:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Then you can do stuff like:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding MyICommandThatShouldHandleLoaded}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Please note that you will have to use an ICommand (or DelegateCommand is you use Prism, or RelayCommand if you use MVVMLight), and the DataContext of your Window must hold that ICommand.
Use Attached Behavior. That is allowed in MVVM ....
(code below may / may not compile just like that)
XAML ...
<Window x:Class="..."
...
xmlns:local="... namespace of the attached behavior class ..."
local:MyAttachedBehaviors.LoadedCommand="{Binding ShowLogInWindowCommand}">
<Grid>
</Grid>
</Window>
Code Behind...
class MainWindowViewModel : ViewModelBase
{
private ICommand _showLogInWindowCommand;
public ICommand ShowLogInWindowCommand
{
get
{
if (_showLogInWindowCommand == null)
{
_showLogInWindowCommand = new DelegateCommand(OnLoaded)
}
return _showLogInWindowCommand;
}
}
private void OnLoaded()
{
//// Put all your code here....
}
}
And the attached behavior...
public static class MyAttachedBehaviors
{
public static DependencyProperty LoadedCommandProperty
= DependencyProperty.RegisterAttached(
"LoadedCommand",
typeof(ICommand),
typeof(MyAttachedBehaviors),
new PropertyMetadata(null, OnLoadedCommandChanged));
private static void OnLoadedCommandChanged
(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
var frameworkElement = depObj as FrameworkElement;
if (frameworkElement != null && e.NewValue is ICommand)
{
frameworkElement.Loaded
+= (o, args) =>
{
(e.NewValue as ICommand).Execute(null);
};
}
}
public static ICommand GetLoadedCommand(DependencyObject depObj)
{
return (ICommand)depObj.GetValue(LoadedCommandProperty);
}
public static void SetLoadedCommand(
DependencyObject depObj,
ICommand value)
{
depObj.SetValue(LoadedCommandProperty, value);
}
}
DelegateCommand source code can be found on the internet... Its the most suited ICommand API available for MVVM.
edit:19.07.2016 two minor syntax errors fixed
Update:
I made a post about a new more flexible version of the method binding that uses a slightly different syntax here:
http://www.singulink.com/CodeIndex/post/updated-ultimate-wpf-event-method-binding
The full code listing is available here:
https://gist.github.com/mikernet/7eb18408ffbcc149f1d9b89d9483fc19
Any future updates will be posted to the blog so I suggest checking there for the latest version.
Original Answer:
.NET 4.5+ supports markup extensions on events now. I used this to create a method binding that can be used like this:
<!-- Basic usage -->
<Button Click="{data:MethodBinding OpenFromFile}" Content="Open" />
<!-- Pass in a binding as a method argument -->
<Button Click="{data:MethodBinding Save, {Binding CurrentItem}}" Content="Save" />
<!-- Another example of a binding, but this time to a property on another element -->
<ComboBox x:Name="ExistingItems" ItemsSource="{Binding ExistingItems}" />
<Button Click="{data:MethodBinding Edit, {Binding SelectedItem, ElementName=ExistingItems}}" />
<!-- Pass in a hard-coded method argument, XAML string automatically converted to the proper type -->
<ToggleButton Checked="{data:MethodBinding SetWebServiceState, True}"
Content="Web Service"
Unchecked="{data:MethodBinding SetWebServiceState, False}" />
<!-- Pass in sender, and match method signature automatically -->
<Canvas PreviewMouseDown="{data:MethodBinding SetCurrentElement, {data:EventSender}, ThrowOnMethodMissing=False}">
<controls:DesignerElementTypeA />
<controls:DesignerElementTypeB />
<controls:DesignerElementTypeC />
</Canvas>
<!-- Pass in EventArgs -->
<Canvas MouseDown="{data:MethodBinding StartDrawing, {data:EventArgs}}"
MouseMove="{data:MethodBinding AddDrawingPoint, {data:EventArgs}}"
MouseUp="{data:MethodBinding EndDrawing, {data:EventArgs}}" />
<!-- Support binding to methods further in a property path -->
<Button Content="SaveDocument" Click="{data:MethodBinding CurrentDocument.DocumentService.Save, {Binding CurrentDocument}}" />
View model method signatures:
public void OpenFromFile();
public void Save(DocumentModel model);
public void Edit(DocumentModel model);
public void SetWebServiceState(bool state);
public void SetCurrentElement(DesignerElementTypeA element);
public void SetCurrentElement(DesignerElementTypeB element);
public void SetCurrentElement(DesignerElementTypeC element);
public void StartDrawing(MouseEventArgs e);
public void AddDrawingPoint(MouseEventArgs e);
public void EndDrawing(MouseEventArgs e);
public class Document
{
// Fetches the document service for handling this document
public DocumentService DocumentService { get; }
}
public class DocumentService
{
public void Save(Document document);
}
More details can be found here: http://www.singulink.com/CodeIndex/post/building-the-ultimate-wpf-event-method-binding-extension
The full class code is available here:
https://gist.github.com/mikernet/4336eaa8ad71cb0f2e35d65ac8e8e161
A more generic way using behaviors is proposed at AttachedCommandBehavior V2 aka ACB and it even supports multiple event-to-command bindings,
Here is a very basic example of use:
<Window x:Class="Example.YourWindow"
xmlns:local="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
local:CommandBehavior.Event="Loaded"
local:CommandBehavior.Command="{Binding DoSomethingWhenWindowIsLoaded}"
local:CommandBehavior.CommandParameter="Some information"
/>
For VS 2013 Update 5 I wasn't able to get around "Unable to cast object of type 'System.Reflection.RuntimeEventInfo' to type 'System.Reflection.MethodInfo". Instead in a "Core" directory I made a simple interface
interface ILoad
{
void load();
}
My viewModel already had the load() function implementing ILoad. In my .xaml.cs I call the ViewModel load() through ILoad.
private void ml_Loaded(object sender, RoutedEventArgs e)
{
(this.ml.DataContext as Core.ILoad).load();
}
The xaml.cs knows nothing about the ViewModel except the POCO ILoad, the ViewModel knows nothing about the xaml.cs. The ml_loaded event is mapped to ViewModel load().

Silverlight custom EventTrigger

I am trying to create a custom event to trigger an animation in Silverlight. Although the event is getting triggered, the animation is not working. The following is the relevant code:
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
MyEvent += new ChangedEventHandler(UserControl_MyEventHandler);
/* Other stuff */
}
private void UserControl_MyEventHandler(object sender, RoutedEventArgs e)
{
MessageBox.Show("MyEventHandler has been called");
}
public delegate void ChangedEventHandler(object sender, RoutedEventArgs e);
private event ChangedEventHandler MyEvent;
private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (MyEvent != null)
MyEvent(this, e);
}
}
}
The XAML code is as follows:
<UserControl
...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" mc:Ignorable="d"
x:Class="SilverlightApplication1.MainPage" MouseLeftButtonDown="UserControl_MouseLeftButtonDown">
<Grid x:Name="LayoutRoot" Background="White">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MyEvent">
<ei:GoToStateAction StateName="Highlighted"/>
</i:EventTrigger>
</i:Interaction.Triggers>
...
</Grid>
</UserControl>
Current, the message box containing "MouseLeftButtonDown" is getting displayed but the animation is not getting called. The animation did get called when the EventTrigger EventName was MouseLeftButtonDown instead of MyEvent. Please help me out. Thanks.
You can set SourceName in EventTrigger if you want to trigger on event of some control.
I guess, in your case in code behind:
VisualStateManager.GoToState(this [or some other object with Highlighted state], "Highlighted", false);

button1.PerformClick() in wpf

Why this code in WPF does not work ?
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("yes");
}
private void Form1_Load(object sender, EventArgs e)
{
button1.PerformClick();
}
I need to command.
To use the windows form application's style, you need to write the following extension method:
namespace System.Windows.Controls
{
public static class MyExt
{
public static void PerformClick(this Button btn)
{
btn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
}
}
now you can use it for any button, assuming a button called "btnOK":
btnOK.PerformClick();
Wait.. there is simple way. if your button name is button1 and button1 click event already subscribed,you will just call that event like
button1_Click(this,null);
Instead of PerformClick() use RaiseEvent()
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("yes");
}
private void Form1_Load(object sender, EventArgs e)
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(Button.ClickEvent);
button1.RaiseEvent(newEventArgs);
}
I think the shortest and most efficient solution to your problem would be simply done in one line.
button1.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
That should work for WPF C#
Good practice in WPF is using commands. It improves testability and separates UI and business logic.
First you may try RoutedUICommand.
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self ="clr-namespace:Test"
Title="MainWindow"
Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="{x:Static self:MainWindow.RoutedClickCommand}"
CanExecute="CommandBinding_CanExecute"
Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<Grid>
<Button Content="Test" Name="Btn1" Command="{x:Static self:MainWindow.RoutedClickCommand}"/>
</Grid>
In code behind file we have to define RoutedClickCommand and Execute|CanExecute handlers:
public static ICommand RoutedClickCommand = new RoutedUICommand("ClickCommand", "ClickCommand", typeof(MainWindow));
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("ololo");
}
So, when you need button logic ("button1.PerformClick();" in your sample), just put next line:
MainWindow.RoutedClickCommand.Execute(null);
As for me, I preffer another way which supposes carry command into presentation model. Composite Application Library (Prism) helps me with its DelegateCommand class. Then command definition in presentation model looks like:
private DelegateCommand<object> _clickCommand;
public ICommand ClickCommand
{
get
{
if (this._clickCommand == null)
{
this._clickCommand = new DelegateCommand<object>(p =>
{
//command logic
},
p =>
{
// can execute command logic
});
}
return this._clickCommand;
}
}
And view XAML and code behind:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self ="clr-namespace:Test"
Title="MainWindow"
Height="350" Width="525">
<Grid>
<Button Content="Test" Name="Btn1" Command="{Binding ClickCommand}"/>
</Grid>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Model = new SampleModel();
}
protected SampleModel Model
{
get
{
if (this.Model.ClickCommand.CanExecute())
{
this.Model.ClickCommand.Execute();
}
return (SampleModel)this.DataContext;
}
set
{
this.DataContext = value;
}
}
}
Next code calls command in view bypassing clicking on button:
if (this.Model.ClickCommand.CanExecute())
{
this.Model.ClickCommand.Execute();
}
An excerpt from Adam Nathans WPF Unleashed, recommended by this blog.
Imho one of the best, if not the best WPF references around.
var bap = new System.Windows.Automation.Peers.ButtonAutomationPeer(someButton);
var iip = bap.GetPattern(System.Windows.Automation.Peers.PatternInterface.Invoke)
as System.Windows.Automation.Provider.IInvokeProvider;
iip.Invoke();
Because PerformClick is a method on WindowsForms Button control:
http://msdn.microsoft.com/en-us/library/system.windows.forms.button.performclick.aspx
Not on the WPF Button control:
http://msdn.microsoft.com/en-us/library/system.windows.controls.button_methods.aspx
To automate a button click, you might like to take a look at the UI automation framework:
http://msdn.microsoft.com/en-us/library/ms747327.aspx

Categories

Resources