1

Silverlight에서 MVVM을 사용하려고하지만 아주 익숙하지 않아서 어떤 점에 대해서는 확신하지 못합니다. 일부 서버 측 작업 진행 상황을 표시하는 실버 라이트 페이지가 있습니다. 현재 진행 상황은 웹 서비스에서 발생하며 매 몇 초마다 새로 고쳐야합니다 (논쟁을 위해 10 초를 말합니다).Silverlight보기를 MVVM으로 주기적으로 업데이트하십시오.

이것을 구현하는 가장 좋은 방법은 무엇입니까? 내가 생각할 수있는 옵션은이었다

  1. Initalize 내 뷰 모델의 Initalize 방법에 DispatcherTimer하고

  2. 는 랩퍼를 작성 (뷰 모델에 타이머 세부 사항을 넣어)을 DispatcherTimer 이벤트에서보기를 새로 고침 컨트롤이거나 내가 (보기에 타이머 세부 사항을 넣어) 뷰 모델에 새로 고침 명령에 결합 명령 속성 WindowsForms의 타이머 제어

유사 자원 것 DispatcherTimer (예 PeriodicCommandExecutor) arround를

두 번째 옵션은 ViewModel을 테스트하기가 더 쉽고 DispatcherTimer가 ViewModel에서 적절하게 원하지 않는 UI 구현 세부 사항이기 때문에 두 번째 옵션을 선호한다고 생각합니다. 동의하니?

예인 경우 해당 래퍼를 어떻게 작성 하시겠습니까? 첨부 된 속성을 사용하여 DependencyObject를 시작했지만 Interval과 같은 속성 값을 내부 DispatcherTimer로 전달하는 방법을 모르겠습니다. Silverlight는 종속성 속성이 변경 될 때 이벤트를 제공하지 않는 것으로 보이며 DispatcherTimer가 DependencyObject가 아니므로 해당 속성에 직접 데이터 바인딩 할 수 없습니다.

감사합니다.

답변

0

결국 나는 내 딜레마를 해결할 수있는 ViewModel에서 주기적으로 새로 고침 명령을 실행하는 동작을 만들었습니다.

동작에 대한 코드는 같은이 (VB 코드에 대한 죄송합니다)입니다 :

Option Strict On 

Imports System.Windows.Threading 
Imports System.Windows.Interactivity 

