Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.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# 从不同类向多个表单发送更新事件-WPF_C#_Wpf_Events_Inotifypropertychanged - Fatal编程技术网

C# 从不同类向多个表单发送更新事件-WPF

C# 从不同类向多个表单发送更新事件-WPF,c#,wpf,events,inotifypropertychanged,C#,Wpf,Events,Inotifypropertychanged,结构 我有一个简单的表单,可以启动一个计时器,定期检查更新。加载时启动的窗体的构造函数如下所示: public MainWindow() { InitializeComponent(); otherWindow = new TheOtherWindow(); if (Meta.hasUpdate) { updateImage.Source = new BitmapImage(new Uri("/My

结构

我有一个简单的表单,可以启动一个计时器,定期检查更新。加载时启动的窗体的构造函数如下所示:

public MainWindow()
    {
        InitializeComponent();
        otherWindow = new TheOtherWindow();

        if (Meta.hasUpdate)
        {
            updateImage.Source = new BitmapImage(new Uri("/MyProject;component/Images/updateTrue.gif", UriKind.Relative));
        }

        Thread updateMonitor = new Thread(() =>
        {
            UpdateManager updater = new UpdateManager();
            updater.StartUpdateMonitor();
        });

        updateMonitor.IsBackground = true;
        updateMonitor.Start();
    }
元类包含一些非常基本的信息,存储各种字符串,这些字符串在多个位置被引用,但有时会被更新。其中包括:

class Meta
{
    ...
    private static bool hasUpdate = false;

    public static bool GetHasUpdate()
    {
        return hasUpdate;
    }

    public static void SetHasUpdate(bool value)
    { 
        hasUpdate = value;
    }
}
另一部分是UpdateManager类,它包括一个小例程,每5分钟检查一次更新

class UpdateManager
{
    Timer timer;

    public void CheckForUpdates(Object source, ElapsedEventArgs e)
    {

        if (!isUpToDate())
        {
            timer.Stop();
            Meta.SetHasUpdate(true);

            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                MessageBox.Show("A new update is now available!);
            }));
        }
    }

    public void StartUpdateMonitor()
    {
        float updateInterval = 300000;

        timer = new Timer(updateInterval); // Milliseconds between checks.

        timer.Elapsed += CheckForUpdates;
        timer.AutoReset = true;
        timer.Enabled = true;
    }
}
问题

简而言之,我想在到达Meta.SetHasUpdate()时触发一个事件,然后将其广播到应用程序中的所有表单,目的是更改一个小图标以指示更新可用

我尝试这样做的结果是,我认识到实现INotifyPropertyChanged并不能很好地处理静态成员。这是我试图实现的

class Meta : INotifyPropertyChanged

{
    ...
    private static bool hasUpdate = true;

    public static bool GetHasUpdate()
    {
        return hasUpdate;
    }

    public static void SetHasUpdate(bool value)
    { 
        hasUpdate = value;
        NotifyPropertyChanged();
    }

    private static void NotifyPropertyChanged()
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(null, new PropertyChangedEventArgs("hasUpdate"));
        }
    }
}
由于这些成员需要从多个表单中读回,我不能在不大量传递对象的情况下使它们不是静态的,这是我不想做的


在这种情况下,如何触发多个窗体可以从元类接收的事件?我需要考虑一个不同的结构,或者我误解了IntIfyPrimTyType?

< P>。虽然可以有很多方法来解决这个问题,(想想你的元类的DI到每个页面的VIEW模型中,并对IPC做出反应……这将比单点方法更好),一个要考虑的方法是使用消息而不是事件。消息(在大多数MVVM框架中提供)是松散耦合组件之间通信的好方法。如果您利用MVVM库,比如,那么这非常容易,因为它包含了一个Messenger实现。这种方法的主要优点是,您希望接收通知的表单不一定需要保留源的引用,就像使用基于事件的方法一样

只需让所有感兴趣的表单注册一条消息,并在收到消息时做出相应的反应

例如,使用MVVM Light,我们可以利用INPC属性更新后自动广播消息的优势

 private bool hasUpdate;
 public bool HasUpdate
 {
    {
        return hasUpdate;
    }

    set
    {
        // the last bool param indicates whether or not to broadcast a message to all interested parties. 
        Set(nameof(HasUpdate), ref hasUpdate, value, true);
    }
}
然后在应用程序的一个完全独立/不相关的部分(通常在ViewModel中),我们可以这样做以表明我们对此类更新感兴趣:

 Messenger.Default.Register<PropertyChangedMessage<bool>>(this, m => ReceiveHasUpdatedMessage(m));
Messenger.Default.Register(this,m=>ReceiveHasUpdatedMessage(m));
然后在接收lambda中:

 private void ReceiveHasUpdatedMessage(PropertyChangedMessage<bool> m)
 {
    // react accordingly.      
 }
private void ReceiveHasUpdatedMessage(PropertyChangedMessage m)
{
//作出相应的反应。
}

这只是MVVM Light提供的
Messenger
的一个简单用例。。你几乎可以做任何你想做的事。这里的前提是,使用这种方法可以使相关方不需要硬引用发射器

结合了大家非常有用的建议,我编写了以下代码。MVVM解决方案如上所述,尽管我没有对其进行测试。如果您不使用MVVM,这就是我所做的

UpdateManager类是相同的。Meta具有以下结构:

class Meta 
{
    private static bool hasUpdate = false;
    public static event PropertyChangedEventHandler StaticPropertyChanged;

    public static bool GetHasUpdate()
    {
        return hasUpdate;
    }

    public static void SetHasUpdate(bool value)
    { 
        hasUpdate = value;
        StaticNotifyPropertyChanged();
    }

    private static void StaticNotifyPropertyChanged([CallerMemberName] string propertyName = null)
    {
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
    }
}
然后,对于我想知道这种变化的任何形式,我插入以下代码:

public partial class SomeForm : Window
{
    public SomeForm()
    {
        InitializeComponent();

        Meta.StaticPropertyChanged += MethodThatTriggersOnUpdate;
        ...
    }

    private void MethodThatTriggersOnUpdate(object sender, EventArgs e)
    {
        myImage.Dispatcher.BeginInvoke(
            (Action)(() => myImage.Source = new BitmapImage(
            new Uri("/MyProject;component/Images/myNewImage.gif", UriKind.Relative))));
    }
    ...
}

尝试单例元,使用实例获取对象,并访问其道具。他们可以使用INotify或propdp's-如果propdps,那么当他们通过wpf的绑定系统将更改推送到绑定到他们的人时,您可以去掉更新程序静态属性更改是可行的,但它是不同的,并且您必须正确获得所有细节: