【问题标题】:WPF Datagrid in ScrollViewer with Dockpanel带有 Dockpanel 的 ScrollViewer 中的 WPF Datagrid
【发布时间】:2018-05-19 02:49:56
【问题描述】:

我想让我的用户界面更负责,现在我遇到了这个问题:

<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 获得许多项目。网格不会创建自己的滚动查看器,它只是使用“主”-ScrollViewer 的全高。 (见下图 - 右下角)


在这里寻找wanted UI design (imgur)

黑色 > Window

绿色 > Scrollviewer

红色 > DataGrid

橙色 > fields to edit data


左上图(好):

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

右上角的图片(好):

  • 空间不足,无法全部显示
  • “DataGrid”使用最小高度,ScrollViewer(绿色)可见以显示其余部分(橙色)

左下图(坏):

  • 空间不足,无法全部显示
  • DataGrid 不使用最小高度

右下图(坏):

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

有没有办法设计如上图所示的 UI?

【问题讨论】:

  • 看起来 MaxHeight 在 DataGrid 上设置应该会有所帮助
  • 当我设置 MaxHeight 时,它在某些时候不会响应。所以这不是一个真正的机会......但感谢你的想法!
  • 在数据网格中使用滚动视图并设置其MaxHeight &lt;DataGrid ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" &gt;
  • @CelsoLívero 当我设置 MaxHeight 时它不会响应......所以这不是我想要的......
  • @bene_rawr 这是一种适合您的场景的独特方式,例如,将 DataGrid 的 MaxHeight 设置为屏幕可见区域的 90%,看,只是,让我们MaxHeight,也就是说,它可能仍然更小,但不会更大,MaxHeight = {Binding MaxHeightProperty},在你的ViewModel中你可以计算MaxHeight

标签: c# wpf datagrid scrollviewer dockpanel


【解决方案1】:

我通常不会创建具有外部滚动的屏幕,这会使其他一切变得复杂。 根据您在图片中的说明,您的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%

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

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

【讨论】:

  • 还有一件事,你可以在你的转换器中改变很多你想要的东西,value是Window的ActualHeight,所以你可以使用你的Convert来根据大小改变Grid的大小窗口的大小,也就是说,它可以根据你的窗口大小有更大或更小的比例
猜你喜欢
  • 2011-05-20
  • 2012-01-07
  • 2014-10-05
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 2011-01-02
  • 1970-01-01
  • 2013-11-24
相关资源
最近更新 更多