2014-09-26 1 views
0

다음은 내 질문에 대한 간단한 예입니다. 함수 시작 부분에 나는 시각적 매개 변수를 변경하고 싶습니다. 예를 들어 창을 숨기고, 빨간색으로 ("내 예제"), 함수 끝에서 다시 넣고 싶습니다. 장기 기능을 위해 마우스 대기 커서와 비슷합니다.스레드가 바쁠 때 WPF 다시 그리기 창

기능 OnButtonClick이 종료되기 전에 버튼 빨간색을 어떤 우아한 방법이 있나요 - 윈도우 메시지 루프가 요청을 병렬 방식으로 배경 = 레드 처리하고 즉시 창을 다시 그릴 수 있도록 방법.

private void OnButtonClick(object sender, RoutedEventArgs e) 
{    
      System.Windows.Media.Brush br = ((Button)sender).Background; 
      ((Button)sender).Background = System.Windows.Media.Brushes.Red; 

      Mouse.OverrideCursor = Cursors.Wait; 
      Function(); //long-term function 
      Mouse.OverrideCursor = Cursors.Arrow; 

      ((Button)sender).Background = br;     
} 
+0

당신의 질문은 무엇입니까 :

<Button Command="{Binding TestCommand}" Content="Test" Focusable="False" Background="Green"> <Button.Resources> <Style TargetType="Button"> <Style.Triggers> <DataTrigger Binding="{Binding Loading}" Value="true"> <Setter Property="Background" Value="Red"/> </DataTrigger> </Style.Triggers> </Style> </Button.Resources> </Button> 

.cs 거짓이 경우로드 녹색의 버튼 배경을 설정합니다이 방법 =? –

+1

'Function()'을 다른 스레드에 넣으십시오. 배경 작업자 사용 – Bolu

답변

1

배경 작업자 또는 작업 병렬 라이브러리 (아래 참조)를 사용하여 새 스레드에서 실행할 수 있습니다.

private void OnButtonClick(object sender, RoutedEventArgs e) 
{    
      System.Windows.Media.Brush br = ((Button)sender).Background; 
      ((Button)sender).Background = System.Windows.Media.Brushes.Red; 

      Mouse.OverrideCursor = Cursors.Wait; 

      // Run function in a new thread. 
      Task.Factory.StartNew(() => 
      { 
       Function(); // Long running function. 
      }) 
      .ContinueWith((result) => 
       { 
        // Runs when Function is complete... 
        Mouse.OverrideCursor = Cursors.Arrow; 
        ((Button)sender).Background = br;  
       }); 


} 

.NET 4.5를 사용하는 경우 Async/Await 키워드로도이 작업을 수행 할 수 있습니다.

+0

고맙습니다. 그러나 이것은 제가 찾고있는 것이 아니며 다른 질문 일 것입니다 : 사용자가 다른 버튼을 클릭하고 창과 상호 작용하기를 원하지 않습니다. 오랫동안 작동하는 기능은 그리 길지 않았고 원래는 대기중인 커서 만 사용하고 이제 사용자에게 바쁜 창에 대한 더 나은 시각적 정보를 제공하려고합니다. 백그라운드 작업에서는 사용자가 실제로 바쁘지 않습니다. – user2136076

+1

귀하의 질문에 함수()를 실행하는 "병렬"방법이 필요합니다. 나는이 답변이 솔직히 질문에 완벽하게 대답한다고 생각한다. 다른 질문이있는 경우 사람들이 답변 할 시간이 지나면이 질문을 변경하는 대신 새 질문을 시작하십시오. – BenjaminPaul

+2

@user2136076이면이 확장 메서드를 사용할 수 있습니다. [새로 고침/WPF 컨트롤 새로 고침] (http://geekswithblogs.net/NewThingsILearned/archive/2008/08/25/refresh--update-wpf-controls.aspx) – Bolu

0

쉬운 방법이 있습니다.
XAML :

public class VM : INotifyPropertyChanged 
{ 
    public bool Loading 
    { 
     get { return _loading; } 
     private set 
     { 
      if (value.Equals(_loading)) return; 
      _loading = value; 
      OnPropertyChanged("Loading"); 
     } 
    } 
    public RelayCommand TestCommand 
    { 
     get { return _testCommand; } 
    } 

    void Test(object parameter) 
    { 
     Dispatcher.CurrentDispatcher.BeginInvoke((Action) (() => Loading = true)); 
     //or if you want to do it with more responsive UI then use 
     Dispatcher.CurrentDispatcher.Invoke((Action) (() => Loading = true)); 
     doSomething(); //this could be replaced with BackgroundWorker DoWork function 
     //or this code could be the DoWork function. 
     Loading = false; 
    } 
} 
+1

우아한 솔루션이지만 타이밍 문제가 발생할 수 있습니다. BeginInvoke 대신 Invoke를 사용하여 즉시 실행되도록하는 것이 더 좋을 것이라고 생각합니다. –

+0

@MarkTravis에게 제안 해 주셔서 감사합니다. 제 대답을 업데이트했습니다. – XAMlMAX

+1

@MarkTravis'Invoke'는 대리자를 즉시 ​​시작할 수는 없지만 대리자 스레드가 디스패처 스레드에 의해 서비스 될 때까지 호출 스레드를 차단합니다.이 호출자는 동기식으로 실행됩니다. http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke – Gusdor

관련 문제