WPF崩溃控制问题 - ListBox未调整大小

时间:2018-01-01 11:07:37

标签: c# wpf xaml

我的主窗口中有一个带有水平网格分割器的网格。在上半部分是普通的ListBox,在下半部分是一个用户控件,其中包含ScrollViewerTextBox

用户可以通过菜单切换下控制的可见性。然后将较低控件的Visibility设置为Collapse(与网格分割器一样)。如果控件没有调整大小但是如果用户拖动网格分割器调整下部控件的大小并切换下控件,那么ListBox会卡在最后一个高度并且不会延伸到底部窗口(见截图)。

Xaml中的所有组件都设置为VerticalAlignment="Stretch",所以我认为ListBox应该在较低的控件再次折叠后伸展到底部。为了让这个工作起作用,我需要注意什么?

screenshot

代码:

MainWindow.xaml

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Menu x:Name="mainMenu" IsMainMenu="True" Grid.Column="0" Grid.Row="0" Padding="2">
            <MenuItem Header="_File">
                <MenuItem Header="_Add Game..." x:Name="menuItemAddGame" Uid="addGame" Click="OnMainMenuItemClick" />
                <MenuItem Header="_Settings..." x:Name="menuItemSettings" Uid="settings" Click="OnMainMenuItemClick" />
                <Separator />
                <MenuItem Header="_Exit" x:Name="menuItemExit" Uid="exit" Click="OnMainMenuItemClick" />
            </MenuItem>
            <MenuItem Header="_View">
                <MenuItem Header="_Games Details" x:Name="menuItemViewModeDetails" Uid="viewModeDetails" IsCheckable="True" Click="OnMainMenuItemClick" />
                <MenuItem Header="_Games List" x:Name="menuItemViewModeList" Uid="viewModeList" IsCheckable="True" Click="OnMainMenuItemClick" />
                <MenuItem Header="_Games Grid" x:Name="menuItemViewModeGrid" Uid="viewModeGrid" IsCheckable="True" Click="OnMainMenuItemClick" />
                <Separator />
                <MenuItem Header="_Log" x:Name="menuItemShowLog" Uid="showLog" IsCheckable="True" Click="OnMainMenuItemClick" />
            </MenuItem>
            <MenuItem Header="_Help">
                <MenuItem Header="_Website" x:Name="menuItemWebsite" Uid="website" Click="OnMainMenuItemClick" />
                <MenuItem Header="_Check for Updates" x:Name="menuItemCheckUpdate" Uid="checkUpdate" Click="OnMainMenuItemClick" />
                <Separator />
                <MenuItem Header="_About..." x:Name="menuItemAbout" Uid="about" Click="OnMainMenuItemClick" />
            </MenuItem>
        </Menu>

        <ToolBarPanel Grid.Column="0" Grid.Row="1" MinHeight="30">
            <ToolBar x:Name="toolBar" HorizontalAlignment="Stretch" Height="30"/>
        </ToolBarPanel>

        <Grid Grid.Column="0" Grid.Row="2" VerticalAlignment="Stretch">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="250"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                <ListBoxItem>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
                        <TextBlock>ListBox Item #1</TextBlock>
                    </StackPanel>
                </ListBoxItem>
                <ListBoxItem>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock>ListBox Item #2</TextBlock>
                    </StackPanel>
                </ListBoxItem>
                <ListBoxItem>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock>ListBox Item #3</TextBlock>
                    </StackPanel>
                </ListBoxItem>
            </ListBox>

            <GridSplitter Focusable="False" HorizontalAlignment="Right" VerticalAlignment="Stretch" Grid.Column="1" ResizeBehavior="PreviousAndNext" Width="4" Background="#EEEEEE"/>
            <Label Content="Right" Grid.Column="2" />
        </Grid>

        <GridSplitter x:Name="gridSplitterV" Focusable="False" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Row="3" ResizeBehavior="PreviousAndNext" Height="4" Background="#EEEEEE" Visibility="Collapsed"/>

        <sirius:LogView x:Name="logView" Grid.Column="0" Grid.Row="4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="Collapsed" MinHeight="20"/>

        <StatusBar x:Name="statusBar" Grid.Column="0" Grid.Row="5" Padding="2">
            <StatusBarItem>
                <TextBlock x:Name="statusBarTextBlock" Text="Ready." />
            </StatusBarItem>
        </StatusBar>

    </Grid>

