Làm cách nào để khiến con của StackPanel lấp đầy không gian tối đa xuống dưới?


356

Tôi chỉ đơn giản muốn chuyển văn bản ở bên trái và một hộp trợ giúp ở bên phải.

Hộp trợ giúp nên mở rộng đến tận đáy.

Nếu bạn lấy ra bên ngoài StackPanel dưới nó hoạt động tuyệt vời.

Nhưng vì lý do bố trí (tôi đang chèn UserControls một cách linh hoạt) tôi cần phải có gói StackPanel .

Làm cách nào để tôi GroupBoxkéo dài xuống tận cùng StackPanel, như bạn có thể thấy tôi đã thử:

  • VerticalAlignment="Stretch"
  • VerticalContentAlignment="Stretch"
  • Height="Auto"

XAML:

<Window x:Class="TestDynamic033.Test3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test3" Height="300" Width="600">
    <StackPanel 
        VerticalAlignment="Stretch" 
        Height="Auto">

        <DockPanel 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            Height="Auto" 
            Margin="10">

            <GroupBox 
                DockPanel.Dock="Right" 
                Header="Help" 
                Width="100" 
                Background="Beige" 
                VerticalAlignment="Stretch" 
                VerticalContentAlignment="Stretch" 
                Height="Auto">
                <TextBlock Text="This is the help that is available on the news screen." TextWrapping="Wrap" />
            </GroupBox>

            <StackPanel DockPanel.Dock="Left" Margin="10" Width="Auto" HorizontalAlignment="Stretch">
                <TextBlock Text="Here is the news that should wrap around." TextWrapping="Wrap"/>
            </StackPanel>

        </DockPanel>
    </StackPanel>
</Window>

Câu trả lời:

Cảm ơn Mark, sử dụng DockPanelthay vì StackPanelxóa nó lên. Nói chung, tôi thấy mình đang sử dụng DockPanelngày càng nhiều hơn cho bố cục WPF, đây là XAML cố định:

<Window x:Class="TestDynamic033.Test3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test3" Height="300" Width="600" MinWidth="500" MinHeight="200">
    <DockPanel 
        VerticalAlignment="Stretch" 
        Height="Auto">

        <DockPanel 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            Height="Auto" 
            MinWidth="400"
            Margin="10">

            <GroupBox 
                DockPanel.Dock="Right" 
                Header="Help" 
                Width="100" 
                VerticalAlignment="Stretch" 
                VerticalContentAlignment="Stretch" 
                Height="Auto">
                <Border CornerRadius="3" Background="Beige">
                    <TextBlock Text="This is the help that is available on the news screen." TextWrapping="Wrap" 

                Padding="5"/>
                </Border>
            </GroupBox>

            <StackPanel DockPanel.Dock="Left" Margin="10" Width="Auto" HorizontalAlignment="Stretch">
                <TextBlock Text="Here is the news that should wrap around." TextWrapping="Wrap"/>
            </StackPanel>

        </DockPanel>
    </DockPanel>
</Window>

Đã sửa lỗi định dạng - không giống như chuyển thẳng từ danh sách sang mã
Greg

1
Bạn có thể tự tạo một GroupBox theo cách đó không? Nếu vậy, hãy bắt đầu thêm từng phần tử cha mẹ cho đến khi bạn tìm ra phần tử nào phá vỡ bố cục.
Drew Noakes

RoBorg: rất vui được biết, điều đó đã khiến tôi bối rối, cảm ơn
Edward Tanguay

1
Cảm ơn. Sử dụng câu trả lời của bạn, tôi đã có thể sử dụng 2 DockPanels lồng nhau để giải quyết vấn đề rất giống tôi!
Yablargo

Câu trả lời:


344

Có vẻ như bạn muốn một StackPanelnơi mà phần tử cuối cùng sử dụng hết tất cả không gian còn lại. Nhưng tại sao không sử dụng a DockPanel? Trang trí các yếu tố khác trong DockPanelvới DockPanel.Dock="Top", và sau đó giúp kiểm soát của bạn có thể lấp đầy khoảng trống còn lại.

