2011-02-28 5 views
6

필자는 하나의 컨트롤을 채우도록 설정하고 나머지는 도킹을 설정하는 논리적이고 간단한 방법을 원합니다. 다음과 같이 사용할 수 있습니다 :WPF : FirstChildFill이있는 StackPanel?

<DockPanel LastChildFill="True"> 
    <Button Content="3" DockPanel.Dock="Bottom" /> 
    <Button Content="2" DockPanel.Dock="Bottom" /> 
    <Button Content="1" /> 
</DockPanel> 

그러나 매우 직관적 인 것은 아닙니다. 나는 이런 식으로 그것을 할도 수 :

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="*" /> 
    <RowDefinition Height="Auto" /> 
    <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Button Content="1" Grid.Row="0" /> 
    <Button Content="2" Grid.Row="1" /> 
    <Button Content="3" Grid.Row="2" /> 
</Grid> 

그러나 XAML의 그것도 꽤 많이 있습니다. 이 같은 내가 정말 원하는이다

이이 DockPanel과 같은 항목을 반전하지 않아도 및 그리드와 같이 행과 연결된 속성의 고정 번호를 사용하지 않으면 서 달성 할 수있는 방법을
<StackPanel Fill="None|First|Last"> 
    <Button Content="1" /> 
    <Button Content="2" /> 
    <Button Content="3" /> 
</StackPanel> 

?

답변

3

언제든지 서로 다른 도킹 규칙으로 패널을 작성할 수 있습니다. 표준 DockPanel 구현 (프레임 워크 소스에서 사용 가능 - 매우 복잡해 보이지 않음)을 사용하고 원하는 규칙과 비슷한 것을 만들 수 있습니다. DockPanel에서 파생되고 ArrangeOverride를 재정의하는 클래스를 만들 수도 있습니다.

개인적으로 필자는 도킹 패널을 사용합니다.이 패널은 어떤 멤버가 채우기에 대한 규칙이 마음에 들지 않는 것을 제외하고는 원하는대로 정확하게 수행합니다.

IME 그리드는 행을 삽입/삭제하면 끝없이 행 번호를 조정할 수 있다는 점에서 끔찍한 유지 관리 문제가 있습니다. DockPanel은 이와 관련하여 훨씬 쉽습니다.

업데이트 : - :

public class BottomDockingPanel : DockPanel 
{ 
    protected override Size ArrangeOverride(Size arrangeSize) 
    { 
     UIElementCollection children = InternalChildren; 
     int totalChildrenCount = children.Count; 

     double accumulatedBottom = 0; 

     for (int i = totalChildrenCount-1; i >=0 ; --i) 
     { 
      UIElement child = children[i]; 
      if (child == null) { continue; } 

      Size childDesiredSize = child.DesiredSize; 
      Rect rcChild = new Rect(
       0, 
       0, 
       Math.Max(0.0, arrangeSize.Width - (0 + (double)0)), 
       Math.Max(0.0, arrangeSize.Height - (0 + accumulatedBottom))); 

      if (i > 0) 
      { 
       accumulatedBottom += childDesiredSize.Height; 
       rcChild.Y = Math.Max(0.0, arrangeSize.Height - accumulatedBottom); 
       rcChild.Height = childDesiredSize.Height; 
      } 

      child.Arrange(rcChild); 
     } 
     return (arrangeSize); 
    } 
} 
+0

감사! 이것은 나를 시작하게 만들 것입니다 ... –

0

이 더 있습니다

다음

당신이 가고, 나는 당신에게 자신이 일의 즐거움을 거부 한이 그냥 잘라 다운/프레임 워크 소스의 버전을 반전 이 상자를 WPF에서 지원합니다. 이 특정 동작을 원한다면 자신 만의 패널을 만들 수도 있지만 꽤 자주 정의되고 필요하지 않기 때문에 그렇게하는 것이 좋습니다 (MidChildFill과 같은 동작을하는 패널을 원한다면 어떻게할까요? 그 사건에 대한 자신의 패널도?).

일반적으로 이러한 레이아웃은 Grid (앞에서 언급 한대로)을 사용하여 이루어집니다. 예, Grid은 매우 자세한 구문을 사용합니다 (this과 같은 도우미를 사용하여 단순화 할 수 있음).하지만 유연성이 가장 좋습니다. 그리고 하루가 끝나면 이것이 중요합니다.

+0

저는이 레이아웃 모델을 아주 자주 사용합니다. 마지막 또는 첫 번째 자식을 채울 수있는 옵션이있는 StackPanel은 매우 유용하다고 생각합니다. –

+0

@Andreas Zita - 이것은 귀하의 선택입니다, 나는 단지 내 경험을 공유하고 있습니다 :) –

1

내부에 StackPanel이있는 DockPanel을 사용할 수 있습니다. "기본"콘텐츠는 첫 번째 콘텐츠 대신 마지막 콘텐츠로 표시되지만, 최소한 콘텐츠는 XAML의 논리적 순서로 표시됩니다. 채워진 내용을 기꺼이 끝까지 기꺼이 가져 가려면이 방법이 가장 간단 할 것입니다. 당신은, 당신은 두 개의 행과 그리드와의 StackPanel에 사용할 수는 화면에 보여줍니다 같은 순서로 XAML에 표시하는 (채워진 내용을 포함) 모두를 원하는 경우

<DockPanel LastChildFill="True"> 
    <StackPanel DockPanel.Dock="Bottom"> 
    <Button Content="Bottom 1" /> 
    <Button Content="Bottom 2" /> 
    <Button Content="Bottom 3" /> 
    </StackPanel> 
    <Button Content="Main" /> 
</DockPanel> 

또는, 두 번째 행. 지적했듯이 그리드에는 상당한 양의 XAML이 필요하지만 중첩 된 StackPanel을 사용하면 각 새 항목에 RowDefinition 및 Grid.Row를 추가하지 않아도됩니다.

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="*" /> 
    <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Button Grid.Row="0" Content="Main" /> 
    <StackPanel Grid.Row="1"> 
    <Button Content="Bottom 1" /> 
    <Button Content="Bottom 2" /> 
    <Button Content="Bottom 3" /> 
    </StackPanel> 
</Grid> 
+0

내 특정 사례의 문제는 ItemsContainer에 템플릿으로이 레이아웃을 생성하고 거기에 분할 방법이 없다고 가정합니다. "주"와 "나머지"에있는 itemspresenter - 수. 가능하다면 ... –

+0

ViewModel에 항상 두 개의 속성 (첫 번째 자식 (공간을 채우기를 원함))과 나머지 항목 (하나는 속성)을 표시하게 할 수 있습니다. 그런 다음 첫 번째 ContentControl을 사용하고 나머지는 ItemsControl을 사용할 수 있습니다. 완전히 우아한 것은 아니지만 자신 만의 패널을 작성하는 것보다 훨씬 간단합니다. –

관련 문제