如果Windows显示屏上的分辨率太低,则启用Scrollviewer

时间:2015-03-17 23:58:59

标签: c# wpf

在几个小时内一直在努力解决这个看似简单的问题。

我有一个主窗口,在该窗口内是一个包含制表符控件的画布。选项卡控件包含各种用户控件。当用户控件是全尺寸时(窗口必须是固定尺寸),用户控件就可以很好地适应窗口。但是,其中一台机器运行的分辨率低于主窗口大小。所以我在主窗口后面的代码中放置了一个maxheight,只调整到显示器的最大高度/宽度。

 public MainWindow()
    {
        InitializeComponent();

        this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight - 20;
        this.MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
...

所以现在主窗口只有屏幕大(减去任务栏的大小)。这很好。但是,我似乎无法使任何滚动条出现在正确的范围内(这是整个窗口)。因此,当分辨率太小时,我想要一个不大于屏幕的窗口,它有滚动条滚动整个内容。

我尝试在多个级别放置Scrollviewer,但即使我可以显示滚动条,我也永远无法启用它们。我认为这是因为主窗口的内容都没有太大,我只是看不到它导致窗口大小更小(因为每个内容项完全适合它的父级)。

那么,如何让窗口滚动所有内容呢?我试过启用Horizo​​ntal&在窗口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>

2 个答案:

答案 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,不要给出元素的绝对大小和位置。使用StackPanelGrid或除Canvas以外的任何面板,在其中放置元素,然后使用MarginPadding微调位置。

答案 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事件或更高版本中使用该函数,而不是在构造函数中使用。必须在装载前测量窗口..