2011-02-14 143 views
19

我有一个包含一些数据的WPF DataGrid。我想设置列的宽度,使内容适合并永远不会被裁剪(相反,水平滚动条应可见)。此外,我希望DataGrid可以填满整个空间(我正在使用DockPanel)。我使用下面的代码(简化):如何设置DataGridColumn的宽度以适应内容(“Auto”),但是完全填充MVVM中DataGrid的可用空间?

<DataGrid ItemsSource="{Binding Table}"> 
    <DataGrid.Columns> 
     <DataGridTextColumn MinWidth="100" Width="Auto" Header="Column 1" Binding="{Binding Property1}" /> 
     <DataGridTextColumn MinWidth="200" Width="Auto" Header="Column 2" Binding="{Binding Property2}" /> 
    </DataGrid.Columns> 
</DataGrid> 

这显然不开箱即用Width="Auto"工作,因为它总是看起来是这样的:

DataGrid: only the first part of the row is marked as "selected"

这显然看起来丑陋。我希望将整行选中,或者,更好的是填充整个宽度的列,但正如人们所看到的,这不起作用。

如果我用Width="*"代替,那么列的内容会被裁剪,这对我来说更糟糕。

我发现了一个similar question here,并且在那里发布了解决方法。这可能会起作用,但我正在使用MVVM模式,所以ItemsSource在ViewModel中得到更新,我无法想象从那里做的一种方式,因为我无法访问DataGridColumnActualWidth属性。另外,如果可能的话,我只想在XAML中执行此操作。

我将不胜感激任何帮助。谢谢!

编辑:由于我仍然不知道该怎么做,我开始一个小赏金。我会很高兴提出一个建议,可以对我的问题做些什么。再次感谢!

编辑2:在saus的回答之后,我再次考虑了选项。问题是我需要在应用程序运行期间更新WidthMinWidth属性,所以不仅在加载窗口之后。我已经试过当DataGrid的根本ItemsSource正在更新被解雇一些事件做一些像

column.Width = new DataGridLength(1, DataGridLengthUnitType.Auto); 
column.MinWidth = column.ActualWidth; 
column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); 

。但是,这不起作用,ActualWidth属性在Auto上设置Width后似乎没有更改。有没有一种选择来“重画”它,以获得ActualWidth属性更新?谢谢!

+0

我不知道我明白你想在这里做什么。如果列的宽度比您想要垂直滚动条的`DataGrid`宽,并且不希望文本换行?你的意思是一个水平滚动条?否则,这对我来说没有意义,但也许我只是在这里缓慢:) – 2011-02-17 09:55:09

+1

感谢您的提示!当然,我的意思是一个水平滚动条,它不会有任何意义,否则;-) – 2011-02-17 13:13:08

回答

2

如果你想在列从未断绝你的数据,以下内容添加到您的窗口/用户控件定义:

xmlns:System="clr-namespace:System;assembly=mscorlib" 

然后你可以使用下面的列的宽度。

Width="{x:Static System:Double.NaN}" 

这使得列始终增大到足以容纳列中最长的值。

正如上面的代码并没有在DataGrid工作,怎么样加入的ScrollViewer周围的DataGrid这样的:

 <ScrollViewer HorizontalScrollBarVisibility="Auto" 
        VerticalScrollBarVisibility="Auto"> 
     <DataGrid ItemsSource="{Binding Table}" AutoGenerateColumns="False"> 
      <DataGrid.Columns> 
       <DataGridTextColumn MinWidth="10" Width="Auto" Header="Column 1" Binding="{Binding Property1}" /> 
       <DataGridTextColumn MinWidth="200" Width="*" Header="Column 2" Binding="{Binding Property2}" />      
      </DataGrid.Columns> 
     </DataGrid> 
    </ScrollViewer> 
+1

