2014-02-12 2 views
6

DB에서 데이터를로드하고, 시뮬레이션을 계산하고, 경로를 최적화하는 등의 많은 장기 실행 작업을 처리해야하는 C# 4.0의 WPF 데스크톱 응용 프로그램을 개발하고 있습니다.WPF Please Wait Dialog

이러한 장기 실행 작업이 백그라운드에서 실행될 때 잠시 기다려주십시오. 대화 상자를 표시하고 싶습니다. Please-Wait 대화 상자가 표시되면 응용 프로그램을 잠글 수 있지만 응용 프로그램 창을 비활성화하는 것은 좋지 않습니다. 모든 DataGrid의 상태 (SelectedItem)가 손실 될 수 있기 때문입니다.

내가 지금까지 사용해 왔지만 몇 가지 문제가 있습니다 : Create-factory 메소드를 사용하여 새로운 WaitXUI가 생성되었습니다. Create 메서드는 캡션 텍스트와 잠글 수있는 호스트 컨트롤에 대한 참조를 필요로합니다. 작성 방법은 윈도우의 StartupLocation을 설정, 캡션 텍스트 및 호스트가 고정하려면 : WaitXUI 다음 표시 할 수있는 과부하 ShowDialog 메서드와

WaitXUI wait = WaitXUI.Create("Simulation running...", this); 
wait.ShowDialog(new Action(() => 
{ 
    // long running operation 
})); 

합니다. ShowDialog 과부하는 장기 실행 작업을 래핑하는 Action을 기대합니다.

ShowDialog 오버로드에서 자체 스레드에서 동작을 시작한 다음 호스트 컨트롤을 비활성화 (불투명도를 0.5로 설정하고 IsEnabled를 false로 설정)하고 기본 클래스의 ShowDialog를 호출합니다. 여기

