2009-11-16 3 views
9

SizeToContentWidthAndHeight으로 설정하면 WindowStartupLocation="CenterOwner"이 제대로 작동하지 않습니다. 새로운 윈도우의 중심이 부모 소유자의 중앙에 위치하는 대신, 부모 창의 중심에있을 자식 윈도우의 왼쪽 상단 모서리와 비슷해 보입니다. SizeToContent을 삭제하면 모두 괜찮습니다. 무엇이 잘못 되었나요?wpf 센터 하위 창이 sizetocontent와 작동하지 않습니다.

답변

6

창을 당신이 잊고 될 수 생각할 수

있는 유일한 방법은 실제로 그 소유자가 자식 창을 얘기하는 것입니다 가 측정되면, WindowStartupLocation은 측정 프로세스에 의해 계산 된 창의 ActualWidthActualHeight을 사용하여 처리됩니다.

설명하는 동작에 따라 ActualWidthActualHeight이 0 또는 Show() 또는 ShowDialog() 호출시 상대적으로 작게 측정되고 나중에 0이 아닌 값으로 설정됩니다.

예를 들어, 창 컨텐트가 Loaded 이벤트에서만 설정된 DataContext를 사용하여 작성된 경우 이런 일이 발생할 수 있습니다. Show()이 호출되면 창은 아직 Loaded이 아니며 데이터가 없습니다. 나중에 Loaded 이벤트가 발생하면 DataContext를 설정하고 창에서 해당 내용을 업데이트하지만 위치 지정이 이미 발생했습니다.

다른 많은 시나리오가 있습니다. 예를 들어 Dispatcher.BeginInvoke 호출을 사용하여 채워진 내용이나 별도의 스레드 또는 지연되거나 비동기적인 바인딩이 있습니다.

기본적으로 Show()이 호출 될 때 창의 내용이 보통보다 작아 질 수있는 항목을 찾아 수정해야합니다.

+0

감사합니다. 실제로 Show() 바로 뒤에 내용을로드하고있었습니다. 바보 같은 실수, 지금은 잘 작동 :) – immuner

1

질문이 약간 모호합니다. SizeToContent 및 WindowStartupLocation을 설정하는 창 ("부모"또는 "자식")은 무엇입니까?

내 프로젝트에서 두 번째 창을 만들고 설명대로 SizeToContent 및 WindowStartupLocation을 설정하면 원하는 결과를 얻습니다. 또는, 더 간결

Window2 w = new Window2(); 
w.Owner = this; // "this" being the parent window 
w.ShowDialog(); 

:

new Window2 { Owner = this }.ShowDialog(); 
9

글쎄, 레이는 이것을 훌륭하게 처리했습니다. 간단히 말해, 그가 말하고자하는 것은 당신이 윈도우의 위치 결정이 완료 후 Height & Width (또한 ActualHeight & ActualWidth) 재설정하여 Loaded 이벤트에 컨트롤의 내용을 설정하는 것을입니다.

, 당신은 두 가지 대안이이 문제를 해결하려면 다음 Owner에 따라 Window의 위치를 ​​계산하는 간단한 방법을 추가

    생성자에 콘텐츠 값 설정 코드를 이동
  1. , 또는,
  2. 및 다음과 같이 Loaded 이벤트가 끝날 때이 메소드를 호출하십시오.

...

private void CenterOwner() 
{ 
    if (Owner != null) 
    { 
     double top = Owner.Top + ((Owner.Height - this.ActualHeight)/2); 
     double left = Owner.Left + ((Owner.Width - this.ActualWidth)/2); 

     this.Top = top < 0 ? 0 : top; 
     this.Left = left < 0 ? 0 : left; 
    } 
} 
2

바인딩 된 동적 콘텐츠는 대개 GUI로 렌더링되지만 GUI로 전달되는 경우도 있습니다. 타이머 및 다른 스레드는 MVVM (Property Change Event) 속성 변경 이벤트를 시작할 수 있습니다. WPF Dispacher 대기열의 우선 순위를 지정하기 때문에 가까운 시간에 렌더링이 수행되지만 병합되지는 않습니다. 그래서 렌더링이 끝났을 때 WPF가 처리 순서에 관해 말할 수 없다는 것을 말할 수 없으므로 WPF는 이제 StartPosition을 계산하기에 이상적인 시간이 될 수 없습니다.

WPF 대기열은 emtpy라는 트릭입니다. 그렇다면 WPF는 코드를 처리 할 시간이 있다는 것을 확신합니다. 즉, 창에 대한 ShowDialog 호출이 지연됩니다.

MVVM 또는 기타 다이내믹 변화에 대한 동적 컨텐츠 변경을 수행하려면 항상이 필요한 GUI 메인 스레드를 제공하십시오. 다중 디스플레이를 지원하기 위해 위치를 수동으로 계산하지 마십시오. 매우 복잡합니다. WPF가 모든 작업을 완료하면 창을 열 때이 코드를 사용하여 창만 엽니 다.

 win.Dispatcher.Invoke(new Action(() => win.ShowDialog()), DispatcherPriority.ApplicationIdle); 
관련 문제