Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在不使用事件的情况下从任何类更新UI_C#_.net_Wpf - Fatal编程技术网

C# 在不使用事件的情况下从任何类更新UI

C# 在不使用事件的情况下从任何类更新UI,c#,.net,wpf,C#,.net,Wpf,我的大多数用户控件和类都需要能够将条目(日志)添加到由列表框绑定的MainWindow中的ObservableCollection 有没有一种优雅的方法可以做到这一点,而无需将MainWindow传递给这些类和控件中的每一个,也无需使用事件,这样我就不必担心内存泄漏 编辑: 好主意,我只能传递Log类,但我仍然希望避免在实例化时向每个类传递Log 我希望存在某种应用程序范围的侦听器,能够从任何地方接收消息,保持代码干净。Prism为您提供了一个事件聚合器,并负责管理对象。使用聚合器,您只能发布和

我的大多数用户控件和类都需要能够将条目(日志)添加到由列表框绑定的MainWindow中的ObservableCollection

有没有一种优雅的方法可以做到这一点,而无需将MainWindow传递给这些类和控件中的每一个,也无需使用事件,这样我就不必担心内存泄漏

编辑: 好主意,我只能传递Log类,但我仍然希望避免在实例化时向每个类传递Log


我希望存在某种应用程序范围的侦听器,能够从任何地方接收消息,保持代码干净。

Prism为您提供了一个
事件聚合器,并负责管理对象。使用聚合器,您只能发布和订阅事件。如果需要传递一些数据,可以将它们与事件一起发布

this.eventAggregator.GetEvent<MyEvent>().Publish(myCustomData);
尽管它仍然是基于事件的,但该解决方案比使用经典事件和处理程序要优雅得多


在这个链接下,你可以找到更详细的解释:

是的,Prism EventAggregator非常适合这种类型的东西

但是,如果您不想sip Prism Kool-Aid,另一种可能有效的方法是让主窗口注册一个自定义TraceListener,并让其他代码使用跟踪方法填充日志。然后,主窗口TraceListener可以对跟踪数据执行任何操作。

我最终使用了 因为我已经在我的程序中使用了Reactive,它非常简单

在主窗口我有

using Reactive.EventAggregator;
MyEventAggregator.MessageAggregator = new EventAggregator();
MyEventAggregator.MessageAggregator.GetEvent<MessageEvent>().Subscribe(se =>
myMessageControl.Add(se)
);

它甚至可以被简化,但我希望MessageEvent在将来保存的不仅仅是一个字符串。

是什么让你认为会出现
内存泄漏
你在编写代码时没有实现
自动处理对象I。使用(){}
或自己不清理对象
您需要实现INotifyPropertyChanged
如果您不熟悉如何实现,那么您可以从这里开始阅读
Daniel
@DJKRAZE not
-=
ing事件处理程序可以在堆中锁定以其他方式正确处理的对象,并防止GC清理它们。这并不是说这个问题没有一个简单的解决方案(即:删除您添加的处理程序),但是有比您建议的更多的方法引发内存泄漏。您为什么要通过MainWindow?只需传递日志。
J
我很清楚内存泄漏的许多方式,我只是一般性地问一下。唯一的方式是,如果这些其他控件比主窗口寿命长一段时间,就会导致内存泄漏。这听起来不太可能,因此让主窗口将一个处理程序附加到其他控件并引用其自身不会是一个问题。尽管这看起来很简单,但我还是希望尽量避免将Prism添加到我的解决方案中,只是为了有一个日志。这很公平。不过,对于任何处于计划阶段而不是实施阶段的人来说,这可能是一条有用的线索。@Daniel您可以非常轻松地编写自己的简单EventAggregator。你甚至可以环顾互联网,找到一个没有完整棱柱的现有的。我正在尝试实现,但如何看待它,我需要全局对象eventAggregator,它需要从所有类访问。这似乎与我调用MainWindow.LogCollection.AddUsing上文提到的一样:如果我理解,我会创建
公共静态事件聚合器EventAggregator
,并使用它发布和订阅。它工作起来很简单。是这样做的吗?
private void HandleMyCustomData(MyCustomData data) { }
using Reactive.EventAggregator;
MyEventAggregator.MessageAggregator = new EventAggregator();
MyEventAggregator.MessageAggregator.GetEvent<MessageEvent>().Subscribe(se =>
myMessageControl.Add(se)
);
using Reactive.EventAggregator;
public partial class MessageControl : UserControl
{
    public MessageControl()
    {
        InitializeComponent();
        LB.SetBinding(ListBox.ItemsSourceProperty, new Binding { Source = this.MessageCollection });
    }
    public ObservableCollection<MessageEvent> MessageCollection = new ObservableCollection<MessageEvent>();

    public void Add(MessageEvent m)
    {
        MessageCollection.Add(m);
    }
}

public class MyEventAggregator
{
    public static EventAggregator MessageAggregator { get; set; }
    public static void PostMessage(string message)
    {
        MessageAggregator.Publish(new MessageEvent(message));
    }
}
MyEventAggregator.PostMessage("This message appears in MessageControl's Listbox");