public bool? ShowDialog(Action action) 
    { 
    bool? result = true; 

    // start a new thread to start the submitted action 
    Thread t = new Thread(new ThreadStart(delegate() 
    { 
     // start the submitted action 
     try 
     { 
      Dispatcher.UnhandledException += Dispatcher_UnhandledException; 
      Dispatcher.Invoke(DispatcherPriority.Normal, action); 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
     finally 
     { 
      // close the window 
      Dispatcher.UnhandledException -= Dispatcher_UnhandledException; 
      this.DoClose(); 
     } 
    })); 
    t.Start(); 

    if (t.ThreadState != ThreadState.Stopped) 
    { 
     result = this.ShowDialog(); 
    } 
    return result; 
} 

private new bool? ShowDialog() 
{ 
    DisableHost(); 
    this.Topmost = true; 
    return base.ShowDialog(); 
} 

private void DisableHost() 
{ 
    if (host != null) 
    { 
     host.Dispatcher.Invoke(new Action(delegate() 
     { 
      this.Width = host.Width - 20; 
      host.Cursor = Cursors.Wait; 
      host.IsEnabled = false; 
      host.Opacity = 0.5; 
     })); 
    } 
} 

는이 문제입니다 :
  • 는 WaitXUI 때때로 일부 밀리 초 동안 표시됩니다 (... selectedItems를) 상태 정보의 손실에 호스트 제어 결과를 비활성화

    • 때 스레드가 WaitXUI가 표시된 후 몇 ms 끝납니다.
    • 스레드가 여전히 실행 중이지만 대화 상자가 나타나지 않는 경우가 있습니다.

    이것은 현재 내 마음에 떠오르는 주요 문제입니다. 이 개념을 어떻게 개선 할 수 있습니까? 아니면이 문제를 해결하기 위해 어떤 다른 방법을 사용할 수 있습니까?

    미리 감사드립니다.

  • +0

    못생긴만큼 게시하지 않으려합니다. 모든 컨트롤을 IsEnabled = false로 설정하십시오. 또는 Window에서 입력을 캡처하고 e.handled = true로 설정하십시오. – Paparazzi

    +0

    이것은 확실히 중복입니다. – UIlrvnd

    +0

    http://stackoverflow.com/questions/3480966/display-hourglass-when-application-is-busy – Jimmy

    답변

    7

    WPF 응용 프로그램을 개발할 때 약간의 측면 사고가 항상 도움이됩니다. Grid, Rectangle, bool 속성 (이미 가질 수 있음) 및 BooleanToVisibilityConverter만으로 쉽게 요구 사항을 충족 할 수 있으며 컨트롤을 비활성화 할 필요가 없습니다.

    아이디어가 간단합니다. 보기 내용 앞에 RectangleOpacity 속성이 0.50.75 사이에 설정되어있는 흰색을 추가하십시오. 데이터 뒤에보기 모델 또는 코드에서 bool 재산의 Visibility 속성을 결합하고 BooleanToVisibilityConverter에 연결 : 당신이 컨트롤을 비활성화 할 때 이제

    <Grid> 
        <Grid> 
         <!--Put your main content here--> 
        </Grid> 
        <Rectangle Fill="White" Opacity="0.7" Visibility="{Binding IsWaiting, 
         Converter={StaticResource BoolToVisibilityConverter}}" /> 
        <!--You could add a 'Please Wait' TextBlock here--> 
    </Grid> 
    

    , 당신은 단지 것 truebool 속성을 설정하고 Rectangle UI가 흐리게 표시되게하십시오 :

    IsWaiting = true; 
    
    +0

    답변 해 주셔서 감사합니다. 그것은 BusyIndicator (_Eugene P_가 제안한)와 동일한 개념입니다. 가능한 해결 방법이 될 것입니다. 내가 좋아하지 않는 유일한 점은 WaitXUI가 호출 된 각 UI에 위 코드를 추가해야한다는 것입니다. 대기 대화 상자를 사용하는 많은 UI (> 50)가 있습니다. 한 곳에서 (WaitXUI에서) 할 수 있다면 좋을 것입니다! : -/ – goflo

    +0

    당신이 오해 한 것처럼 보입니다 ... 메인 뷰 모델의'MainWindow.xaml'과'bool' 속성에 이것을 넣으면, 당신은 하나만 필요합니다. '기본 콘텐츠를 여기에 넣으세요'라고 적혀있는 모든 일반 앱 콘텐츠를 * 넣으십시오. – Sheridan

    +0

    네, 맞습니다. 나는 각 UI가 아닌 각 창에서만 코드를 필요로한다. 나는 그것을 시도 할 것이다. 감사! – goflo

    1

    실제로 구현하지 않아도됩니다. 중복되는 것 같습니다.

    유사한 요구 사항에 대해 바쁨 표시기과 같이 이미 생성 된 구성 요소를 살펴보십시오. 이는 매우 중요하고 효과적입니다. .

    더 자세한 정보 codeplex

    +0

    답변 해 주셔서 감사합니다. BusyIndicator는 Sharidan이 제안한 것과 동일한 개념을 사용하고 있습니다. 그것은 가능한 해결책 일 것입니다. 내가 좋아하지 않는 유일한 점은 WaitXUI가 호출 된 각 UI에 BusyIndicator에 대한 UI 코드를 추가해야한다는 것입니다. 대기 대화 상자를 사용하는 많은 UI (> 50)가 있습니다. 한 곳에서 (WaitXUI에서) 할 수 있다면 좋을 것입니다! : -/ – goflo

    +0

    나는 당신이 도달하려고 시도했는지 확신 할 수 없다. 그러나 어쨌든, busyindicator는 바인드 가능하다. 이것을 root view placeholder로 설정 한 다음, 임의의 자식 (페이지/etc) 뷰를 주입 할 수있다. 다음으로 Binding을 사용하여 컨트롤 사용자 정의 작업을 손쉽게 수행 할 수 있습니다. –

    관련 문제