简体   繁体   中英

WPF Datagrid in ScrollViewer with Dockpanel

I want to make my UI more responsable and right now I have this problem:

<ScrollViewer VerticalScrollBarVisibility="Auto">
    <DockPanel LastChildFill="True">
        <StatusBar HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" DockPanel.Dock="Bottom">
            <StatusBarItem>
                <Ellipse Width="15" Height="15" Fill="{Binding StatusColor}"></Ellipse>
            </StatusBarItem>
            <StatusBarItem>
                <TextBlock Text="{Binding StatusText}" ToolTip="{Binding StatusToolTip}"></TextBlock>
            </StatusBarItem>
            <StatusBarItem HorizontalAlignment="Right">
                <TextBlock Text="{Binding StatusLastAction}"></TextBlock>
            </StatusBarItem>
        </StatusBar>
        <Grid DockPanel.Dock="Bottom" Margin="0,0,0,10">
            //
            // Fields to edid data from MySelectedItem
            //
        </Grid>
        <Grid DockPanel.Dock="Top">
            <DataGrid MinHeight="150" AutoGenerateColumns="True" SelectedItem="{Binding MySelectedItem}" HorizontalAlignment="Stretch" Margin="10,10,10,0" VerticalAlignment="Stretch" ItemsSource="{Binding MyItems}" IsReadOnly="True"/>
        </Grid>
    </DockPanel>
</ScrollViewer>

This works like a charm until the point when the DataGrid gets to many items. The grid doesn't create a own scrollviewer it just uses the full height from the "Main"- ScrollViewer . (see image below - bottom-right)


Look here for wanted UI design (imgur)

black > Window

green > Scrollviewer

red > DataGrid

orange > fields to edit data


top left image (good):

  • there is enough space in the window to show everything
  • the DataGrid (red) fills the available space and has a own scoll viewer if there are to many items to show

top right image (good):

  • there isn't enough space to show all
  • the 'DataGrid' uses the min-height and the ScrollViewer (green) gets visible to show the rest (orange)

bottom left image (bad):

  • there is not enough space to show all
  • the DataGrid doen't use the min-height

bottom right image (bad):

  • there is enough space to show everything
  • the DataGrid uses all needed space to show all Item

Is there a way to design the UI as shown in the top images?

I usually do not create screens so that they have an external scroll, that makes everything else complicated. According to what you illustrated in the image, your DataGrid should have no height greater than the height of the screen.

So what you need to do is set a size for your grid, example: 60%, 70%, 80% of the height of your screen and the rest your other information

In the solution below I leave the DataGrid always with 80% of the height on the screen

XAML

<Window x:Class="MyApp.MainWindow"
        .....
        Title="MainWindow" 
        Name="MainWindowName"
        >

<DataGrid Height="{Binding ActualHeight, ElementName=MainWindowName, Converter={StaticResource PercentConverter}}"
          ScrollViewer.VerticalScrollBarVisibility="Auto" 
          ScrollViewer.HorizontalScrollBarVisibility="Auto" 
          ScrollViewer.CanContentScroll="True" 
          />

Converter Class

public class PercentConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return 0;
        var valor = (int)(int.Parse(value.ToString()) * 0.8); //80% of my Window Height
        return valor;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var valor = (int)(int.Parse(value.ToString()) / 0.8);
        return valor;
    }
}       

I tested with a large number of data generated in a simple loop

ViewModel (My test)

public MainViewModel()
{
    MyItems = new ObservableCollection<MyData>();
    for (var i = 0;i < 1000;i++)
        MyItems.Add(new MyData { Id = i, Name = GenerateNames() });

}

private string GenerateNames()
{
    var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    var n = _random.Next(5, 15);
    return new string(Enumerable.Repeat(chars, n).Select(s => s[_random.Next(s.Length)]).ToArray());
}

resulting in the image below, and whatever the size of the window the DataGrid will be 80% of the height of it

影像01

Edit: if you do not need the external scroll, ie if it is possible to keep everything visible at the same time on the screen the best way is to leave everything with relative position, this way:

<Grid.RowDefinitions>
    <RowDefinition Height="6*"/> // 6* 
    <RowDefinition Height="3*"/>
    <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<!-- 6 *, 3 *, *, Auto, <fixed value> are possible values at row height, 6 and 3 means how much of the ratio I'm adding to them -->

<Grid Grid.Row="0" >
    <DataGrid AutoGenerateColumns="True" 
              SelectedItem="{Binding MySelectedItem}" 
              HorizontalAlignment="Stretch" 
              Margin="10,10,10,0" 
              VerticalAlignment="Stretch" 
              ItemsSource="{Binding MyItems}" 
              IsReadOnly="True"
              ScrollViewer.VerticalScrollBarVisibility="Auto" 
              ScrollViewer.HorizontalScrollBarVisibility="Auto" 
              ScrollViewer.CanContentScroll="True" 
              />
</Grid>

<Grid  Grid.Row="1" Margin="0,0,0,10">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Label Grid.Row="0" Content="This is an example"/>
    <Label Grid.Row="1" Content="This is an example"/>
</Grid>

<StatusBar Grid.Row="2"  
           HorizontalAlignment="Stretch" 
           Margin="0,0,0,0" 
           VerticalAlignment="Stretch" 
           DockPanel.Dock="Bottom">
    <StatusBarItem>
        <Ellipse Width="15" Height="15" Fill="{Binding StatusColor}"></Ellipse>
    </StatusBarItem>
    <StatusBarItem>
        <TextBlock Text="{Binding StatusText}" ToolTip="{Binding StatusToolTip}"></TextBlock>
    </StatusBarItem>
    <StatusBarItem HorizontalAlignment="Right">
        <TextBlock Text="{Binding StatusLastAction}"></TextBlock>
    </StatusBarItem>
</StatusBar>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM