2011-02-14 38 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的定義將列寬縮小到其最小寬度,並使其寬度爲靜態且不可編輯。

相關問題