2014-02-18 98 views
0

我有一個包含大量組件的頁面,需要幾秒鐘才能加載。WPF Toolkit DataGrid呈現不正確的列寬度

我的問題是,該頁面在組件已計算其列寬並且用戶可以在屏幕上看到渲染之前呈現頁面。

我建立一個非常簡單的例子:本數據網格有3列,第一列具有Width="*" ,另一列具有一個固定的寬度。 與固定寬度的列從一開始就正確地呈現,但星形柱呈現與20

enter image description here

的寬度之後的第二的數據網格計算星列的正確寬度並呈現網格正確:

enter image description here

我的例子XAML:

<ScrollViewer> 
    <Controls:DataGrid Name="mainTable" AutoGenerateColumns="False"> 
     <Controls:DataGrid.Columns> 
      <Controls:DataGridTemplateColumn Header="col 0" Width="*"> 
       <Controls:DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding Col0}" /> 
        </DataTemplate> 
       </Controls:DataGridTemplateColumn.CellTemplate> 
      </Controls:DataGridTemplateColumn> 

      <Controls:DataGridTextColumn Header="col 1" Binding="{Binding Col1}" Width="150" /> 
      <Controls:DataGridTextColumn Header="col 2" Binding="{Binding Col2}" Width="150" /> 
     </Controls:DataGrid.Columns> 
    </Controls:DataGrid> 

而後面的代碼:

public MainWindow() 
{ 
    InitializeComponent(); 

    var rows = new List<RowObj>(); 
    for (int i = 0; i < 5000; i++) 
    { 
     rows.Add(new RowObj 
     { 
      Col0 = "col0," + i, 
      Col1 = "col1," + i, 
      Col2 = "col2," + i, 
      Col3 = "col3," + i, 
      Col4 = "col4," + i, 
     }); 
    } 

    mainTable.ItemsSource = rows; 
} 

作爲一個說明:我用WpfToolkit(最新的版本,從2010年)和.NET 3.5 我不能切換到WPF4組件。

任何想法如何解決加載問題?

+0

嘗試之前'的InitializeComponent移動行列表生成的邏輯()'。 –

+0

@RohitVats:沒有幫助,它在大多數情況下實際上會拋出一個異常,因爲這些控件還沒有創建。實際的渲染不會在綁定時發生,因此設置數據實際上可以在init或加載事件中以相同的結果完成。 –

+0

我的意思是隻移動列表部分而不是賦值 - 'mainTable.ItemsSource = rows;'。這隻能在'InitializeComponent()'之下。 –

回答

0

我的解決方案是創建一個新的DataGrid繼承工具包DataGrid和覆蓋的MeasureOverride方法,並設置寬度。這樣在第一次渲染時就可以正確計算寬度。

protected override Size MeasureOverride(Size availableSize) 
{ 
    double totalWidth = availableSize.Width; 
    double absoluteWidth = 0.0; 

    DataGridColumn star = null; 
    foreach (var col in Columns) 
    { 
     if (col.Width.IsAbsolute) 
     { 
      absoluteWidth += col.Width.Value; 
      col.MinWidth = col.Width.Value; 
     } 
     else if (col.Width.IsAuto) 
     { 
      absoluteWidth += col.Width.DisplayValue; 
     } 
     else if (col.Width.IsStar) 
     { 
      if (null == star) 
      { 
       star = col; 
      } 
      else 
      { 
       // This method only handles one star column 
       star = null; 
       break; 
      } 
     } 
    } 

    if (null != star) 
    { 
     double diff = totalWidth - absoluteWidth - 4.0; 
     if (diff > 0.0) 
      star.MinWidth = diff; 
     else 
      star.MinWidth = 10.0; 
    } 

    return base.MeasureOverride(availableSize); 
} 

警告:這更是一個黑客/變通辦法的,因爲它規定列的寬度,我可以使用的類型做了一些限制,並在操作,我可以對他們做(例如結合寬度是這個解決方案無法解決問題)。

備註:對於任何可以在創建頁面之前加載數據的人,Rohit Vats的答案很可能會奏效。

0

嘗試手動將代碼放在調度

Application.Current.Dispatcher.BeginInvoke(new Action(() => { 

       var rows = new List<RowObj>(); 
       for (int i = 0; i < 5000; i++) 
       { 
        rows.Add(new RowObj 
        { 
         Col0 = "col0," + i, 
         Col1 = "col1," + i, 
         Col2 = "col2," + i, 
         Col3 = "col3," + i, 
         Col4 = "col4," + i, 
        }); 
       } 

       mainTable.ItemsSource = rows; 

      }), System.Windows.Threading.DispatcherPriority.Background); 
+0

沒有幫助,現在表格顯示爲部分空白並且具有調整大小。 –

1

移動生成列表的邏輯上述InitializeComponent()和簡單地設定ItemsSource算賬:

public MainWindow() 
{ 
    var rows = new List<RowObj>(); 
    for (int i = 0; i < 5000; i++) 
    { 
     rows.Add(new RowObj 
     { 
      Col0 = "col0," + i, 
      Col1 = "col1," + i, 
      Col2 = "col2," + i, 
      Col3 = "col3," + i, 
      Col4 = "col4," + i, 
     }); 
    } 
    InitializeComponent(); 

    mainTable.ItemsSource = rows; 
} 
+1

+1這適用於任何在頁面創建後不需要加載數據的人。如果我可以改變我的應用程序的工作流程,這也將是接受的答案。 –