我有一个简单的WrapPanel
,其中包含许多宽控件。当我调整Width
的{{1}}时,一切都按预期工作。如果有足够的空间,控件将在一行上进行,或者当没有空格时,控件将包含在下一行。
然而,我需要发生的是,如果所有控件基本上都是垂直堆叠的(因为没有更多的水平空间),Window
的{{1}}会更多地减少,出现水平滚动条,以便我可以滚动并查看整个控件。下面是我的xaml。我尝试将Width
包裹在Window
但我无法实现目标。
WrapPanel
因此,如果您将上述ScrollViewer
的{{1}}缩小到最小值,您将无法看到按钮的文字。我希望出现一个水平滚动条,以便我可以滚动查看文本,但不会干扰通常的包装功能。
感谢。
更新
我已经按照下面的Paul的建议,水平滚动条现在按预期显示。但是,我也想要垂直滚动,所以我设置了<Window x:Class="WpfQuotes.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="Auto" Width="600" Foreground="White">
<WrapPanel>
<Button Width="250">1</Button>
<Button Width="250">2</Button>
<Button Width="250">3</Button>
</WrapPanel>
</Window>
。问题是,如果我调整窗口大小以便显示垂直滚动条,即使不需要(也有足够的水平空间来查看整个控件),也会始终显示水平滚动条。好像出现的垂直滚动条会弄乱滚动查看器的宽度。有没有办法纠正这个问题,除非实际需要水平滚动条,否则不会出现?
下面是我的xaml和我在Width
中添加的唯一代码:
Window
VerticalScrollBarVisibility="Auto"
中唯一被覆盖的内容:
CustomWrapPanel
答案 0 :(得分:47)
这就是,如果你要使用一个包装面板,它会做两件事,它会在一个方向上占用尽可能多的可用空间,并在另一个方向上根据需要进行扩展。例如,如果你将它放在一个窗口内,就像你拥有它一样,它会占用尽可能多的水平空间,然后根据需要向下扩展,这就是垂直滚动条可以工作的原因,父容器说“这是我有多宽,但是你可以让自己变得像你想要的一样大“,如果你把它改成水平滚动条,滚动查看器基本上是说”这是你有多高,但你可以像你想要“在这种情况下,包装面板不会换行,因为没有水平约束。
一个可能的解决方案是改变包裹面板从水平到垂直的方向(这可能不是理想或预期的行为):
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<WrapPanel Orientation="Vertical">
<Button Width="250">1</Button>
<Button Width="250">2</Button>
<Button Width="250">3</Button>
</WrapPanel>
</ScrollViewer>
为了获得您期望的行为,您必须做更接近这一点的事情:
<ScrollViewer x:Name="MyScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<WrapPanel MinWidth="250" Width="{Binding ElementName=MyScrollViewer, Path=ViewportWidth}">
<Button Width="250">1</Button>
<Button Width="250">2</Button>
<Button Width="250">3</Button>
</WrapPanel>
</ScrollViewer>
然而,第二个解决方案只有在您已经知道子元素的宽度时才有效,理想情况下您希望将最大宽度设置为最大子项的实际宽度,但为了做到这一点,您需要创建一个从包装面板派生的自定义控件,并自己编写代码以检查它。
答案 1 :(得分:1)
这是我的解决方案:
<Grid Width="475">
<ItemsControl ItemsSource="{Binding Items}"
Height="450" Width="475" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:HorizontalListItemControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
</Grid>
我将尝试解释:
我使用了ItemsControl,它的ItemsSource绑定到我的Items集合。
在其中,我定义了一个WrapPanel作为ItemsPanelTemplate。这就是使包装工作完成的原因。
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
但是现在没有滚动了,对吗?
为了解决这个问题,我在ScrollViewer中定义了ItemsPresenter作为ControlTemplate:
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
现在您可以滚动了。
希望我能帮上忙。
答案 2 :(得分:0)
public bool CheckUIElementInBounary(UIElement element, Rect r)
{
bool inbound = false;
Point p1 = element.PointToScreen(new Point(0, 0));
Point p2 = element.PointToScreen(new Point(0, element.RenderSize.Height));
Point p3 = element.PointToScreen(new Point(element.RenderSize.Width, 0));
Point p4 = element.PointToScreen(new Point(element.RenderSize.Width, element.RenderSize.Height));
if (CheckPoint(p1, r) || CheckPoint(p2, r) || CheckPoint(p3, r) || CheckPoint(p4, r))
{
inbound = true;
}
return inbound;
}
public bool CheckPoint(Point p, Rect bounday)
{
bool inbound = false;
if (p.X >= bounday.Left && p.X <= bounday.Right && p.Y <= bounday.Top && p.Y <= bounday.Bottom)
{
inbound = true;
}
return inbound;
}
===================
void mainViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
foreach (var item in this.mainContent.Items)
{
Button btn = item as Button;
Point p1 = mainViewer.PointToScreen(new Point(0, 0));
Point p2 = mainViewer.PointToScreen(new Point(mainViewer.ActualWidth, mainViewer.ActualHeight));
Rect bounds = new Rect(p1, p2);
if (!CheckUIElementInBounary(btn, bounds))
{
this.Title = btn.Content.ToString();
mainContent.ScrollIntoView(btn);
break;
}
}
}