0

我编写了一个 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();
    }

}

提前致谢。

4

1 回答 1

0

您可能需要考虑查看 Prism WPF 框架。里面有很多东西,但您感兴趣的是一个名为 EventAggregator 的类,它为您完成所有这些工作。

EventAggregator 允许您“发布”其他类可以“订阅”的事件。但与传统的 .Net 事件不同,订阅者不会直接将事件处理程序连接到引发事件的对象。EventAggregator 充当中间人,因此发布者或其订阅者都不需要相互了解。

发布和订阅是单行的,但奇怪的是令人费解,所以我将 EventAggregator 包装在一个辅助类中以简化一些事情:-

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 线程等)。

于 2014-03-27T16:38:00.507 回答