2017-03-23 22 views
0

"(프리즘) 영역"MainViewRegion "이있는 MainWindow를 사용하여 WPF에서 작업하고 있습니다. 이것은 사용자의 원하는보기를 기반으로 전환되며, 그렇게 할 때 MainWindow는 삽입 된보기의 새 치수에 맞추기 위해 크기가 조정됩니다.프리즘 영역 전환 및 컨테이너 인스턴스와의 동기화

지역 전환 후 바탕 화면에 창을 완전히 표시하는 코드가 있습니다. 코드는 다음과 같습니다.

private void WindowModeChange(string uri)    
{ 

     IRegion mviewRegion = regionManager.Regions[RegionNames.MainViewRegion]; 

     if (mviewRegion == null) return; 

     regionManager.RequestNavigate(mviewRegion.Name, new Uri(uri, UriKind.Relative)); 

      //Get the MainWindow instance from the container 
      var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView); 
      //Make sure the entire window is visible onscreen 
      ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc); 
} 

"uc"변수는 영역 변경 전에 항상 MainWindow 매개 변수와 동일합니다. "uc"는 항상 내가 원하는 것보다 한 발 앞선다. 그래서 "snap-to"코드는 항상 꺼져있다.

무엇이 누락 되었습니까?

+1

그렇게하지 마십시오. 그러지 마. regionmanager에서 응답 할 수있는 이벤트가 많이 있으며 탐색 콜백에서 이벤트를 수행 할 수 있습니다. 그러나 VM에서 View에 액세스하지 마십시오. 이 논리 유형은 VIew의 코드 숨김에 속합니다. –

+0

오 와우! 브라이언 라구나 스! 개인적인 팁을 감사하십시오. 이 메서드는 뷰 모델이 아닌 "컨트롤러"로 추가해야합니다. – Moe45673

+0

@BrianLagunas : 응답 한 알림을 시작하기 만하면 – Moe45673

답변

1

일부 이벤트에서 실행되는 코드가 있고 UI가 이미 해당 이벤트에 어느 정도 응답했는지 확인해야 할 때 가장 좋은 방법은 Dispatcher을 사용하여 실행을 지연하는 것입니다. 제공 한 코드로 판단하면 UI 변경은 regionManager.RequestNavigate 호출에 의해 트리거됩니다. 이제는 그 문서를 가리킬 수는 없지만, 프레임 워크가이 요청을 처리 할 것이라는 것을 경험으로부터 알았습니다. 비동기 적으로입니다. 즉, 모든 작업이 발생하기 전에 컨트롤이 사용자의 메서드로 반환됩니다. 이 요청에 의해 (따라서 귀하의 문제가) 완료됩니다. 그것은 (내가 말할 수있는 한) Dispatcher을 사용하여 프레임 워크에 의해 내부적으로 수행됩니다.

프레임 워크에서 트리거 된 변경을 처리해야하는 정도에 따라 적절한 DispatcherPriority 열거 형 값을 사용하여 코드가 실행 된 후에 특정 작업이 완료되도록해야합니다. 귀하의 질문에 근거하여, 나는 DispatcherPriority.Loaded이 좋은 선택이라고 생각합니다. (발송자가 중요한 조건 인) 사용자 입력이 처리되기 전에 디스패처가 그러한 코드를 실행할 것입니다. 개인적으로는 작업이 중지 될 때까지 우선 순위를 최대화하는 경향이 있습니다 (예를 들어 사용자 입력과 같은 예기치 않은 동작을 피할 수 있음).

그래서 코드이 수정이 당신의 목표를 달성하기에 충분해야한다 :

이제
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView); 
uc.Dispatcher.InvokeAsync(() => 
    ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc), 
    DispatcherPriority.Loaded); 

난 당신이 궁극적으로 Dispatcher.Invoke보다는 Dispatcher.InvokeAsync에 정착 것으로 나타났습니다 - 나는 그것이를 이후는 귀하의 경우 확인 같아요 귀하의 방법에 마지막으로 지시하지만, 일반적으로 안전한 방법은 Dispatcher.InvokeAsync (나는 개인적으로 Dispatcher.Invoke 겨자를 자르지 않은 상황을 경험했습니다)를 사용하는 것입니다.

+0

놀라운 답변을 보내 주셔서 감사합니다! 그러면 InvokeAsync로 전환 할 것입니다. 필자의 경우에 가장 의미있는 점에 대해 정말로 숙고 할 필요가 있습니다. 창을 옮겨서 가상 화면 내에 완전히 들어갈 때까지 사용자가 아무 것도하지 않기를 바란다. – Moe45673

0

내 질문에 대한 의견에 Grx70 덕분에 그는 해결책을 내게되었습니다.

IRegion mviewRegion = regionManager.Regions[RegionNames.MainViewRegion]; 

     if (mviewRegion == null) return; 


     mviewRegion.RequestNavigate(new Uri(uri, UriKind.Relative), (x => 
     { 

      var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView); 
      uc.Dispatcher.Invoke(() => ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc), DispatcherPriority.Loaded); 

     })); 

나는 내가 RequestNavigate()의 콜백 매개 변수에 디스패처를 호출 한 이유에 확실하지 오전하지만, 그것없이 작동하지 않습니다 방법의 몸은 이제 읽습니다.