使 WrapPanel 尊重其父级的宽度

发布于 2024-11-17 17:20:37 字数 2268 浏览 3 评论 0原文

好的,这是我的代码。请注意,StackPanel 直接位于 UserControl 中。

<UserControl>
    <StackPanel Orientation="Horizontal">

        <ScrollViewer Width="450"
                      VerticalScrollBarVisibility="Auto"
                      HorizontalScrollBarVisibility="Disabled">

            <Rectangle Width="400" Height="4000" Fill="BlanchedAlmond"/>
        </ScrollViewer>

        <ScrollViewer VerticalScrollBarVisibility="Auto"
                      HorizontalScrollBarVisibility="Disabled">

            <ItemsControl BorderBrush="Green"
                          BorderThickness="2"
                          ItemsSource="{Binding Path=MyObservableCollection}"
                          ItemTemplate="{StaticResource FatTemplate}">

                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

            </ItemsControl>
        </ScrollViewer>

    </StackPanel>
</UserControl>

代码已编辑

请注意,矩形就在那里,因为滚动查看器的内容无关。

问题是 WrapPanel 只是水平扩展并且不换行...

我找到了一些解决方案:

  1. 为 WrapPanel 提供绝对宽度(但随后它不会随窗口调整大小)。

  2. 将宽度绑定到其父宽度 - ItemsControl 或 ScrollViewer(ScrollViewer 在像这样的有限情况下效果更好)。

    Width="{绑定RelativeSource=
        {相对源查找祖先,
        AncestorType={x:Type ScrollViewer}},
        路径=实际宽度}”
    

此技术的问题在于,如果 StackPanel 或 Grid 中某个控件位于其旁边,则需要将其绑定到其父级大小减去其旁边的控件的大小。然后是困难的事情。我构建了一个转换器,它对收到的数字应用数学运算,这样我就可以从其父宽度中减去给定的宽度:

Width="{Binding RelativeSource=
    {RelativeSource FindAncestor,
    AncestorType={x:Type UserControl}},
    Path=ActualWidth,
    Converter={StaticResource Convertisseur_Size_WXYZ}, 
    ConverterParameter=-260}"

但是,由于您无法将传递给 ConverterParameter 的值绑定,

ConverterParameter={Binding ...} (doesn't work)

我希望:

  • 能够调整我的大小我的 WrapPanel 和 ScrollViewer 大小调整得很好,
  • 我的 UserControl 易于维护,
  • 我的代码比这些依赖于父控件类型的大绑定表达式更干净。

什么是更好的解决方案?

注意:如果有任何不清楚的地方,我可以添加详细信息。

Ok here's my code. Note that the StackPanel is directly in a UserControl.

<UserControl>
    <StackPanel Orientation="Horizontal">

        <ScrollViewer Width="450"
                      VerticalScrollBarVisibility="Auto"
                      HorizontalScrollBarVisibility="Disabled">

            <Rectangle Width="400" Height="4000" Fill="BlanchedAlmond"/>
        </ScrollViewer>

        <ScrollViewer VerticalScrollBarVisibility="Auto"
                      HorizontalScrollBarVisibility="Disabled">

            <ItemsControl BorderBrush="Green"
                          BorderThickness="2"
                          ItemsSource="{Binding Path=MyObservableCollection}"
                          ItemTemplate="{StaticResource FatTemplate}">

                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

            </ItemsControl>
        </ScrollViewer>

    </StackPanel>
</UserControl>

(Code EDITED)

Note that the rectangle is just there because the content of that scroll viewer is irrelevant.

The problem is that the WrapPanel just expands horizontally and doesn't wrap...

I found a few solutions:

  1. Giving absolute width to the WrapPanel (but then it doesn't resize with the window).

  2. Binding width to its parent width - either ItemsControl or ScrollViewer (ScrollViewer worked better in a limited situation like this one).

    Width="{Binding RelativeSource=
        {RelativeSource FindAncestor,
        AncestorType={x:Type ScrollViewer}},
        Path=ActualWidth}"
    

The problem with this technique is that if a control is beside it in a StackPanel or Grid, you need to bind it to it's parent size minus the control next to it. Then comes the hard stuff. I built a converter which applies mathematical operations on the number received so I could subtract a given width from its parent width:

Width="{Binding RelativeSource=
    {RelativeSource FindAncestor,
    AncestorType={x:Type UserControl}},
    Path=ActualWidth,
    Converter={StaticResource Convertisseur_Size_WXYZ}, 
    ConverterParameter=-260}"

But still, since you can't bind a value you pass to a ConverterParameter,

ConverterParameter={Binding ...} (doesn't work)

I want:

  • to be able to resize my app with my WrapPanel and ScrollViewer resizing well,
  • my UserControl to be easily maintainable,
  • my code cleaner than these big binding expressions which rely on parent control's Type.

What's a better solution?

Note: If anything isn't clear, I can add detail.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟雨凡馨 2024-11-24 17:20:37

ScrollViewer 允许水平滚动时,为什么它会换行?您应该在 ScrollViewer 中禁用水平滚动:

<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">

编辑后编辑:这是因为您的 StackPanel 是水平方向的。水平方向的 StackPanel 将为其子级提供其请求的任何宽度 - 它根本不会限制它。使用正确的面板,一切都会好起来的。可能您只需要一个包含两列的Grid

Why would it wrap when the ScrollViewer allows horizontal scrolling? You should disable horizontal scrolling in the ScrollViewer:

<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">

EDIT AFTER YOUR EDIT: It's because your StackPanel is oriented horizontally. A horizontally-oriented StackPanel will give whatever width its child requests to it - it won't constrain it at all. Use the right panel, and you'll be fine. Likely you just want a Grid with two columns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文