带有Dockpanel的ScrollViewer中的WPF Datagrid

时间:2017-12-05 12:30:33

标签: c# wpf datagrid scrollviewer dockpanel

我想让我的UI更负责任,现在我遇到了这个问题:

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

这就像魅力一样,直到DataGrid获得许多项目为止。网格不会创建自己的滚动查看器,它只使用&#34; Main&#34; - ScrollViewer的全高。 (见下图 - 右下角)

在这里查看wanted UI design (imgur)

黑色&gt; Window

绿色&gt; Scrollviewer

红色&gt; DataGrid

橙色&gt; fields to edit data

左上图(好):

  • 窗口中有足够的空间来显示所有内容
  • DataGrid(红色)填充可用空间并拥有自己的scoll查看器(如果要显示的项目数量很多)

右上角图片(好):

  • 没有足够的空间来展示所有
  • &#39; DataGrid&#39;使用最小高度,ScrollViewer(绿色)可见,以显示其余(橙色)

左下角图片(不良):

  • 没有足够的空间来展示所有
  • DataGrid使用min-height

右下角图片(不良):

  • 有足够的空间展示一切
  • DataGrid使用所有需要的空间来显示所有Item

有没有办法设计UI,如顶部图片所示?

1 个答案:

答案 0 :(得分:0)

我通常不创建屏幕,因此他们有一个外部滚动,这使其他一切变得复杂。 根据您在图片中说明的内容,DataGrid的高度不应高于屏幕的高度。

所以你需要做的就是为你的网格设置一个大小,例如:60%,70%,80%的屏幕高度,其余的是你的其他信息

在下面的解决方案中,我将DataGrid始终保留在屏幕上80%的高度

<强> 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" 
          />

转换器类

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

我测试了在一个简单的循环中生成的大量数据

ViewModel (我的测试)

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());
}

导致下面的图像,无论窗口大小如何,DataGrid都将是它高度的80%

Imagem 01

编辑: 如果您不需要外部滚动,即如果可以在屏幕上同时显示所有内容,最好的方法是将所有内容保留在相对位置,这样:

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