Scrollviewer 在 wpf 中超出父 window 时不显示数据
Scrollviewer doesnt show data when its beyond parent window in wpf
在一个带有 6 个扩展器的网格中有大约 6 个内容控件(每个内容控件在一个扩展器中)
在我的 mainwindow 上,它调用各种用户控件来为每个上层 tab/left 菜单选择填充 mainwindow。
一次将激活一个扩展器,其余的将折叠起来。
每个新的 window 都会在一个内容控件上。
问题是当我有更大的动态加载数据时,我的内容超出了父控件,并且
即使我使用 scrollviewer 时,scrollviewer 也会出现,但数据会被切断。
这是我的代码:
以下是我在 mainwindow
的 contentcontrol 中使用的 UserControl 中的代码
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Expander Header="Settings" BorderBrush="SteelBlue" BorderThickness="5"
IsExpanded="{Binding Path=ShowPreview, Mode=TwoWay}"
Background="AliceBlue" FontFamily="Poor Richard" FontSize="24"
FontWeight="Bold">
<DatePicker Name="MyDateRange" />
</Expander>
<Expander Header="Permissions" Grid.Row="1" BorderBrush="SteelBlue"
BorderThickness="5" Background="AliceBlue" FontFamily="Poor Richard"
<local:Permissions />
<!--/*Permissions is another usercontrol with a grid layout (a dataentry form)*/-->
</Expander>
</Grid>
6 行的第二个网格是我主窗口中的代码。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Expander Grid.Row="1" IsExpanded="False" x:Name="Expander1"
Style="{DynamicResource OutlookStyleExpanderStyle}" Visibility="Hidden">
<Expander.Header>
<WrapPanel HorizontalAlignment="Right" Margin="450,0,0,0">
<Button Name="ExpandButtonMin" Background="#FFACD0EE"
Click="ExpandButtonMin_Click" HorizontalAlignment="Right">
<Image Source="/Images/Minimize_Box_Blue.png" Height="30" Width="30" />
</Button>
<Button Name="ExpandButtonMax" Background="#FFACD0EE"
Click="ExpandButtonMax_Click" HorizontalAlignment="Right">
<Image Source="/Images/maximize.png" Height="30" Width="30" />
</Button>
<Button Name="ExpandButtonClose" Background="#FFACD0EE"
Click="ExpandButton1_Click" HorizontalAlignment="Right">
<Image Source="/Images/Close_Box_Red.png" Height="30" Width="30" />
</Button>
</WrapPanel>
</Expander.Header>
<ScrollViewer MaxHeight="800">
<ContentControl Grid.Row="1" x:Name="contentControl1"
Content="{Binding ContentControlOne}" Margin="0,0,0,0"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
</ScrollViewer>
</Expander>
</Grid>
类似地,有 5 个带有 contentcontrol2 的扩展器行,..在每个行中。
问题是当我的内容控件具有超过父级大小的最大动态内容时,数据被切断并且显示滚动查看器但仍未显示完整数据。当我删除 scrollviewer 高度并将 scrollviewer 高度保持为 "Auto" 时,scrollviewer 根本不显示。
这里的问题是,通过将 Grid
的所有行的高度设置为 "Auto",您最终会得到 StackPanel
。因此,没有单元格被强制设置为比它需要的高度更小的高度,因此 ScrollViewer
是无用的。
展开的扩展器行的高度必须为“*”。将其视为 "Each expander takes the height it needs, except the active one who takes all the remaining".
也许是这样的:
<Grid>
<Expander x:Name="Expander1" ... />
<Expander x:Name="Expander2" ... />
<Expander x:Name="Expander3" ... />
...
<Grid.RowDefinitions>
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander1, Converter={x:Static BoolToRowHeightConverter.Instance}}"/>
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander2, Converter={x:Static BoolToRowHeightConverter.Instance}}"/>
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander3, Converter={x:Static BoolToRowHeightConverter.Instance}}"/>
...
</Grid.RowDefinitions>
</Grid>
BoolToRowHeightConverter
returns GridLength.Star
如果为真,否则 GridLength.Auto
.
你的问题是你如何定义网格的 RowDefinition。
Auto
表示 "allow children to grow to any size they want",因此您的 ScrollViewer 会增长到 800px 高(因为 MaxHeight
),它超出了屏幕。
这种事情的标准解决方案是在 RowHeight
中使用转换器将其设置为 Auto
或 "*"
("allow child to take up all remaining space") 基于Expander.IsExpanded
状态。
这意味着如果 Expander 折叠,它会占用任何 space 它需要的东西,但如果它展开,它将占用所有剩余的 space(仅此而已)。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander1, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander2, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander3, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander4, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander5, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander6, Converter={x:Static MyBoolToGridSizeConverter}}" />
</Grid.RowDefinitions>
<Expander Grid.Row="0" x:Name="Expander1">
<ScrollViewer>
<ContentControl x:Name="contentControl1" Content="{Binding ContentControlOne}" />
</ScrollViewer>
</Expander>
...
</Grid>
如果扩展了多个项目,它们应该平均分配剩余的 space,因为它们共享 "1*"
的大小,因此会分配等量的 space .
创建转换器很简单。创建一个继承自IValueConverter
的class,实现接口,修改Convert
方法,将bool值(IsExpanded
)转换为GridLength
值行高。
public class BoolToGridSizeConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
if (value is bool && (bool)value)
return new GridLength(1, GridUnitType.Star);
return GridLength.Auto;
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
// this is not needed
}
}
然后将此转换器的一个实例添加到您的 XAML 某处的资源中,例如
<Window.Resources>
<local:BoolToGridSizeConverter x:Key="MyBoolToGridSizeConverter" />
</Window.Resources>
当然,另一种选择是google一个免费的WPF手风琴控件,例如WPF Toolkit :)
在一个带有 6 个扩展器的网格中有大约 6 个内容控件(每个内容控件在一个扩展器中) 在我的 mainwindow 上,它调用各种用户控件来为每个上层 tab/left 菜单选择填充 mainwindow。
一次将激活一个扩展器,其余的将折叠起来。
每个新的 window 都会在一个内容控件上。
问题是当我有更大的动态加载数据时,我的内容超出了父控件,并且 即使我使用 scrollviewer 时,scrollviewer 也会出现,但数据会被切断。
这是我的代码: 以下是我在 mainwindow
的 contentcontrol 中使用的 UserControl 中的代码<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Expander Header="Settings" BorderBrush="SteelBlue" BorderThickness="5"
IsExpanded="{Binding Path=ShowPreview, Mode=TwoWay}"
Background="AliceBlue" FontFamily="Poor Richard" FontSize="24"
FontWeight="Bold">
<DatePicker Name="MyDateRange" />
</Expander>
<Expander Header="Permissions" Grid.Row="1" BorderBrush="SteelBlue"
BorderThickness="5" Background="AliceBlue" FontFamily="Poor Richard"
<local:Permissions />
<!--/*Permissions is another usercontrol with a grid layout (a dataentry form)*/-->
</Expander>
</Grid>
6 行的第二个网格是我主窗口中的代码。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Expander Grid.Row="1" IsExpanded="False" x:Name="Expander1"
Style="{DynamicResource OutlookStyleExpanderStyle}" Visibility="Hidden">
<Expander.Header>
<WrapPanel HorizontalAlignment="Right" Margin="450,0,0,0">
<Button Name="ExpandButtonMin" Background="#FFACD0EE"
Click="ExpandButtonMin_Click" HorizontalAlignment="Right">
<Image Source="/Images/Minimize_Box_Blue.png" Height="30" Width="30" />
</Button>
<Button Name="ExpandButtonMax" Background="#FFACD0EE"
Click="ExpandButtonMax_Click" HorizontalAlignment="Right">
<Image Source="/Images/maximize.png" Height="30" Width="30" />
</Button>
<Button Name="ExpandButtonClose" Background="#FFACD0EE"
Click="ExpandButton1_Click" HorizontalAlignment="Right">
<Image Source="/Images/Close_Box_Red.png" Height="30" Width="30" />
</Button>
</WrapPanel>
</Expander.Header>
<ScrollViewer MaxHeight="800">
<ContentControl Grid.Row="1" x:Name="contentControl1"
Content="{Binding ContentControlOne}" Margin="0,0,0,0"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
</ScrollViewer>
</Expander>
</Grid>
类似地,有 5 个带有 contentcontrol2 的扩展器行,..在每个行中。
问题是当我的内容控件具有超过父级大小的最大动态内容时,数据被切断并且显示滚动查看器但仍未显示完整数据。当我删除 scrollviewer 高度并将 scrollviewer 高度保持为 "Auto" 时,scrollviewer 根本不显示。
这里的问题是,通过将 Grid
的所有行的高度设置为 "Auto",您最终会得到 StackPanel
。因此,没有单元格被强制设置为比它需要的高度更小的高度,因此 ScrollViewer
是无用的。
展开的扩展器行的高度必须为“*”。将其视为 "Each expander takes the height it needs, except the active one who takes all the remaining".
也许是这样的:
<Grid>
<Expander x:Name="Expander1" ... />
<Expander x:Name="Expander2" ... />
<Expander x:Name="Expander3" ... />
...
<Grid.RowDefinitions>
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander1, Converter={x:Static BoolToRowHeightConverter.Instance}}"/>
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander2, Converter={x:Static BoolToRowHeightConverter.Instance}}"/>
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander3, Converter={x:Static BoolToRowHeightConverter.Instance}}"/>
...
</Grid.RowDefinitions>
</Grid>
BoolToRowHeightConverter
returns GridLength.Star
如果为真,否则 GridLength.Auto
.
Auto
表示 "allow children to grow to any size they want",因此您的 ScrollViewer 会增长到 800px 高(因为 MaxHeight
),它超出了屏幕。
这种事情的标准解决方案是在 RowHeight
中使用转换器将其设置为 Auto
或 "*"
("allow child to take up all remaining space") 基于Expander.IsExpanded
状态。
这意味着如果 Expander 折叠,它会占用任何 space 它需要的东西,但如果它展开,它将占用所有剩余的 space(仅此而已)。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander1, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander2, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander3, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander4, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander5, Converter={x:Static MyBoolToGridSizeConverter}}" />
<RowDefinition Height="{Binding IsExpanded, ElementName=Expander6, Converter={x:Static MyBoolToGridSizeConverter}}" />
</Grid.RowDefinitions>
<Expander Grid.Row="0" x:Name="Expander1">
<ScrollViewer>
<ContentControl x:Name="contentControl1" Content="{Binding ContentControlOne}" />
</ScrollViewer>
</Expander>
...
</Grid>
如果扩展了多个项目,它们应该平均分配剩余的 space,因为它们共享 "1*"
的大小,因此会分配等量的 space .
创建转换器很简单。创建一个继承自IValueConverter
的class,实现接口,修改Convert
方法,将bool值(IsExpanded
)转换为GridLength
值行高。
public class BoolToGridSizeConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
if (value is bool && (bool)value)
return new GridLength(1, GridUnitType.Star);
return GridLength.Auto;
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
// this is not needed
}
}
然后将此转换器的一个实例添加到您的 XAML 某处的资源中,例如
<Window.Resources>
<local:BoolToGridSizeConverter x:Key="MyBoolToGridSizeConverter" />
</Window.Resources>
当然,另一种选择是google一个免费的WPF手风琴控件,例如WPF Toolkit :)