Namespace View.Behaviors 

    Public Class RefreshBehavior 
     Inherits Behavior(Of FrameworkElement) 



     Public Property Command As ICommand 
      Get 
       Return DirectCast(GetValue(CommandProperty), ICommand) 
      End Get 

      Set(ByVal value As ICommand) 
       SetValue(CommandProperty, value) 
      End Set 
     End Property 

     Public Shared ReadOnly CommandProperty As DependencyProperty = _ 
            DependencyProperty.Register("Command", _ 
                   GetType(ICommand), GetType(RefreshBehavior), _ 
                   New PropertyMetadata(Nothing)) 


     Public Property CommandParameter As Object 
      Get 
       Return GetValue(CommandParameterProperty) 
      End Get 

      Set(ByVal value As Object) 
       SetValue(CommandParameterProperty, value) 
      End Set 
     End Property 

     Public Shared ReadOnly CommandParameterProperty As DependencyProperty = _ 
            DependencyProperty.Register("CommandParameter", _ 
                   GetType(Object), GetType(RefreshBehavior), _ 
                   New PropertyMetadata(Nothing)) 




     Public Property Interval As TimeSpan 
      Get 
       Return DirectCast(GetValue(IntervalProperty), TimeSpan) 
      End Get 

      Set(ByVal value As TimeSpan) 
       SetValue(IntervalProperty, value) 
      End Set 
     End Property 

     Public Shared ReadOnly IntervalProperty As DependencyProperty = _ 
            DependencyProperty.Register("Interval", _ 
                   GetType(TimeSpan), GetType(RefreshBehavior), _ 
                   New PropertyMetadata(TimeSpan.Zero, AddressOf OnIntervalUpdate)) 



     Public Property Enabled As Boolean 
      Get 
       Return DirectCast(GetValue(EnabledProperty), Boolean) 
      End Get 

      Set(ByVal value As Boolean) 
       SetValue(EnabledProperty, value) 
      End Set 
     End Property 

     Public Shared ReadOnly EnabledProperty As DependencyProperty = _ 
           DependencyProperty.Register("Enabled", _ 
           GetType(Boolean), GetType(RefreshBehavior), _ 
           New PropertyMetadata(False, AddressOf OnEnabledUpdate)) 




     Dim WithEvents timer As New DispatcherTimer() 

     Private Shared Sub OnEnabledUpdate(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs) 
      Dim enable As Boolean = CType(e.NewValue, Boolean) 
      Dim executor As RefreshBehavior = CType(d, RefreshBehavior) 
      If Not executor.attached Then Return 

      Dim timer As DispatcherTimer = executor.timer 

      If enable AndAlso Not timer.IsEnabled Then 
       timer.Start() 
      ElseIf Not enable AndAlso Not timer.IsEnabled Then 
       timer.Stop() 
      End If 
     End Sub 

     Private Shared Sub OnIntervalUpdate(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs) 
      Dim executor As RefreshBehavior = CType(d, RefreshBehavior) 

      Dim timer As DispatcherTimer = executor.timer 
      timer.Interval = CType(e.NewValue, TimeSpan) 
     End Sub 

     Private WithEvents attachedObject As FrameworkElement 

     Private Sub OnUnload(ByVal sender As Object, ByVal e As EventArgs) Handles attachedObject.Unloaded 
      timer.Stop() 
     End Sub 

     Private attached As Boolean = False 
     Protected Overrides Sub OnAttached() 
      attached = True 
      attachedObject = AssociatedObject 

      If Enabled Then timer.Start() 
      MyBase.OnAttached() 
     End Sub 

     Protected Overrides Sub OnDetaching() 
      timer.Stop() 
      attached = False 
      attachedObject = Nothing 
      MyBase.OnDetaching() 
     End Sub 

     Private Sub OnTick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer.Tick 
      Dim cmd = Command 
      Dim parameter = CommandParameter 
      If Interval < TimeSpan.MaxValue AndAlso cmd IsNot Nothing AndAlso cmd.CanExecute(parameter) Then 
       cmd.Execute(parameter) 
      End If 
     End Sub 
    End Class 
End Namespace 

당신은 다음과 같이 사용할 수 있습니다 :

<i:Interaction.Behaviors> 
    <Behaviors:RefreshBehavior Enabled="True" Interval="0:0:10" Command="{Binding RefreshPageCommand}" /> 
</i:Interaction.Behaviors> 

을 나는 그것이 비슷한 문제를 가진 사람을 도움이되기를 바랍니다 .

0

왜 DispatcherTimer를 사용합니까? 일반 스레드 System.Threading.Timer을 사용하지 않으면 배경 스레드에서 콜백이 실행됩니다.

UI 진행 업데이트를 UI의 중심이 아닌 하단 중앙 또는 상태 표시 줄에 놓으면 사용자가하고있는 일을 계속하는 동안 배경 타이머가 꺼져 버리게됩니다. . 진행률 값을 뷰 모델에 채울 수 있으며 바인딩을 사용하여 UI에 표시 할 수 있습니다. 이렇게하면 웹 서비스 호출을하는 UI 스레드를 묶을 필요가 없습니다.

+0

이것은 실제로 문제가되지 않습니다. Silverlight의 서비스 호출은 항상 백그라운드 스레드에서 실행되며 실제로 작업이 끝나고 ViewModel에 업데이트 논리가있는 경우 별도의 * 완료 이벤트가 있습니다. 그리고 당신이 제안한 것처럼 데이터 바인딩이 있습니다. 따라서 어떤 경우에도보기가 차단되지 않습니다. – aKzenT