2010-11-15 24 views
5

Tôi đang sử dụng một DataGrid trong WPF và muốn nó co lại để chỉ vừa với chiều rộng của các cột của nó. Nó làm điều này độc đáo cho việc dựng hình ban đầu. Khi tôi thay đổi kích thước một cột để làm cho nó rộng hơn lưới cũng phát triển. Nhưng nếu tôi thay đổi kích thước cột để làm cho nó hẹp hơn một lần nữa tôi nhận được không gian màu trắng ở phía bên phải của cột của tôi (và tôi có thể thấy rằng khu vực màu xám tiêu đề cột được mở rộng ra ngoài các cột. lưới thu nhỏ chiều rộng của nó với các cột vì vậy tôi không nhận được không gian màu trắng bên phải.Tôi đã cố gắng để gỡ lỗi mã và như xa như tôi có thể thấy vấn đề là trong DataGridCellsPanel, nhưng tôi không thể nhìn thấy bất cứ nơi nào để sửa chữa đo chiều rộng.WPF DataGrid không co lại khi chiều rộng cột co lại

Bất kỳ trợ giúp sẽ được đánh giá cao.

Trả lời

3

tôi đã có vấn đề với một thời gian trở lại và tôi đã nhận được rất khó chịu bởi nó mà tôi đã thực hiện một sửa chữa xấu xí cho nó. nó không đẹp, nhưng nó được công việc đã xong. của anh ta chỉ là một vấn đề khi Horizontal ScrollBar là vô hình vì vậy chúng tôi sẽ cần một tham chiếu đến nó. Mã này sẽ phải được chạy một khi tất cả các DataGridColumn đã được nạp (trong trường hợp của tôi, tất cả trong Xaml, vì vậy sự kiện Loaded) và nó không có thêm/loại bỏ DataGridColumns vào xem xét nhưng đó là một sửa chữa dễ dàng.

<DataGrid Name="c_dataGrid" 
      Loaded="c_dataGrid_Loaded" 
      ...> 
    <DataGrid.Columns> 
     <DataGridTextColumn ..."/> 
     <DataGridTextColumn ..."/> 
     <!-- ... --> 

Sau đó, trong EventHandler Loaded chúng tôi nhận được DataGrid ScrollViewer và thêm một người biết lắng nghe cho những thay đổi trong ActualWidthProperty của mỗi DataGridColumn trong DataGrid.

private ScrollViewer m_dataGridScrollViewer = null; 
private void c_dataGrid_Loaded(object sender, RoutedEventArgs e) 
{ 
    m_dataGridScrollViewer = GetVisualChild<ScrollViewer>(c_dataGrid); 
    DependencyPropertyDescriptor dependencyPropertyDescriptor = 
     DependencyPropertyDescriptor.FromProperty(DataGridColumn.ActualWidthProperty, typeof(DataGridColumn)); 
    if (dependencyPropertyDescriptor != null) 
    { 
     foreach (DataGridColumn column in c_dataGrid.Columns) 
     { 
      dependencyPropertyDescriptor.AddValueChanged(column, DataGridColumn_ActualWidthChanged); 
     } 
    } 
} 

Và sau đó chúng tôi tính toán kích thước của DataGrid từ kích thước của tất cả DataGridColumn và thêm hằng số 8,0 (đó là sự khác biệt bình thường).

private void DataGridColumn_ActualWidthChanged(object sender, EventArgs e) 
{ 
    if (m_dataGridScrollViewer != null) 
    { 
     if (m_dataGridScrollViewer.ComputedHorizontalScrollBarVisibility != Visibility.Visible) 
     { 
      double dataGridWidth = 8.0; 
      foreach (DataGridColumn column in c_dataGrid.Columns) 
      { 
       dataGridWidth += column.ActualWidth; 
      } 
      c_dataGrid.Width = dataGridWidth; 
     } 
     else 
     { 
      c_dataGrid.Width = double.NaN; 
     } 
    } 
} 

Nếu bạn đưa ra một cách tốt hơn để làm điều này sau đó cho tôi biết :)

public static T GetVisualChild<T>(object parent) where T : Visual 
{ 
    DependencyObject dependencyObject = parent as DependencyObject; 
    return InternalGetVisualChild<T>(dependencyObject); 
} 
private static T InternalGetVisualChild<T>(DependencyObject parent) where T : Visual 
{ 
    T child = default(T); 

    int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
    for (int i = 0; i < numVisuals; i++) 
    { 
     Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); 
     child = v as T; 
     if (child == null) 
     { 
      child = GetVisualChild<T>(v); 
     } 
     if (child != null) 
     { 
      break; 
     } 
    } 
    return child; 
} 
+0

Đó là một giải pháp tốt đẹp. Tôi đã tinh chỉnh nó một chút để nó đặt thuộc tính MaxWidth thay thế. Điều này giải quyết vấn đề của lưới mở rộng vượt ra ngoài các ràng buộc của cha mẹ trực quan. Tôi cũng chuyển đổi nó thành một hành vi thay thế để đóng gói nó tốt hơn. – jjrdk

+0

Ngoài ra, nếu DataGridColumn_ActualWidthChanged không được gọi, đảm bảo rằng bạn sử dụng Microsoft.Windows.Controls.DataGridColumn và không phải là System.Windows.Controls.DataGridColumn khi bạn đang nhận DependencyPropertyDescriptor. – Monsignor