</Window>

LogView.xaml

<UserControl x:Class="Sirius.LogView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="200" d:DesignWidth="640">
    <Grid>
        <ScrollViewer x:Name="scrollViewer" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch">
            <TextBox x:Name="textBox" IsReadOnly="True" TextWrapping="Wrap" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch"/>
        </ScrollViewer>
    </Grid>
</UserControl>

MainWindow.xaml.cs 中,我有这个方法来切换LogView:

public void ToggleLogView()
{
    if (logView.Visibility == Visibility.Collapsed)
    {
        gridSplitterV.Visibility = Visibility.Visible;
        logView.Visibility = Visibility.Visible;
        logView.Enabled = true;
        menuItemShowLog.IsChecked = true;
    }
    else
    {
        logView.Enabled = false;
        gridSplitterV.Visibility = Visibility.Collapsed;
        logView.Visibility = Visibility.Collapsed;
        menuItemShowLog.IsChecked = false;
    }
}

1 个答案:

答案 0 :(得分:2)

我之前遇到过这种情况。一致地工作的简单解决方案是在拆分器和另一行折叠时将仍然可见的行内容的行跨度设置为3。

因此,请为该行的内容命名:

<Grid 
    x:Name="ListBoxGrid"
    Grid.Column="0" 
    Grid.Row="2" 
    VerticalAlignment="Stretch" 
    >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="250"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>

...并在代码中设置rowspan:

    public void ToggleLogView()
    {
        if (logView.Visibility == Visibility.Collapsed)
        {
            gridSplitterV.Visibility = Visibility.Visible;
            logView.Visibility = Visibility.Visible;
            logView.IsEnabled = true;
            menuItemShowLog.IsChecked = true;

            Grid.SetRowSpan(ListBoxGrid, 1);
        }
        else
        {
            logView.IsEnabled = false;
            gridSplitterV.Visibility = Visibility.Collapsed;
            logView.Visibility = Visibility.Collapsed;
            menuItemShowLog.IsChecked = false;

            Grid.SetRowSpan(ListBoxGrid, 3);
        }
    }

我会毫不吝啬地告诉你MVVM,因为这是仅限查看的代码,但是你在ToggleLogView中所做的一切,加上我的补充,都可以非常直接地在XAML中完成。

我有另一个选项适用于我的简化测试XAML,但不适用于OP的完整布局:命名* RowDefinition并在隐藏日志视图行时将其高度设置为GridLength(1, GridUnit.Star);。我没有调查OP的XAML失败的原因。

更新

纯XAML版本。菜单项将自动切换其IsChecked状态,因为您在其上设置了IsCheckable="True",因此可以完全省略该菜单项上的单击处理程序。 BooleanToVisibilityConverter位于System.Windows.Controls。无需编写自己的转换器。如果需要,您可以为行跨度编写转换器,并避免使用详细的样式。

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVis" />
</Window.Resources>

<!-- ...snip... -->

            <MenuItem Header="_Log" x:Name="menuItemShowLog" Uid="showLog" IsCheckable="True" />

<!-- ...snip... -->

    <Grid 
        Grid.Column="0" 
        Grid.Row="2" 
        VerticalAlignment="Stretch" 
        x:Name="ListBoxGrid"
        >
        <Grid.Style>
            <Style TargetType="Grid">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsChecked, ElementName=menuItemShowLog}" Value="False">
                        <Setter Property="Grid.RowSpan" Value="3" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>

         <!-- ...snip... -->

    </Grid>

    <GridSplitter 
        Visibility="{Binding IsChecked, ElementName=menuItemShowLog, Converter={StaticResource BoolToVis}}"
        ...
        />

    <sirius:LogView 
        Visibility="{Binding IsChecked, ElementName=menuItemShowLog, Converter={StaticResource BoolToVis}}"
        ...
        />