C# 如何从EventToCommandBehavior分离?

C# 如何从EventToCommandBehavior分离?,c#,xamarin,C#,Xamarin,在使用从这里获得的EventToCommandBehavior类时,我似乎遇到了重复事件: 我遵循的是MVVM模式,因此在我的XAML中有以下内容: <Switch IsToggled="{Binding FilterOptions.IsActive}" HorizontalOptions="Center"> <Switch.Behaviors> <behaviour:EventToCommandBehaviour Event

在使用从这里获得的EventToCommandBehavior类时,我似乎遇到了重复事件:

我遵循的是MVVM模式,因此在我的XAML中有以下内容:

<Switch IsToggled="{Binding FilterOptions.IsActive}"
        HorizontalOptions="Center">
    <Switch.Behaviors>
        <behaviour:EventToCommandBehaviour EventName="Toggled" Command="{Binding OnActiveCommand}" CommandParameter="{Binding FilterOptions.IsActive}" />
    </Switch.Behaviors>
</Switch>
public ICommand OnActiveCommand => new Command<Boolean>(OnActive);
public ICommand OnDiscontinuedCommand => new Command<Boolean>(OnDiscontinued);

private void OnDiscontinued(Boolean value) {
    Debug.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
    if (!value) {
        FilterOptions.IsActive = false;
    }
}

private void OnActive(Boolean value) {
    Debug.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
    if (!value) {
        FilterOptions.IsDiscontinued = false;
    }
}

在我的ViewModel中,我有:

<Switch IsToggled="{Binding FilterOptions.IsActive}"
        HorizontalOptions="Center">
    <Switch.Behaviors>
        <behaviour:EventToCommandBehaviour EventName="Toggled" Command="{Binding OnActiveCommand}" CommandParameter="{Binding FilterOptions.IsActive}" />
    </Switch.Behaviors>
</Switch>
public ICommand OnActiveCommand => new Command<Boolean>(OnActive);
public ICommand OnDiscontinuedCommand => new Command<Boolean>(OnDiscontinued);

private void OnDiscontinued(Boolean value) {
    Debug.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
    if (!value) {
        FilterOptions.IsActive = false;
    }
}

private void OnActive(Boolean value) {
    Debug.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
    if (!value) {
        FilterOptions.IsDiscontinued = false;
    }
}
public-ICommand-OnActiveCommand=>new命令(OnActive);
public ICommand OnDiscontinued=>new命令(OnDiscontinued);
私有void OnDiscontinued(布尔值){
Debug.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
如果(!值){
FilterOptions.IsActive=false;
}
}
私有void OnActive(布尔值){
Debug.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
如果(!值){
FilterOptions.IsDiscontinued=false;
}
}
它完美地连接在一起,当我与开关交互时,命令按预期调用。但是,我注意到,如果我关闭当前页面并返回到它,当我与任何开关交互时,命令会重复吗


我在OnDetachingFrom()上(在BahviourBase.cs中)和DeregisterEvent()上(在eventToCommandBehavior.cs中)放置了一个断点,假设在关闭页面时可以调用它们?二者均如下所示:

BahviourBase.cs

public class BehaviourBase<T> : Behavior<T> where T : BindableObject {
    public T AssociatedObject { get; private set; }

    protected override void OnAttachedTo(T bindable) {
        base.OnAttachedTo(bindable);
        AssociatedObject = bindable;

        if (bindable.BindingContext != null) {
            BindingContext = bindable.BindingContext;
        }

        bindable.BindingContextChanged += OnBindingContextChanged;
    }

    protected override void OnDetachingFrom(T bindable) {
        base.OnDetachingFrom(bindable);
        bindable.BindingContextChanged -= OnBindingContextChanged;
        AssociatedObject = null;
    }

    void OnBindingContextChanged(object sender, EventArgs e) {
        OnBindingContextChanged();
    }