2

Đó là một giải pháp tốt đẹp. Tôi đã tinh chỉnh nó một chút để nó đặt thuộc tính MaxWidth thay thế. Điều này giải quyết vấn đề của lưới mở rộng vượt ra ngoài các ràng buộc của cha mẹ trực quan. Tôi cũng chuyển đổi nó thành một hành vi thay thế để đóng gói nó tốt hơn.

Đây là những gì tôi đã kết thúc.

public class UpdateWidthOnColumnResizedBehavior : Behavior<DataGrid> 
{ 
     private static readonly DependencyPropertyDescriptor Descriptor; 

     static UpdateWidthOnColumnResizedBehavior() 
     { 
      Descriptor = DependencyPropertyDescriptor.FromProperty(DataGridColumn.ActualWidthProperty, typeof(DataGridColumn)); 
     } 

     protected override void OnAttached() 
     { 
      base.OnAttached(); 

      AssociatedObject.Columns.CollectionChanged += OnColumnsCollectionChanged; 

      foreach (var column in AssociatedObject.Columns) 
      { 
       AddListener(column); 
      } 
     } 

     void OnColumnsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
     { 
      switch (e.Action) 
      { 
       case NotifyCollectionChangedAction.Add: 
        foreach (var column in e.NewItems.OfType<DataGridColumn>()) 
        { 
         AddListener(column); 
        } 
        break; 
       case NotifyCollectionChangedAction.Remove: 
        foreach (var column in e.OldItems.OfType<DataGridColumn>()) 
        { 
         RemoveListener(column); 
        } 
        break; 
       case NotifyCollectionChangedAction.Replace: 
        foreach (var column in e.NewItems.OfType<DataGridColumn>()) 
        { 
         AddListener(column); 
        } 
        foreach (var column in e.OldItems.OfType<DataGridColumn>()) 
        { 
         RemoveListener(column); 
        } 
        break; 
      } 
     } 

     protected override void OnDetaching() 
     { 
      base.OnDetaching(); 

      foreach (var column in AssociatedObject.Columns) 
      { 
       RemoveListener(column); 
      } 
     } 

     private void AddListener(DataGridColumn column) 
     { 
      Descriptor.AddValueChanged(column, ResizeGrid); 
     } 

     private void RemoveListener(DataGridColumn column) 
     { 
      Descriptor.RemoveValueChanged(column, ResizeGrid); 
     } 

     private void ResizeGrid(object sender, EventArgs e) 
     { 
      var columnsWidth = AssociatedObject.Columns.Sum(c => c.ActualWidth); 
      AssociatedObject.MaxWidth = columnsWidth + 2; 
      AssociatedObject.InvalidateMeasure(); 
     } 
    } 

Tôi vẫn còn một số điều cần chú ý về sự phối hợp chiều rộng của hai lưới nhưng có vẻ phù hợp với một lưới.

+0

Có vẻ tuyệt vời, sẽ thử lần sau tôi cần! –

0

dường như có một vấn đề nhỏ với cả hai cách tiếp cận của bạn. Khi tôi kéo cột bên trái nhiều nhất sang bên phải, toàn bộ lưới được thu nhỏ lại/cuộn bên trong (không may là tôi không có đủ danh tiếng để đăng hình ảnh).

Vì vậy, tôi đã sửa đổi jjrdk ResizeGrid chức năng, do đó, nó tính toán chiều rộng cột cuối cùng và kéo dài nó tất cả các cách bên trái. Lưới HorizontalAlignment và HorizontalContentAlignment phải được đặt thành HorizontalAlignment.Stretch.

void ResizeGrid(object sender, EventArgs e) 
    { 
     var scroll = ExTreeHelper.FindVisualChild<ScrollViewer>(AssociatedObject); 

     if (scroll != null && null != AssociatedObject.Columns && AssociatedObject.Columns.Count > 0) 
     { 
      var lastColumn = AssociatedObject.Columns.Last(); 

      double dataGridWidth = AssociatedObject.Columns.Sum(c => c.ActualWidth) + 2.0; 

      if (scroll.ComputedHorizontalScrollBarVisibility != Visibility.Visible) 
      { 
       RemoveListener(lastColumn); 

       AssociatedObject.Columns.Last().Width = 
        AssociatedObject.Columns.Last().Width.DisplayValue + scroll.ViewportWidth - dataGridWidth; 

       AssociatedObject.Width = dataGridWidth + scroll.ViewportWidth - dataGridWidth; 

       AddListener(lastColumn); 
      } 
      else 
      { 
       AssociatedObject.HorizontalAlignment = HorizontalAlignment.Stretch; 
       AssociatedObject.HorizontalContentAlignment = HorizontalAlignment.Stretch; 

       AssociatedObject.Width = double.NaN; 
      } 
     }   } 

Vấn đề duy nhất tôi có, là thanh cuộn luôn ở đó, ngay cả khi tất cả các cột đều vừa.

Vẫn còn một vấn đề khác, khi tất cả các cột được thu gọn sang trái, nó bắt đầu nhấp nháy.

Có điều gì có thể được thực hiện, để thực sự thoát khỏi không gian màu trắng này?

Leon

Các vấn đề liên quan