silverlight   发布时间:2022-05-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了MVVM之旅-给任意的事件绑定命令(Adventures in MVVM – Binding Commands to ANY Event)大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

 原文标题:Adventures in MVVM – Binding Commands to ANY Event 当我实现MVVM模式时,令我最为头疼一件事是需要给事件绑定命令。当我使用Prism框架时,我得到一个Button.Click的命令绑定,但是每一个其他的时间都需要单独的进行处理。做这些的时候,需要很多的@R_173_10197@的样板代码。在我过去的工作岗位上,我发表一些代码来减轻疼痛。然而,仍需要你针
@H_607_7@

 原文标题Adventures in MVVM – Binding Commands to ANY Event

当我实现MVVM模式时,令我最为头疼一件事是需要给事件绑定命令。当我使用Prism框架时,我得到一个Button.Click的命令绑定,但是每一个其他的时间都需要单独的进行处理。做这些的时候,需要很多的@R_173_10197@的样板代码。在我过去的工作岗位上,我发表一些代码来减轻疼痛。然而,仍需要你针对每一个你想进行绑定的事件写一个新的行为和附加内容

有一段时间了,我的想法只是直接绑定命令到时间。在这期间我遇到很多困难。例如,每一个事件处理都有一个同的事件参数类型。这需要所有的处理都是动态的。我仍然不能创建一个内置的命令绑定--我将确信对每一个单一控件绑定到超过1个的事件。因此我需要创建一个绑定的集合。创建结构体数据就是给自己创造麻烦---绑定仅工作在VisualTree的FrameWorkElements上。这需要我来写自己的绑定基于我的通用的行为。

以下是非常松散的基础下Chinch MVVM框架。我测试了这些代码在Silverlight和WPF,并且运行真的不错!

假定我有一个像如下的viewmode

public class MainPageviewmodel : INotifyPropertyChanged
{
    ...
    public ICommand MouSELEaveCommand { get; private set; }
    public ICommand MouseEnterCommand { get; private set; }
    public ICommand ClickCommand { get; private set; }
    ...
}

我能绑定命令到一个控件的时间上,以一Button为例:

Button Content="Click Me">
    <Behaviors:Events.Commands>
        <Behaviors:EventCommandCollection>
            <Behaviors:EventCommand CommandName="MouseEnterCommand" EventName="MouseEnter" />
            <Behaviors:EventCommand CommandName="MouSELEaveCommand" EventName="MouSELEave" />
            <Behaviors:EventCommand CommandName="ClickCommand" EventName="Click" />
        </Behaviors:EventCommandCollection>
    </Behaviors:Events.Commands>
</Button>

我不再需写任何的额外的代码,无论何时我想附加命令到我的事件上!下面是砂锅面代码的警告:

 

  1. the XAML requires the EventCommandCollection to be declared in the XAMl.  I struggled to figure out how to eliminate this but gave up.  Someone smarter than me might be able to tell me what I am doing wrong.
  2. This code does not consider command properties.  Every command assumes a null parameter.  If you need parameters (like data context),then you’ll have to do something differently (either use the old-school mechanism or extend this code to handle some special event types).
  3. You don’t bind directly to the command.  Instead,you declare the name of the command (Notice CommandName is not bound).  The behavior binds for you using a primitive mechanism.

下面给出命令的行为,它可以完成所有的工作:

public class Events
{
    private static readonly DependencyProperty EventBehaviorsProperty =
        DependencyProperty.RegisterAttached(
        "EventBehaviors",typeof(EventBehaviorCollection),typeof(Control),null);

    private static readonly DependencyProperty InternalDataContextProperty =
        DependencyProperty.RegisterAttached(
        "InternalDataContext",typeof(Object),new PropertyMetadata(null,DataContextChanged));

    private static void DataContextChanged(DependencyObject dependencyObject,DependencyPropertyChangedEventArgs E)
    {
        var target = dependencyObject as Control;
        if (target == null) return;

        foreach (var behavior in GetOrCreateBehavior(target))
            behavior.bind();
    }