感谢您的答案。然而,我在添加之后得到一个`XamlParseException`。另外,我认为这会以与将`Width`设置为`“Auto”(实际上,我认为`“Auto”`在内部表示为`Double.NaN`)完全相同的行为结束。 – 2011-02-14 21:51:31

+0

我曾在GridViews上使用过它,并且它非常适合动态调整列的大小。今天早上试用了DataGrid,并得到了相同的Xaml错误。 – 2011-02-15 13:40:22

+1

所以你有一个错误,但仍然决定发布你的答案? – David 2017-06-19 12:04:54

4

使用一个TextBlock用文字环绕模板列里:

<DataGrid ItemsSource="{Binding Table}">  
    <DataGrid.Columns>   
     <DataGridTextColumn MinWidth="100" Width="Auto" Header="Column 1" 
          Binding="{Binding Property1}" />   
     <DataGridTemplateColumn Width="*" Header="Column 2"> 
      <DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Property2}" TextWrapping="Wrap" /> 
       </DataTemplate> 
      </DataGridTemplateColumn.CellTemplate> 
     </DataGridTemplateColumn> 
    </DataGrid.Columns> 
</DataGrid> 
1

这是怎么回事:

为您的列'MinWidth,你设置绑定到dataGrid的ScrollContent的宽度,用一个转换器将这个宽度除以nu mber列

你需要一些代码为转换器,但这会保持你的MVVM结构完好无损。

可能是一个长镜头,但没有时间去尝试。

编辑:我把一些更多的思考这个,有一个Pb:如果你有,比如说它不会很好地工作,一个巨大的列和几个小的。我认为所有的cols都是相同的宽度,这显然不是这种情况。

尽管如此,你可能想要探索一下。在转换器上使用宽度上的绑定是我能想到的唯一可行的方法:由于在计算列宽时基本上有两个条件需要考虑,因此不会有简单的方法来执行此操作。

29

我建议使用您链接到的解决方法。它确实有效。在您看来的代码隐藏,添加以下的构造函数的InitializeComponent()后:

Griddy.Loaded += SetMinWidths; // I named my datagrid Griddy 

,并定义为SetMinWidths:

public void SetMinWidths(object source, EventArgs e) 
     { 
      foreach (var column in Griddy.Columns) 
      { 
       column.MinWidth = column.ActualWidth; 
       column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); 
      } 
     } 

我假设的原因,你不想使用这种解决方案是,您认为MVVM禁止代码隐藏中的代码。但由于这完全是查看特定的逻辑,我认为在这种情况下是合理的。整个“MVVM禁止代码隐藏”的东西有点误解。

但是,如果你是风格指南的约束,或者你想要这个逻辑,可用于应用中的所有数据网格,可以使一个附加的行为,做这样的工作:

public class SetMinWidthToAutoAttachedBehaviour 
    { 
     public static bool GetSetMinWidthToAuto(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(SetMinWidthToAutoProperty); 
     } 

     public static void SetSetMinWidthToAuto(DependencyObject obj, bool value) 
     { 
      obj.SetValue(SetMinWidthToAutoProperty, value); 
     } 

     // Using a DependencyProperty as the backing store for SetMinWidthToAuto. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty SetMinWidthToAutoProperty = 
      DependencyProperty.RegisterAttached("SetMinWidthToAuto", typeof(bool), typeof(SetMinWidthToAutoAttachedBehaviour), new UIPropertyMetadata(false, WireUpLoadedEvent)); 

     public static void WireUpLoadedEvent(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var grid = (DataGrid)d; 

      var doIt = (bool)e.NewValue; 

      if (doIt) 
      { 
       grid.Loaded += SetMinWidths; 
      } 
     } 

     public static void SetMinWidths(object source, EventArgs e) 
     { 
      var grid = (DataGrid)source; 

      foreach (var column in grid.Columns) 
      { 
       column.MinWidth = column.ActualWidth; 
       column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); 
      } 
     } 
    } 

,然后为要应用此行为,添加以下任何数据网格:

<DataGrid ItemsSource="{Binding Table}" local:SetMinWidthToAutoAttachedBehaviour.SetMinWidthToAuto="true"> 

然后你的良心,以及你的代码隐藏,就清楚了。

0

队最后一列采取所有剩余空间在数据网格

grid.Columns[grid.Columns.Count -1].Width = new 
        DataGridLength(250, DataGridLengthUnitType.Star); 
1

我加入了Event到重新定义关于向DataGrid的实际宽度的宽度DataGrid

private static void OnLoaded(object sender, RoutedEventArgs e) 
    { 
     DataGrid dg = sender as DataGrid; 
     foreach (var column in dg.Columns) 
     { 
      column.Width = new DataGridLength(dg.ActualWidth/dg.Columns.Count, DataGridLengthUnitType.Pixel); 
     } 
    } 

该行:

column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); 

绝对是无厘头的。 DataGridLengthUnitType.Star的定义将列宽缩小到其最小宽度,并使其宽度为静态且不可编辑。

相关问题