在几个小时内一直在努力解决这个看似简单的问题。
我有一个主窗口,在该窗口内是一个包含制表符控件的画布。选项卡控件包含各种用户控件。当用户控件是全尺寸时(窗口必须是固定尺寸),用户控件就可以很好地适应窗口。但是,其中一台机器运行的分辨率低于主窗口大小。所以我在主窗口后面的代码中放置了一个maxheight,只调整到显示器的最大高度/宽度。
public MainWindow()
{
InitializeComponent();
this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight - 20;
this.MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
...
所以现在主窗口只有屏幕大(减去任务栏的大小)。这很好。但是,我似乎无法使任何滚动条出现在正确的范围内(这是整个窗口)。因此,当分辨率太小时,我想要一个不大于屏幕的窗口,它有滚动条滚动整个内容。
我尝试在多个级别放置Scrollviewer,但即使我可以显示滚动条,我也永远无法启用它们。我认为这是因为主窗口的内容都没有太大,我只是看不到它导致窗口大小更小(因为每个内容项完全适合它的父级)。
那么,如何让窗口滚动所有内容呢?我试过启用Horizontal&在窗口xaml中垂直滚动并包围画布。我也尝试用滚动浏览器包围窗口(这不起作用)。
我在xaml或codebehind中缺少什么。
P.S。 - 我已经取出了所有我一直在搞乱的scrollViewer引用,万一我的笨蛋让别人感到困惑。
<Window x:Class="myWin.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:usercontrols="myControls"
Title="PCU ATS" Height="985" Width="1280" Left="0" Top="0" Background="#FFAE4949" ResizeMode="NoResize">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{Binding CloseCmd}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Canvas Background="CadetBlue">
<TextBlock x:Name ="debugBlock" Canvas.Left="1030" TextWrapping="Wrap" Text="" Canvas.Top="4" Width="91"/>
<Button x:Name= "btnLogIn" Content="Access Debug" Command="{Binding LoginCmd}" VerticalAlignment="Top" Height="23" Background="Maroon" Foreground="White" BorderBrush="#FF060303" Canvas.Left="1126" Width="79" />
<TabControl Canvas.Left="0" Canvas.Top="0" Height="946" Name="mainTabControl" Width="1264" Padding="0" ScrollViewer.CanContentScroll="True" >
<TabItem Header="Test Description" Name="testTab" FontWeight="Bold">
<Grid Background="LightSteelBlue">
<usercontrols:testDescEntry x:Name="userControl1" Loaded="testUserControl_Loaded" ScrollViewer.CanContentScroll="True" Margin="0,0,0.5,0" />
</Grid>
</TabItem>
<TabItem Header="Start Test" Name="sTab" FontWeight="Bold" ScrollViewer.CanContentScroll="True">
<Grid Background="LightSteelBlue" ScrollViewer.CanContentScroll="True">
<usercontrols:StartCon x:Name="userControl2" ScrollViewer.CanContentScroll="True"/>
</Grid>
</TabItem>
<TabItem Header="Manual Debug" Name="mainDTab" FontWeight="Bold" Visibility="Hidden">
<Canvas Background="DarkOrange" >
<TabControl Canvas.Left="0" Canvas.Top="0" Height="922" Name="debugControl" Width="1262" Padding="0">
<TabItem Header="debug3" Name="debug1Tab" FontWeight="Bold">
<Grid Background="LightSteelBlue">
<usercontrols:debug3 x:Name="Control1" ScrollViewer.CanContentScroll="True" />
</Grid>
</TabItem>
<TabItem Header="Name1" Name="debug2Tab" FontWeight="Bold">
<Grid Background="LightSteelBlue">
<usercontrols:debug4 x:Name="Control2" ScrollViewer.CanContentScroll="True" />
</Grid>
</TabItem>
<TabItem Header="Nam2" Name="debug3Tab" FontWeight="Bold">
<Grid Background="LightSteelBlue">
<usercontrols:Name3 x:Name="Control3" ScrollViewer.CanContentScroll="True" />
</Grid>
</TabItem>
</TabControl>
</Canvas>
</TabItem>
</TabControl>
</Canvas>
答案 0 :(得分:1)
我的建议是:不要使用Canvas
。在WPF中,与Windows Forms不同,强烈建议不要对UI元素进行绝对定位。这是因为当你这样做时,你禁用了WPF动态重新定位项目的能力,这是很多WPF布局功能所依据的。
基本上,当你使用Canvas
时,你告诉WPF只是给你一个画空间而不用担心它。如果您没有指定大小,WPF将不知道您的Canvas
有多大,因此无法确定滚动条是否应该可见。这可以通过为Canvas
提供固定大小并使用ScrollViewer
来解决。像这样:
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas Background="CadetBlue" Width="1500" Height="1000">
<!-- your canvas content -->
</Canvas>
</ScrollViewer>
但是,我强烈建议不要这样做。如果窗口大小发生变化或某人有不同的屏幕分辨率,该怎么办?您可以使用其他WPF容器以更好,更灵活的方式实现布局。下面是一个示例(我删除了一堆对布局没有影响的东西):
<Grid Background="CadetBlue">
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Right"
Margin="0,0,20,0" Orientation="Horizontal">
<TextBlock x:Name ="debugBlock" Margin="0,0,20,0"/>
<Button x:Name="btnLogIn" Content="Access Debug" Height="23""/>
</StackPanel>
<TabControl Name="mainTabControl" Padding="0">
<TabItem Header="Test Description">
<Border Background="LightSteelBlue">
</Border>
</TabItem>
<TabItem Header="Start Test">
<Border Background="LightSteelBlue">
</Border>
</TabItem>
<TabItem Header="Manual Debug">
<Border Background="DarkOrange" >
<TabControl Padding="0">
<TabItem Header="debug3">
<Border Background="LightSteelBlue">
</Border>
</TabItem>
<TabItem Header="Name1">
<Border Background="LightSteelBlue">
</Border>
</TabItem>
<TabItem Header="Nam2">
<Border Background="LightSteelBlue">
</Border>
</TabItem>
</TabControl>
</Border>
</TabItem>
</TabControl>
</Grid>
对于标签内容的背景,我使用了Border
,因为它比Grid
更轻一些。但是你可以使用它们。
使用这种方法,当屏幕本身调整大小时,一切都应该很好地调整大小。你可以看到,它实现了与画布基本相同的布局,同时更加简单。
如果您想使用ScrollViewer
,请注意内部必须有固定大小的内容。
TL; DR不要使用Canvas
,不要给出元素的绝对大小和位置。使用StackPanel
,Grid
或除Canvas
以外的任何面板,在其中放置元素,然后使用Margin
或Padding
微调位置。
答案 1 :(得分:0)
在画布上方添加ScrollViewer,并根据控件设置其高度和宽度。我做了一个工作..
将scrollViewer设为
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Canvas Name="canvas1" Background="CadetBlue">
....
....
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
autoSizeCanvas(canvas1);
}
void autoSizeCanvas(Canvas canv)
{
int height = canv.Height;
int width = canv.Width;
foreach (UIElement ctrl in canv.Children)
{
bool nullTop = ctrl.GetValue(Canvas.TopProperty) == null || Double.IsNaN(Convert.ToDouble(ctrl.GetValue(Canvas.TopProperty))),
nullLeft = ctrl.GetValue(Canvas.LeftProperty) == null || Double.IsNaN(Convert.ToDouble(ctrl.GetValue(Canvas.LeftProperty)));
int curControlMaxY = (nullTop ? 0 : Convert.ToInt32(ctrl.GetValue(Canvas.TopProperty))) +
Convert.ToInt32(ctrl.GetValue(Canvas.ActualHeightProperty)
),
curControlMaxX = (nullLeft ? 0 : Convert.ToInt32(ctrl.GetValue(Canvas.LeftProperty))) +
Convert.ToInt32(ctrl.GetValue(Canvas.ActualWidthProperty)
);
height = height < curControlMaxY ? curControlMaxY : height;
width = width < curControlMaxX ? curControlMaxX : width;
}
canv.Height = height;
canv.Width = width;
}
仅在Loaded事件或更高版本中使用该函数,而不是在构造函数中使用。必须在装载前测量窗口..