    protected override void OnBindingContextChanged() {
        base.OnBindingContextChanged();
        BindingContext = AssociatedObject.BindingContext;
    }
}
public class EventToCommandBehaviour : BehaviourBase<View> {
    Delegate eventHandler;

    public static readonly BindableProperty EventNameProperty = BindableProperty.Create("EventName", typeof(string), typeof(EventToCommandBehaviour), null, propertyChanged: OnEventNameChanged);
    public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(EventToCommandBehaviour), null);
    public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(EventToCommandBehaviour), null);
    public static readonly BindableProperty InputConverterProperty = BindableProperty.Create("Converter", typeof(IValueConverter), typeof(EventToCommandBehaviour), null);

    public string EventName {
        get { return (string)GetValue(EventNameProperty); }
        set { SetValue(EventNameProperty, value); }
    }

    public ICommand Command {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public object CommandParameter {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    public IValueConverter Converter {
        get { return (IValueConverter)GetValue(InputConverterProperty); }
        set { SetValue(InputConverterProperty, value); }
    }

    protected override void OnAttachedTo(View bindable) {
        base.OnAttachedTo(bindable);
        RegisterEvent(EventName);
    }

    protected override void OnDetachingFrom(View bindable) {
        DeregisterEvent(EventName);
        base.OnDetachingFrom(bindable);
    }

    void RegisterEvent(string name) {
        if (string.IsNullOrWhiteSpace(name)) {
            return;
        }

        EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
        if (eventInfo == null) {
            throw new ArgumentException(string.Format("EventToCommandBehavior: Can't register the '{0}' event.", EventName));
        }
        MethodInfo methodInfo = typeof(EventToCommandBehaviour).GetTypeInfo().GetDeclaredMethod("OnEvent");
        eventHandler = methodInfo.CreateDelegate(eventInfo.EventHandlerType, this);
        eventInfo.AddEventHandler(AssociatedObject, eventHandler);
    }

    void DeregisterEvent(string name) {
        if (string.IsNullOrWhiteSpace(name)) {
            return;
        }

        if (eventHandler == null) {
            return;
        }
        EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
        if (eventInfo == null) {
            throw new ArgumentException(string.Format("EventToCommandBehavior: Can't de-register the '{0}' event.", EventName));
        }
        eventInfo.RemoveEventHandler(AssociatedObject, eventHandler);
        eventHandler = null;
    }

    void OnEvent(object sender, object eventArgs) {
        if (Command == null) {
            return;
        }

        object resolvedParameter;
        if (CommandParameter != null) {
            resolvedParameter = CommandParameter;
        } else if (Converter != null) {
            resolvedParameter = Converter.Convert(eventArgs, typeof(object), null, null);
        } else {
            resolvedParameter = eventArgs;
        }

        if (Command.CanExecute(resolvedParameter)) {
            Command.Execute(resolvedParameter);
        }
    }

    static void OnEventNameChanged(BindableObject bindable, object oldValue, object newValue) {
        var behavior = (EventToCommandBehaviour)bindable;
        if (behavior.AssociatedObject == null) {
            return;
        }

        string oldEventName = (string)oldValue;
        string newEventName = (string)newValue;

        behavior.DeregisterEvent(oldEventName);
        behavior.RegisterEvent(newEventName);
    }
}
公共类行为库:行为,其中T:BindableObject{
公共T关联对象{get;私有集;}
受保护的覆盖无效数据到(T可绑定){
碱。可粘合的DTO(可粘合);
AssociatedObject=可绑定;
if(bindable.BindingContext!=null){
BindingContext=bindable.BindingContext;
}
bindable.BindingContextChanged+=OnBindingContextChanged;
}
受保护的覆盖无效OnDetachingFrom(T可绑定){
基础。从(可装订)开始连接;
bindable.BindingContextChanged-=OnBindingContextChanged;
AssociatedObject=null;
}
void OnBindingContextChanged(对象发送方,事件参数e){
OnBindingContextChanged();
}
受保护的覆盖无效OnBindingContextChanged(){
base.OnBindingContextChanged();
BindingContext=AssociatedObject.BindingContext;
}
}
eventtocommandbehavior.cs

public class BehaviourBase<T> : Behavior<T> where T : BindableObject {
    public T AssociatedObject { get; private set; }

    protected override void OnAttachedTo(T bindable) {
        base.OnAttachedTo(bindable);
        AssociatedObject = bindable;

        if (bindable.BindingContext != null) {
            BindingContext = bindable.BindingContext;
        }

        bindable.BindingContextChanged += OnBindingContextChanged;
    }

    protected override void OnDetachingFrom(T bindable) {
        base.OnDetachingFrom(bindable);
        bindable.BindingContextChanged -= OnBindingContextChanged;
        AssociatedObject = null;
    }

    void OnBindingContextChanged(object sender, EventArgs e) {
        OnBindingContextChanged();
    }

    protected override void OnBindingContextChanged() {
        base.OnBindingContextChanged();
        BindingContext = AssociatedObject.BindingContext;
    }
}
public class EventToCommandBehaviour : BehaviourBase<View> {
    Delegate eventHandler;

    public static readonly BindableProperty EventNameProperty = BindableProperty.Create("EventName", typeof(string), typeof(EventToCommandBehaviour), null, propertyChanged: OnEventNameChanged);
    public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(EventToCommandBehaviour), null);
    public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(EventToCommandBehaviour), null);
    public static readonly BindableProperty InputConverterProperty = BindableProperty.Create("Converter", typeof(IValueConverter), typeof(EventToCommandBehaviour), null);

    public string EventName {
        get { return (string)GetValue(EventNameProperty); }
        set { SetValue(EventNameProperty, value); }
    }

    public ICommand Command {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public object CommandParameter {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    public IValueConverter Converter {
        get { return (IValueConverter)GetValue(InputConverterProperty); }
        set { SetValue(InputConverterProperty, value); }
    }

    protected override void OnAttachedTo(View bindable) {
        base.OnAttachedTo(bindable);
        RegisterEvent(EventName);
    }

    protected override void OnDetachingFrom(View bindable) {
        DeregisterEvent(EventName);
        base.OnDetachingFrom(bindable);
    }

    void RegisterEvent(string name) {
        if (string.IsNullOrWhiteSpace(name)) {
            return;
        }

        EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
        if (eventInfo == null) {
            throw new ArgumentException(string.Format("EventToCommandBehavior: Can't register the '{0}' event.", EventName));
        }
        MethodInfo methodInfo = typeof(EventToCommandBehaviour).GetTypeInfo().GetDeclaredMethod("OnEvent");
        eventHandler = methodInfo.CreateDelegate(eventInfo.EventHandlerType, this);
        eventInfo.AddEventHandler(AssociatedObject, eventHandler);
    }

    void DeregisterEvent(string name) {
        if (string.IsNullOrWhiteSpace(name)) {
            return;
        }

        if (eventHandler == null) {
            return;
        }
        EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
        if (eventInfo == null) {
            throw new ArgumentException(string.Format("EventToCommandBehavior: Can't de-register the '{0}' event.", EventName));
        }
        eventInfo.RemoveEventHandler(AssociatedObject, eventHandler);
        eventHandler = null;
    }

    void OnEvent(object sender, object eventArgs) {
        if (Command == null) {
            return;
        }

        object resolvedParameter;
        if (CommandParameter != null) {
            resolvedParameter = CommandParameter;
        } else if (Converter != null) {
            resolvedParameter = Converter.Convert(eventArgs, typeof(object), null, null);
        } else {
            resolvedParameter = eventArgs;
        }

        if (Command.CanExecute(resolvedParameter)) {
            Command.Execute(resolvedParameter);
        }
    }

    static void OnEventNameChanged(BindableObject bindable, object oldValue, object newValue) {
        var behavior = (EventToCommandBehaviour)bindable;
        if (behavior.AssociatedObject == null) {
            return;
        }

        string oldEventName = (string)oldValue;
        string newEventName = (string)newValue;

        behavior.DeregisterEvent(oldEventName);
        behavior.RegisterEvent(newEventName);
    }
}
公共类事件到CommandBehavior:行为库{
委托事件处理程序;
public static readonly BindableProperty EventNameProperty=BindableProperty.Create(“EventName”、typeof(string)、typeof(eventToCommandBehavior)、null、propertyChanged:OnEventNameChanged);
public static readonly BindableProperty CommandProperty=BindableProperty.Create(“命令”、typeof(ICommand)、typeof(eventtocommandbehavior)、null);
public static readonly BindableProperty CommandParameterProperty=BindableProperty.Create(“CommandParameter”、typeof(object)、typeof(eventToCommandBehavior)、null);
public static readonly BindableProperty InputConverterProperty=BindableProperty.Create(“转换器”、typeof(IValueConverter)、typeof(eventtocommandbehavior)、null);
公共字符串事件名{
获取{return(string)GetValue(EventNameProperty);}
set{SetValue(EventNameProperty,value);}
}
公共ICommand命令{
获取{return(ICommand)GetValue(CommandProperty);}
set{SetValue(CommandProperty,value);}
}
公共对象命令参数{
获取{return GetValue(CommandParameterProperty);}
set{SetValue(CommandParameterProperty,value);}
}
公用变频器{
获取{return(IValueConverter)GetValue(InputConverterProperty);}
set{SetValue(InputConverterProperty,value);}
}
受保护的替代数据(视图可绑定){
碱。可粘合的DTO(可粘合);
RegisterEvent(事件名称);
}
受保护的覆盖无效OnDetachingFrom(视图可绑定){
注销事件(事件名称);
基础。从(可装订)开始连接;
}
无效RegisterEvent(字符串名称){
if(string.IsNullOrWhiteSpace(name)){
返回;
}
EventInfo EventInfo=AssociatedObject.GetType().GetRuntimeEvent(名称);
if(eventInfo==null){
抛出新的ArgumentException(string.Format(“EventToCommandBehavior:无法注册“{0}”事件。”,EventName));
}
MethodInfo MethodInfo=typeof(EventToCommandBehavior).GetTypeInfo().GetDeclaredMethod(“OneEvent”);
eventHandler=methodInfo.CreateDelegate(eventInfo.EventHandlerType,this);
AddEventHandler(关联对象,eventHandler);
}
作废注销事件(字符串名称){
if(string.IsNullOrWhiteSpace(name)){
返回;
}
if(eventHandler==null){
返回;
}
EventInfo EventInfo=AssociatedObject.GetType().GetRuntimeEvent(名称);
if(eventInfo==null){
抛出新的ArgumentException(string.Format(“EventToCommandBehavior:无法取消注册“{0}”事件。”,EventName));
}
RemoveEventHandler(关联对象,eventHandler);
eventHandler=null;
}
void OnEvent(对象发送方、对象事件参数){
如果(命令==null){
返回;
}
对象解析参数;
if(CommandParameter!=null){
resolvedParameter=命令参数;
}else if(转换器!=null){
resolvedParameter=Converter.Convert(eventArgs,typeof(object),null,null);
}否则{
resolvedParameter=eventArgs;
}
if(Command.CanExecute(resolvedParameter)){
Command.Execute(resolvedParameter);
}
}
静态void OnEventNameChanged(BindableObject bindable、object oldValue、object newValue){
变量行为=(EventToCommandBehavior)可绑定;
if(behavior.AssociatedObject==null){
返回;
}
字符串oldEventName=(字符串)oldValue;
字符串newEventName=(字符串)newValue;