Scrollviewer doesnt show data when its beyond parent window in wpf

☆樱花仙子☆ 提交于 2019-12-12 04:56:08

问题


There are some 6 contentcontrols within a single grid with 6 expanders(each contentcontrol in one expander) on my mainwindow which calls various usercontrols to fill the mainwindow for each upper tab/left menu selection.

One expander would be active at a time and rest would be collapsed.

Each new window would be on a contentcontrol.

The problem was when i have larger data thats loading dynamically my content exceeds beyond the parent control and even when i use scrollviewer ,scrollviewer shows up but data is cut off.

Here is my code: Following is my Code in UserControl that was used in contentcontrol of mainwindow

<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>

Second grid with 6 rows was code in my MainWindow.

<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>

Similarly there are five expander rows with contentcontrol2,..in each of them.

The problem was when my contentcontrol has max dynamic content that exceeds parent size ,data is cut off and scrollviewer shows up but still doesnt show complete data. When i remove the scrollviewer height and keep scrollviewer height to "Auto", scrollviewer doesnt show up at all.


回答1:


Nicholas' answer is correct that your problem is how you're defining the RowDefinition of the Grid.

Auto means "allow children to grow to any size they want", so your ScrollViewer is growing to up to 800px high (because of the MaxHeight), which is off the screen.

The standard solution for this kind of thing is to use a Converter in the RowHeight to set it to either Auto or "*" ("allow child to take up all remaining space") based on the Expander.IsExpanded state.

This means if the Expander is collapsed, it will take up whatever space it needs, but if it's expanded it will take up all remaining space (and no more than that).

<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>

If more than one item is expanded, they should split the remaining space evenly because they both share a size of "1*", so would get allocated an equal amount of space.

Creating a converter is simple. Create a class that inherits from IValueConverter, implement the interface, and alter the Convert method to convert the bool value (IsExpanded) to a GridLength value for the RowHeight.

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
    }
}

Then add an instance of this converter to your XAML Resources somewhere, such as

<Window.Resources>
    <local:BoolToGridSizeConverter x:Key="MyBoolToGridSizeConverter" />
</Window.Resources>

Of course, the other alternative is to google for a free WPF Accordion control, such as the one in the WPF Toolkit :)




回答2:


The problem here is that by setting all the heights of your Grid's rows to "Auto", you end up with a StackPanel. And so no cell is forced to a smaller height than the height it needs, and so ScrollViewer is useless.

The height of the expanded expander row must be "*". Think of it as "Each expander takes the height it needs, except the active one who takes all the remaining".

Maybe something like that :

<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 if true, else GridLength.Auto.



来源:https://stackoverflow.com/questions/28548534/scrollviewer-doesnt-show-data-when-its-beyond-parent-window-in-wpf

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!