XAML:

<DockPanel Width="200" Height="200" Background="PowderBlue">
    <TextBlock DockPanel.Dock="Top">Something</TextBlock>
    <TextBlock DockPanel.Dock="Top">Something else</TextBlock>
    <DockPanel
        HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch" 
        Height="Auto" 
        Margin="10">

      <GroupBox 
        DockPanel.Dock="Right" 
        Header="Help" 
        Width="100" 
        Background="Beige" 
        VerticalAlignment="Stretch" 
        VerticalContentAlignment="Stretch" 
        Height="Auto">
        <TextBlock Text="This is the help that is available on the news screen." 
                   TextWrapping="Wrap" />
     </GroupBox>

      <StackPanel DockPanel.Dock="Left" Margin="10" 
           Width="Auto" HorizontalAlignment="Stretch">
          <TextBlock Text="Here is the news that should wrap around." 
                     TextWrapping="Wrap"/>
      </StackPanel>
    </DockPanel>
</DockPanel>

Nếu bạn đang ở trên một nền tảng không DockPanelcó sẵn (ví dụ: WindowsStore), bạn có thể tạo hiệu ứng tương tự với lưới. Đây là ví dụ trên được thực hiện bằng cách sử dụng lưới thay thế:

<Grid Width="200" Height="200" Background="PowderBlue">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0">
        <TextBlock>Something</TextBlock>
        <TextBlock>Something else</TextBlock>
    </StackPanel>
    <Grid Height="Auto" Grid.Row="1" Margin="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        <GroupBox
            Width="100"
            Height="Auto"
            Grid.Column="1"
            Background="Beige"
            Header="Help">
            <TextBlock Text="This is the help that is available on the news screen." 
              TextWrapping="Wrap"/>
        </GroupBox>
        <StackPanel Width="Auto" Margin="10" DockPanel.Dock="Left">
            <TextBlock Text="Here is the news that should wrap around." 
              TextWrapping="Wrap"/>
        </StackPanel>
    </Grid>
</Grid>

18
Xuất sắc! Tôi đã dành một giờ cuối cùng để cố gắng tìm ra cách để StackPanel làm điều này. Từ giờ trở đi, tôi sẽ tìm ở đây trước để biết thông tin về WPF (và những thứ khác).
paxdiablo

7
Tôi không thể tin được mình đã dành bao nhiêu thời gian để cố gắng để StackPanels làm những gì tôi muốn. Cám ơn vì đã chia sẻ! DockPanels là những gì tôi muốn tất cả cùng.
danglund

Có vẻ như không có dockpanel cho máy tính bảng. telerik.com/forums/following-blog-post-and-comparison
JP Hellemons

1
Không có bảng điều khiển dock cho các ứng dụng Windows Store.
Teoman shipahi

Bây giờ tất cả là về ứng dụng phổ quát và ứng dụng phổ quát chưa hỗ trợ DockPanel?
yonexbat

105

Lý do điều này xảy ra là bởi vì bảng ngăn xếp đo lường mọi phần tử con có vô cực dương là ràng buộc cho trục mà nó đang xếp các phần tử dọc theo. Các điều khiển con phải trả về mức độ lớn mà chúng muốn (vô cực dương không phải là lợi nhuận hợp lệ từ Biện pháp đo lường trong cả hai trục) để họ trở lại kích thước nhỏ nhất mà tất cả mọi thứ sẽ phù hợp. Họ không có cách nào để biết họ thực sự phải lấp đầy bao nhiêu không gian.

Nếu chế độ xem của bạn không cần phải có tính năng cuộn và câu trả lời ở trên không phù hợp với nhu cầu của bạn, tôi khuyên bạn nên thực hiện bảng điều khiển của riêng mình. Bạn có thể lấy trực tiếp từ StackPanel và sau đó tất cả những gì bạn cần làm là thay đổi ArrangeOverride phương thức để nó phân chia không gian còn lại giữa các phần tử con của nó (cung cấp cho chúng cùng một không gian thừa). Các phần tử sẽ hiển thị tốt nếu chúng được cung cấp nhiều không gian hơn chúng muốn, nhưng nếu bạn cho chúng ít hơn, bạn sẽ bắt đầu thấy các trục trặc.

