c# - Binding Event to a Method of the ViewModel without ICommand -
the problem: bind event public method of viewmodel
via xaml.
the notorious solution create public icommand
property on viewmodel
returns relaycommand
or delegatecommand
, use eventtrigger
, invokecommandaction
windows.interactivity
in xaml bind event command. similar alternative use mvvmlight's eventtocommand
, provides possibility pass eventargs
command's parameter.
this solution has pitfall of being verbose, , hence makes code hard refactor , maintain.
i use markupextension binding event public method of viewmodel
directly. such possibility provided eventbindingextension
this blog post.
example usage in xaml:
<button content="click me" click="{my:eventbinding onclick}" />
where viewmodel has following method:
public void onclick(object sender, eventargs e) { messagebox.show("hello world!"); }
i have few questions regarding approach:
- i have tested , works charm me since no expert ask if solution have pitfalls or possibly unexpected behaviors.
- is in compliance mvvm pattern?
eventbindingextension
requires public method bound to match parameters of event. how extended allowobject source
parameter omitted?- what other markupextensions similar there available in frameworks wpf or nuget packages?
1) 1 of benefits of icommand can more route commands around application modifying bindings accordingly. binding directly handler lose functionality , have implement yourself. may not issue in specific case it's unnecessary layer regardless.
2) bit of subjective topic think although it's not technical violation of mvvm it's not in keeping overall philosophy. wpf, , mvvm, designed data-driven; binding method smacks of going old event-driven way of doing things (at least me). in case while binding method might still qualify mvvm, @ least technically, passing ui object in sender not!
3) you'll need modify gethandler function construct, compile , return either linq expression or il delegate accepts expected parameters, removes first , passes rest binding target's method. should enough started:
static delegate gethandler(object datacontext, eventinfo eventinfo, string eventhandlername) { // vm handler we're binding var eventparams = getparametertypes(eventinfo.eventhandlertype); var method = datacontext.gettype().getmethod(eventhandlername, eventparams.skip(1).toarray()); if (method == null) return null; // construct expression calls var instance = expression.constant(datacontext); var paramexpressions = eventparams.select(p => expression.parameter(p)).toarray(); var call = expression.call(instance, method, paramexpressions.skip(1)); // wrap in lambda , compile return expression.lambda(eventinfo.eventhandlertype, call, paramexpressions).compile(); }
4) bit of generic question, 1 use translate localization.
Comments
Post a Comment