WPF, EventAggregator代替定时器读取游标位置

本文关键字:读取 游标 位置 定时器 EventAggregator WPF | 更新日期: 2023-09-27 17:53:50

我编写了一个WPF应用程序,其中Singleton类读取光标坐标,Observer类使用它将它们发布到标签中。

在Singleton类读取坐标现在我使用定时器。我想用EventAggregator取代他,这将使用MouseMoveEvent。我读了很多教程,但我不明白EventAggregator是如何工作的,如何适合我的应用程序。有人能解释一下我自己的例子吗?下面是代码:

单:

public class MousePointProvider
{
    [DllImport("user32.dll")]
    static extern bool GetCursorPos(ref System.Drawing.Point lpPoint);
    private List<IObserver> _observerList;
    private DispatcherTimer _timer;
    private static MousePointProvider _instance = null;
    public static MousePointProvider Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new MousePointProvider();
            }
            return _instance;
        }
    }
    private Point _currentMousePosition;
    public Point CurrentMousePosition
    {
        get { return _currentMousePosition; }
    }
    private MousePointProvider()
    {
        _observerList = new List<IObserver>();
        _timer = new DispatcherTimer();
        _timer.Interval = TimeSpan.FromMilliseconds(1);
        _timer.Tick += (s, e) =>
            {
                MousePositionChanged();
            };
        _timer.Start();
    }
    public void RegisterObserver(IObserver observer)
    {
        if (!_observerList.Contains(observer))
        {
            _observerList.Add(observer);
        }
    }
    public void UnregisterObserver(IObserver observer)
    {
        _observerList.Remove(observer);
    }
    public void MousePositionChanged()
    {
        GetCursorPos(ref _currentMousePosition);
        for (int i = 0; i < _observerList.Count; i++)
        {
            _observerList[i].MouseChanged(_currentMousePosition.X, _currentMousePosition.Y);
        }
    }
}

观察者:

public class Listener : Canvas, IObserver
{
    System.Windows.Controls.Label labelX = new System.Windows.Controls.Label();
    System.Windows.Controls.Label labelY = new System.Windows.Controls.Label();
    public Listener()
    {
        MousePointProvider.Instance.RegisterObserver(this);
        this.Children.Add(labelX);
        Canvas.SetLeft(labelX, 100);
        Canvas.SetTop(labelX, 100);
        this.Children.Add(labelY);
        Canvas.SetLeft(labelY, 100);
        Canvas.SetTop(labelY, 200);
    }
    public void MouseChanged(int x, int y)
    {
        labelX.Content = "X=" + x.ToString();
        labelY.Content = "Y=" + y.ToString();
    }

}

WPF, EventAggregator代替定时器读取游标位置

您可能想要考虑一下Prism WPF框架。里面有很多东西,但你感兴趣的是一个叫做EventAggregator的类它为你做了所有这些。

EventAggregator允许你"发布"其他类可以"订阅"的事件。但与传统的。net事件不同,订阅者不直接将事件处理程序连接到引发事件的对象。EventAggregator作为一个中间人,所以发布者和订阅者都不需要知道对方。

发布和订阅是一行代码,但奇怪地令人费解,所以我将EventAggregator包装在一个helper类中以简化事情:-

public class EventAggregatorWrapper
{
    private EventAggregator _eventAggregator = new EventAggregator();
    // Publish
    public void Publish<TEvent>(TEvent eventToPublish)
    {
        GetEvent<TEvent>().Publish(eventToPublish);
    }
    // Subscribe
    public SubscriptionToken Subscribe<TEvent>(
        Action<TEvent> action, 
        ThreadOption threadOption = ThreadOption.PublisherThread, 
        bool keepSubscriberReferenceAlive = false, 
        Predicate<TEvent> filter = null)
    {
        return GetEvent<TEvent>().Subscribe(action, threadOption, keepSubscriberReferenceAlive, filter);
    }
    // Unsubscribe
    public void Unsubscribe<TEvent>(SubscriptionToken token)
    {
        GetEvent<TEvent>().Unsubscribe(token);
    }
    // Helper method to get a CompositePresentationEvent to act upon.
    private CompositePresentationEvent<TEvent> GetEvent<TEvent>()
    {
        return _eventAggregator.GetEvent<CompositePresentationEvent<TEvent>>();
    }
}
接下来,你需要创建一个类来表示你的事件"消息"(有点像EventArgs对象),例如:
public class CursorMovedMessage
{
    public Point NewPosition { get; set; }
}

然后发布一个事件:-

var msg = new CursorMovedMessage();
msg.NewPosition = new Point(mouse.X, mouse.Y);
_eventAggregatorWrapper.Publish(msg);

"消费者"将像这样订阅这些消息:-

_eventAggregatorWrapper.Subscribe<CursorMovedMessage>(CursorMovedMessageHandler, ThreadOption.BackgroundThread);
private void CursomrMovedMessageHandler(CursorMovedMessage msg)
{
    // Do something with the message object here
}

订阅者可以指定在哪个线程上运行委托(例如UI线程,b/g线程等)