Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.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/jsf-2/2.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
Wpf Microsoft.Win32.SystemEvents事件不';Don’’我不能和温特经理一起工作_Wpf_Weak Events_Weakeventmanager - Fatal编程技术网

Wpf Microsoft.Win32.SystemEvents事件不';Don’’我不能和温特经理一起工作

Wpf Microsoft.Win32.SystemEvents事件不';Don’’我不能和温特经理一起工作,wpf,weak-events,weakeventmanager,Wpf,Weak Events,Weakeventmanager,当我这样做的时候 WeakEventManager<SystemEvents, EventArgs> .AddHandler(null, nameof(SystemEvents.DisplaySettingsChanged), OnDisplaySettingsChanged); ventManager .AddHandler(null,nameof(SystemEvents.DisplaySettingsChanged),OnDisplaySettingsChanged)

当我这样做的时候

WeakEventManager<SystemEvents, EventArgs>
    .AddHandler(null, nameof(SystemEvents.DisplaySettingsChanged), OnDisplaySettingsChanged);
ventManager
.AddHandler(null,nameof(SystemEvents.DisplaySettingsChanged),OnDisplaySettingsChanged);
My
OnDisplaySettingsChanged
从未被调用。但是,如果我改为通过
SystemEvents.DisplaySettingsChanged+=OnDisplaySettingsChanged
使用普通事件订阅,则一切正常


发生了什么事?

原来是
薄弱的管理员的错。触发事件时,表示静态事件源的
source
将为
null
(代码摘录自):

但是
SystemEvents
sender
从不为
null
。相反,它传递一个
SystemEvents
的私有实例,
WeakEventManager
然后假设它是另一个它以前不知道的实例,并且不调用处理程序

以下是我提出的解决方法:

class EventProxy
{
    private readonly Action<EventHandler> _subscribe;
    private readonly Action<EventHandler> _unsubscribe;

    public EventProxy(Action<EventHandler> subscribe, Action<EventHandler> unsubscribe)
    {
        _subscribe = subscribe;
        _unsubscribe = unsubscribe;
    }

    private EventHandler _event;
    public event EventHandler Event
    {
        add
        {
            if (_event == null)
                _subscribe(OnEvent);
            _event += value;
        }
        remove
        {
            // ReSharper disable once DelegateSubtraction
            _event -= value;
            if (_event == null)
                _unsubscribe(OnEvent);
        }
    }

    private void OnEvent(object sender, EventArgs args)
    {
        _event?.Invoke(this, args);
    }
}
class事件代理
{
私有只读操作_订阅;
私人只读操作_取消订阅;
公共事件代理(操作订阅、操作取消订阅)
{
_订阅=订阅;
_退订=退订;
}
私有EventHandler\u事件;
公共事件处理程序事件
{
添加
{
如果(_event==null)
_订阅(OneEvent);
_事件+=值;
}
去除
{
//ReSharper禁用一次委派减法
_事件-=值;
如果(_event==null)
_取消订阅(OneEvent);
}
}
私有void OneEvent(对象发送方、事件参数)
{
_事件?.Invoke(这个,args);
}
}
用法示例:

var proxy = new EventProxy(h => SystemEvents.DisplaySettingsChanged += h, h => SystemEvents.DisplaySettingsChanged -= h);
WeakEventManager<EventProxy, EventArgs>.AddHandler(proxy, nameof(EventProxy.Event), OnDisplaySettingsChanged);
var proxy=neweventproxy(h=>SystemEvents.DisplaySettingsChanged+=h,h=>SystemEvents.DisplaySettingsChanged-=h);
WeakEventManager.AddHandler(代理、名称(EventProxy.Event)、OnDisplaySettingsChanged);
一些解释:

  • SystemEvents
    包含对
    EventProxy
    的强引用,后者包含对处理程序的弱引用(通过
    WeakEventManager
  • WeakEventManager
    订阅
    AddHandler
    中的事件时,代理订阅原始事件
  • EventProxy
    充当静态事件和处理程序之间的代理,在原始事件激发时调用处理程序
  • 收集处理程序后,
    WeakEventManager
    最终将运行清理,发现处理程序已死亡并取消订阅
  • 这将导致代理取消订阅原始事件,并最终被GC收集
var proxy = new EventProxy(h => SystemEvents.DisplaySettingsChanged += h, h => SystemEvents.DisplaySettingsChanged -= h);
WeakEventManager<EventProxy, EventArgs>.AddHandler(proxy, nameof(EventProxy.Event), OnDisplaySettingsChanged);