1

WinRT でカスタム イベント用のクラスを作成しました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;

namespace BA_Lib
{
    public class RTEventHandler<T>
    {
        private EventRegistrationTokenTable<EventHandler<T>> m_EventTokenTable = null;

        public event EventHandler<T> Event
        {
            add { EventRegistrationTokenTable<EventHandler<T>>.GetOrCreateEventRegistrationTokenTable(ref m_EventTokenTable).AddEventHandler(value); return; }
            remove { EventRegistrationTokenTable<EventHandler<T>>.GetOrCreateEventRegistrationTokenTable(ref m_EventTokenTable).RemoveEventHandler(value); }
        }

        public void Fire(T argument)
        {
            EventHandler<T> temp = EventRegistrationTokenTable<EventHandler<T>>.GetOrCreateEventRegistrationTokenTable(ref m_EventTokenTable).InvocationList;
            if (temp != null)
                temp(null, argument);
        }

        public void Fire(object sender,T argument)
        {
            EventHandler<T> temp = EventRegistrationTokenTable<EventHandler<T>>.GetOrCreateEventRegistrationTokenTable(ref m_EventTokenTable).InvocationList;
            if (temp != null)
                temp(sender, argument);
        }
    }
}

このクラスを使用して、次のように独自のイベントへのカスタム バインディングを作成します。

public RTEventHandler<int> Count{get;set;}

public void init(){Count=new RTEventHandler<int>();}

そして、他のクラスから:

EventHolder.Count.Event+=myEventHandler;

EventHolder.Count.Event-=myEventHandler;これは魅力のように機能しますが、トークンを使用してイベントから登録解除しようとすると、テーブルのままになります。これにより、イベント ハンドラーが蓄積され、複数回起動されるため、望ましくない動作が発生します。

4

1 に答える 1

1

問題を解決できたので、最終的な解決策を投稿して、さらに参照できるようにします。

問題は、RemoveEventHandler 関数がハンドラーではなくトークンを予期していたことです。このトークンは、AddEventHandler 関数によって返されます。add は void を返すため、このトークンを返すことができませんでした。このトークンを保持し、それらを EventHandler にリンクするための辞書を追加しました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;

namespace BA_Lib
{
    public class RTEventHandler<T>
    {
        private EventRegistrationTokenTable<EventHandler<T>> m_EventTokenTable = null;
        Dictionary<EventHandler<T>, EventRegistrationToken> _tokens = new Dictionary<EventHandler<T>, EventRegistrationToken>();

        public event EventHandler<T> Event
        {
            add
            {
                if (_tokens.ContainsKey(value))
                    return;
                var token = EventRegistrationTokenTable<EventHandler<T>>.GetOrCreateEventRegistrationTokenTable(ref m_EventTokenTable).AddEventHandler(value);
                _tokens.Add(value, token);
                return;
            }
            remove
            {
                if (_tokens.ContainsKey(value))
                {
                    var token = _tokens[value];
                    EventRegistrationTokenTable<EventHandler<T>>.GetOrCreateEventRegistrationTokenTable(ref m_EventTokenTable).RemoveEventHandler(token);
                    _tokens.Remove(value);
                }
            }
        }

        public void Fire(T argument)
        {
            EventHandler<T> temp = EventRegistrationTokenTable<EventHandler<T>>.GetOrCreateEventRegistrationTokenTable(ref m_EventTokenTable).InvocationList;
            if (temp != null)
                temp(null, argument);
        }

        public void Fire(object sender, T argument)
        {
            EventHandler<T> temp = EventRegistrationTokenTable<EventHandler<T>>.GetOrCreateEventRegistrationTokenTable(ref m_EventTokenTable).InvocationList;
            if (temp != null)
                temp(sender, argument);
        }
    }
}

私がやっていることは、トークンと EventHanlder (呼び出す関数) の間の接続を追跡することです。このようにして、関数からトークンを解決し、エントリを削除できます。

于 2013-09-25T05:44:14.577 に答える