WordPress database error: [INSERT, UPDATE command denied to user '51213-2'@'10.10.20.88' for table 'wp_options']
INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('_transient_doing_cron', '1715964198.8947949409484863281250', 'yes') ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)


Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/rest-api/class-wp-rest-server.php on line 1372

Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/rest-api/class-wp-rest-server.php on line 1372

Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/rest-api/class-wp-rest-server.php on line 1372

Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/rest-api/class-wp-rest-server.php on line 1372

Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/rest-api/class-wp-rest-server.php on line 1372

Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/rest-api/class-wp-rest-server.php on line 1372

Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/rest-api/class-wp-rest-server.php on line 1372

Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/rest-api/class-wp-rest-server.php on line 1372
{"id":461,"date":"2011-09-23T10:29:24","date_gmt":"2011-09-23T09:29:24","guid":{"rendered":"http:\/\/www.jonathanantoine.com\/?p=461"},"modified":"2011-10-24T00:18:39","modified_gmt":"2011-10-23T22:18:39","slug":"wpf-4-5s-markupextension-invoke-a-method-on-the-viewmodel-datacontext-when-an-event-is-raised","status":"publish","type":"post","link":"http:\/\/www.jonathanantoine.com\/2011\/09\/23\/wpf-4-5s-markupextension-invoke-a-method-on-the-viewmodel-datacontext-when-an-event-is-raised\/","title":{"rendered":"UPDATE: WPF 4.5’s MarkupExtension : Invoke a method on the ViewModel \/ DataContext when an event is raised."},"content":{"rendered":"

\"\"<\/a>We have seen in a previous post<\/a> that WPF 4.5 enable the use of custom markup extensions to provide event handlers. <\/p>\n

In this post we’ll see that we can execute a method on the DataContext of the control when an event is raised using this new ability of the MarkupExtension. <\/strong><\/p>\n

With some tiny modifications you can run it on Silverlight too !<\/p>\n

<\/p>\n

How does it work ?<\/h3>\n

For a start, I suggest you to read my first post describing “markup extensions for events in WPF 4.5”.
\nThe code used is based on the one presented in this previous post.<\/p>\n

As already said, the DataContext may not be available when the MarkupExtension is used so it is not possible to register directly a Delegate on the ViewModel because we do not have it.<\/p>\n

So the tip I use is to create a proxy handler on the markup extension itself. When this handler is called, I will retrieve the viewModel from the DataContext because it will then be set. From it I am able to get the targeted method trough reflection. Then I just have to execute the method if it truly exists.<\/p>\n

The name of the method to call is passed in the constructor of the extension and is exposed as a property named ActionName<\/em>.<\/p>\n

The code !<\/h3>\n

It also can be found on my dropbox folder after registration<\/a>.
\n[csharp]
\npublic class Call : MarkupExtension
\n{
\n public string ActionName { get; set; }
\n public Call(string actionName){ ActionName = actionName; }<\/p>\n

public override object ProvideValue(IServiceProvider serviceProvider)
\n {
\n IProvideValueTarget targetProvider = serviceProvider
\n .GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
\n if (targetProvider == null)
\n throw new InvalidOperationException(@"The CallAction extension
\n can’t retrieved the IProvideValueTarget service.");<\/p>\n

targetProvider.TargetObject as FrameworkElement;
\n if (target == null)
\n throw new InvalidOperationException(@"The CallAction extension
\n can only be used on a FrameworkElement.");<\/p>\n

var targetEventAddMethod = targetProvider.TargetProperty as MethodInfo;
\n if (targetEventAddMethod == null)
\n throw new InvalidOperationException(@"The CallAction extension
\n can only be used on a event.");<\/p>\n

\/\/Retrieve the handler of the event
\n ParameterInfo[] pars = targetEventAddMethod.GetParameters();
\n Type delegateType = pars[1].ParameterType;<\/p>\n

\/\/Retrieves the method info of the proxy handler
\n MethodInfo methodInfo = this.GetType().GetMethod("MyProxyHandler",
\n BindingFlags.NonPublic | BindingFlags.Instance);<\/p>\n

\/\/Create a delegate to the proxy handler on the markupExtension
\n Delegate returnedDelegate =
\n Delegate.CreateDelegate(delegateType, this, methodInfo);<\/p>\n

return returnedDelegate;<\/p>\n

}<\/p>\n

void MyProxyHandler(object sender, EventArgs e)
\n {
\n FrameworkElement target = sender as FrameworkElement;
\n if (target == null) return;
\n var dataContext = target.DataContext;
\n if (dataContext == null) return;<\/p>\n

\/\/get the method on the datacontext from its name
\n MethodInfo methodInfo = dataContext.GetType()
\n .GetMethod(ActionName, BindingFlags.Public | BindingFlags.Instance);
\n methodInfo.Invoke(dataContext, null);
\n }
\n}
\n[\/csharp]<\/p>\n

How to use it ?<\/h3>\n

Use it is simplier thant to create it ! You simply have to use the markupExtension as you would declare a Binding in the XAML:
\n[xml]<Grid PreviewMouseDown="{custMarkup:Call MyMethodToCallOnTheViewModel}"
\n Background="Transparent"\/>[\/xml]<\/p>\n

For the record, here is the method I created on my ViewModel :
\n[csharp]public void MyMethodToCallOnTheViewModel()
\n{
\n MessageBox.Show("oh no, you’ve got me …");
\n}
\n[\/csharp]<\/p>\n

This example leads to really funny things \ud83d\ude42 :
\n
\"\"<\/a><\/p>\n

Update !<\/h3>\n

As pointed out by ThomasX in a comment below, the returned target property is not always a MethodInfo but can be an EventInfo. <\/strong>
\nIt seems to be a bug in this release (
a connection is open for it<\/a>) and I am pretty sure it will be corrected in the final release. By the time, I updated the code to work in all case. Here are only the revelant two parts. <\/p>\n

First we check the type of the target property:
\n[csharp]Delegate returnedDelegate =null;<\/p>\n

var targetEventAddMethod = targetProvider.TargetProperty as MethodInfo;
\nif (targetEventAddMethod != null)
\n returnedDelegate= CreateDelegateForMethodInfo(targetEventAddMethod);<\/p>\n

var targetEventInfo = targetProvider.TargetProperty as EventInfo;
\nif (targetEventInfo != null)
\n returnedDelegate=CreateDelegateForEventInfo(targetEventInfo);[\/csharp]<\/p>\n

Then, here is the method to create a delegate in case the target property is of EventInfo type:
\n[csharp] private Delegate CreateDelegateForEventInfo(EventInfo targetEventInfo)
\n {<\/p>\n

if (targetEventInfo == null)
\n throw new InvalidOperationException(
\n @"The CallAction extension can only be used on a event.");<\/p>\n

Type delegateType = targetEventInfo.EventHandlerType;<\/p>\n

\/\/Retrieves the method info of the proxy handler
\n MethodInfo methodInfo = this.GetType().GetMethod("MyProxyHandler",
\n BindingFlags.NonPublic | BindingFlags.Instance);<\/p>\n

\/\/Create a delegate to the proxy handler on the markupExtension
\n Delegate returnedDelegate =
\n Delegate.CreateDelegate(delegateType, this, methodInfo);
\n return returnedDelegate;
\n }[\/csharp]<\/p>\n

How can it be improved ?<\/h3>\n

Here is the improvement I lacked the time to implement:<\/p>\n

    \n
  • Check if the method on the ViewModel has the correct signature,<\/li>\n
  • Pass the event’s arguments to the ViewModel method if it accepts it,<\/li>\n
  • Cache the reflected method to save execution time,<\/li>\n
  • …<\/li>\n<\/ul>\n

    As said in my previous post, I think that because of the Blend integration, the preferred way to do this kind of feature has to be the behavior\/triggers.<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"

    We have seen in a previous post that WPF 4.5 enable the use of custom markup extensions to provide event handlers. In this post we’ll see that we can execute a method on the DataContext…<\/p>\n","protected":false},"author":3,"featured_media":508,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[6,4,5],"tags":[14,15],"_links":{"self":[{"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/posts\/461"}],"collection":[{"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/comments?post=461"}],"version-history":[{"count":17,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/posts\/461\/revisions"}],"predecessor-version":[{"id":708,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/posts\/461\/revisions\/708"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/media\/508"}],"wp:attachment":[{"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/media?parent=461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/categories?post=461"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/tags?post=461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}