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();
}
}
您可能想要考虑一下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线程等)