2017-12-01 20 views
0

의 구조다른 클래스에서 여러 양식에 업데이트 이벤트를 보내기 - WPF

내가 꽤 정기적으로 업데이트를 확인 타이머를 발생시키는 간단한 양식을 가지고있다. 부하에서 시작 폼의 생성자는 그래서 다음과 같습니다

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; 
    } 
} 

다른 부분은 업데이트를 5 분마다 확인하는이 작은 루틴을 포함하는 UpdateManager를 클래스입니다.

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")); 
     } 
    } 
} 

이 회원은 다시 여러 형태의 읽을 필요가 있기 때문에, 내가하지 않는, 많은 주위 물체를 통과하지 않고 그들을 정적이지 수 없습니다 하고 싶다.

이 경우 여러 양식이 Meta 클래스에서받을 수있는 이벤트를 어떻게 시작합니까? 다른 구조를 고려해야합니까, 아니면 INotifyPropertyChanged를 오해하고 있습니까?

+0

하는 싱글 메타은의를 사용하십시오 메타은 다음과 같은 구조를 가지고 객체를 가져와 해당 소품에 액세스하는 인스턴스입니다. 그들은 INotify 또는 propdp''를 사용할 수 있습니다. 만약 propdps를 사용하면 wpf의 bindningsystem을 통해 수정자를 바꿀 때 updater를 제거 할 수 있습니다. –

+0

정적 속성 변경은 가능하지만 다른 점은 모든 것을 가져와야합니다. 세부 정보 : https://stackoverflow.com/a/41823852/424129 –

답변

1

여러 가지 방법으로 문제를 해결할 수 있지만 (메타 클래스의 DI를 각 페이지의 ViewModels로 생각하고 싱글 톤 접근 방식보다 선호되는 INPC에 대응), 메시징을 사용하는 것이 좋습니다. 이벤트보다는. 메시지 (대부분의 MVVM 프레임 워크에서 제공)는 느슨하게 결합 된 구성 요소간에 통신하는 좋은 방법입니다. MVVM Light과 같은 MVVM 라이브러리를 활용하면 Messenger 구현이 포함되어있어 매우 쉽습니다. 이 접근법의 가장 큰 장점은 알림을 받기를 원하는 양식이 이벤트 기반 접근 방식과 마찬가지로 소스의 참조를 유지할 필요가 없다는 것입니다.

모든 관심있는 양식을 메시지에 등록하고 수신하면 이에 따라 대응하십시오.

예를 들어 MVVM Light을 사용하면 INPC 속성이 업데이트 될 때 자동으로 메시지를 브로드 캐스팅 할 수 있습니다.다음

Messenger.Default.Register<PropertyChangedMessage<bool>>(this, m => ReceiveHasUpdatedMessage(m)); 

과 : (보통의 ViewModel에서) 응용 프로그램, 우리는이 작업을 수행 할 수의 완전히 분리/관련이없는 부분에 다음

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); 
    } 
} 

우리는 업데이 트에 관심이 있음을 나타냅니다 수신 람다 :

private void ReceiveHasUpdatedMessage(PropertyChangedMessage<bool> m) 
{ 
    // react accordingly.  
} 

이 MVVM 빛 ... 당신이 원하는 거의 아무것도 할 수 있습니다 제공하는 Messenger의 한 간단한 사용 사례입니다. 여기서이 전제는이 접근법을 사용하면 이해 당사자가 이미 터에 대한 하드 참조를 요구하지 못하도록한다는 것입니다.

0

모두의 도움이되는 조언을 조합하여 다음 코드를 작성했습니다. 필자가 테스트하지는 않았지만 MVVM 솔루션은 위와 같습니다. MVVM을 사용하지 않는다면, 이것이 내가 한 것입니다.

UpdateManager 클래스는 동일합니다.

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)))); 
    } 
    ... 
}