Nếu bạn muốn có thể cuộn toàn bộ thì tôi sợ mọi thứ sẽ khó khăn hơn một chút, vì ScrollViewer cung cấp cho bạn một lượng không gian vô hạn để làm việc sẽ đưa bạn vào vị trí giống như các phần tử con ban đầu. Trong tình huống này, bạn có thể muốn tạo một thuộc tính mới trên bảng điều khiển mới cho phép bạn chỉ định kích thước khung nhìn, bạn sẽ có thể liên kết nó với kích thước của ScrollViewer. Lý tưởng nhất là bạn sẽ triển khai IScrollInfo , nhưng điều đó bắt đầu trở nên phức tạp nếu bạn thực hiện đúng tất cả.


+1, tôi sẽ cung cấp cho bạn nhiều hơn nhưng chỉ được phép 1, đoạn đầu tiên của bạn đã chỉ ra rất nhiều trang Microsoft đã thất bại, cụ thể là tại sao vô cực có thể xảy ra như chiều cao / chiều rộng và thực tế là bạn không thể dựa vào việc trả lại kích thước có sẵn từ Đo lường .
Aidan

Một StackPanel bên trong Grid giải quyết nhu cầu khá phổ biến của anh ấy rất dễ dàng. Bit dưới cùng có thể được đặt bên trong ScrollViewer, nếu cần. Tôi đã làm WPF từ năm 2006 và chỉ cần một lần để làm bảng điều khiển tùy chỉnh. Tôi không nghĩ rằng đó là một ý tưởng tốt để khuyến khích sự phức tạp thêm.
Chris Bordeman

@ChrisBordeman Tôi không chắc tôi hiểu cách bảng ngăn xếp bên trong lưới giải quyết vấn đề. Ý tưởng là có một hoặc nhiều phần tử con trong bảng ngăn xếp kéo dài để lấp đầy không gian có sẵn. Đặt bảng ngăn xếp bên trong một lưới không làm cho nó làm điều đó phải không?
Caleb Vear

61

Một phương pháp khác là sử dụng Lưới có một cột và n hàng. Đặt tất cả các chiều cao hàng thành Autovà chiều cao hàng dưới cùng nhất thành 1*.

Tôi thích phương pháp này vì tôi thấy Lưới có hiệu suất bố trí tốt hơn DockPanels, StackPanels và WrapPanels. Nhưng trừ khi bạn đang sử dụng chúng trong ItemTemplate (nơi bố trí đang được thực hiện cho một số lượng lớn các mục), bạn có thể sẽ không bao giờ nhận thấy.


1
cho tôi giải pháp tốt nhất với điều này, có thể định nghĩa nhiều hơn một hàng đang phát triển
niyou

18

Bạn có thể sử dụng SpicyTaco.AutoGrid - phiên bản sửa đổi của StackPanel:

<st:StackPanel Orientation="Horizontal" MarginBetweenChildren="10" Margin="10">
   <Button Content="Info" HorizontalAlignment="Left" st:StackPanel.Fill="Fill"/>
   <Button Content="Cancel"/>
   <Button Content="Save"/>
</st:StackPanel>

Nút đầu tiên sẽ được điền.

Bạn có thể cài đặt nó qua NuGet:

Install-Package SpicyTaco.AutoGrid

Tôi khuyên bạn nên xem SpicyTaco.AutoGrid . Nó rất hữu ích cho các hình thức trong WPF thay vì DockPanel, StackPanelGridvà giải quyết vấn đề với kéo dài rất dễ dàng và duyên dáng. Chỉ cần nhìn vào readme trên GitHub.

<st:AutoGrid Columns="160,*" ChildMargin="3">
    <Label Content="Name:"/>
    <TextBox/>

    <Label Content="E-Mail:"/>
    <TextBox/>

    <Label Content="Comment:"/>
    <TextBox/>
</st:AutoGrid>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.