    public static readonly DependencyProperty CommandsProperty =
        DependencyProperty.RegisterAttached(
        "Commands",typeof(EventCommandCollection),typeof(Events),CommandsChanged));

    public static EventCommandCollection GetCommands(DependencyObject dependencyObject)
    {
        return dependencyObject.GetValue(CommandsProperty) as EventCommandCollection;
    }

    public static void SetCommands(DependencyObject dependencyObject,EventCommandCollection eventCommands)
    {
        dependencyObject.SETVALue(CommandsProperty,eventCommands);
    }

    private static void CommandsChanged(DependencyObject dependencyObject,DependencyPropertyChangedEventArgs E)
    {
        var target = dependencyObject as Control;
        if (target == null) return;

        var behaviors = GetOrCreateBehavior(target);
        foreach (var eventCommand in e.NewValue as EventCommandCollection)
        {
            var behavior = new EventBehavior(target);
            behavior.bind(eventCommand);
            behaviors.Add(behavior);
        }

    }

    private static EventBehaviorCollection GetOrCreateBehavior(FrameworkElement target)
    {
        var behavior = target.GetValue(EventBehaviorsProperty) as EventBehaviorCollection;
        if (behavior == null)
        {
            behavior = new EventBehaviorCollection();
            target.SETVALue(EventBehaviorsProperty,behavior);
            target.SetBinding(InternalDataContextProperty,new Binding());
        }

        return behavior;
    }
}

public class EventCommand
{
    public String CommandName { get; set; }
    public String EventName { get; set; }
}

public class EventCommandCollection : List<EventCommand>
{
}

public class EventBehavior : CommandBehaviorBase<Control>
{
    private EventCommand _bindingInfo;

    public EventBehavior(Control control)
        : base(control)
    {

    }

    public void Bind(EventCommand bindingInfo)
    {
        ValidateBindingInfo(bindingInfo);

        _bindingInfo = bindingInfo;

        Bind();
    }

    private void ValidateBindingInfo(EventCommand bindingInfo)
    {
        if(bindingInfo == null) throw new Argumentexception("bindingInfo");
        if (String.IsNullOrEmpty(bindingInfo.CommandName)) throw new Argumentexception("bindingInfo.CommandName");
        if (String.IsNullOrEmpty(bindingInfo.EventName)) throw new Argumentexception("bindingInfo.EventName");
    }

    public void Bind()
    {
        ValidateBindingInfo(_bindingInfo);
        HookPropertyChanged();
        HookEvent();
        SetCommand();
    }

    public void HookPropertyChanged()
    {
        var dataContext = TargetObject.DataContext as INotifyPropertyChanged;
        if (dataContext == null) return;

        dataContext.PropertyChanged -= DataContextPropertyChanged;
        dataContext.PropertyChanged += DataContextPropertyChanged;
    }

    private void DataContextPropertyChanged(object sender,PropertyChangedEventArgs E)
    {
        if (e.PropertyName == _bindingInfo.CommandName)
            SetCommand();
    }

    private void SetCommand()
    {
        var dataContext = TargetObject.DataContext;
        if (dataContext == null) return;

        var propertyInfo = dataContext.GetType().GetProperty(_bindingInfo.CommandName);
        if (propertyInfo == null) throw new Argumentexception("commandName");

        Command = propertyInfo.GetValue(dataContext,null) as ICommand;
    }

    private void HookEvent()
    {
        var evenTinfo = TargetObject.GetType().GetEvent(
            _bindingInfo.EventName,BindingFlags.Public | BindingFlags.InstancE);
        if (evenTinfo == null) throw new Argumentexception("eventName");

        evenTinfo.RemoveEventHandler(TargetObject,GetEventMethod(evenTinfo));
        evenTinfo.AddEventHandler(TargetObject,GetEventMethod(evenTinfo));
    }

    private Delegate _method;
    private Delegate GetEventMethod(EvenTinfo evenTinfo)
    {
        if (evenTinfo == null) throw new ArgumentNullException("evenTinfo");
        if (evenTinfo.EventHandlerType == null) throw new Argumentexception("EventHandlerType is null");

        if (_method == null)
        {
            _method = Delegate.CreateDelegate(
                evenTinfo.EventHandlerType,this,GetType().getmethod("OnEvenTraised",BindingFlags.NonPublic | BindingFlags.InstancE));
        }

        return _method;
    }

    private void OnEvenTraised(object sender,EventArgs E)
    {
        ExecuteCommand();
    }
}

public class EventBehaviorCollection : List<EventBehavior>
{ }

翻译完毕,本人将继续制作有关WPF和WCF相关文章的翻译,如果有不错的文章可以推荐

转载请注明文章出处,表示对作者的尊重,谢谢……

大佬总结

以上是大佬教程为你收集整理的MVVM之旅-给任意的事件绑定命令(Adventures in MVVM – Binding Commands to ANY Event)全部内容,希望文章能够帮你解决MVVM之旅-给任意的事件绑定命令(Adventures in MVVM – Binding Commands to ANY Event)所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。