2010-11-18 26 views
11

Giả sử tôi có một DataGrid được định nghĩa như thế nàyDataGrid RowDetails vấn đề Width

<DataGrid AreRowDetailsFrozen="True" 
      ItemsSource="{Binding MyCollection}" 
      AutoGenerateColumns="False"> 
    <DataGrid.RowDetailsTemplate> 
     <DataTemplate> 
      <Border CornerRadius="5" BorderBrush="Red" 
        BorderThickness="2" Background="Black"> 
       <TextBlock Foreground="White" Text="{Binding RowDetails}" 
          TextWrapping="Wrap"/> 
      </Border> 
     </DataTemplate> 
    </DataGrid.RowDetailsTemplate> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="0" Binding="{Binding Value1}"/> 
     <DataGridTextColumn Header="1" Binding="{Binding Value2}"/> 
     <DataGridTextColumn Header="2" Binding="{Binding Value3}"/> 
     <DataGridTextColumn Header="3" Binding="{Binding Value4}"/> 
    </DataGrid.Columns> 
</DataGrid> 

Và trông như thế này có và không có RowDetails

alt text

Trong bức ảnh bên phải tôi nhận được một DataGridRow rất dài không bao giờ kết thúc tốt đẹp.
Có thể lấy RowDetails để sử dụng cùng chiều rộng với DataGrid và không ảnh hưởng đến Chiều rộng không?

Những điều tôi đã cố gắng mà đạt được gói nhưng không phải trong một cách thỏa mãn

  • Set Width hoặc MaxWidth trên biên giới hoặc TextBlock. Không phải rất năng động.
  • Đặt ScrollViewer.HorizontalScrollBarVisibility = "Đã tắt" trên DataGrid. Không phải là rất tốt khi các cột không phù hợp.

Trả lời

10

Đây là những gì tôi đã kết thúc. Tôi muốn sử dụng một tài sản trên DataGrid cho điều này, nhưng vì không có tài sản như vậy tồn tại tôi cần một workaround.

alt text

Đầu tiên tôi chỉ sử dụng ActualWidth từ DataGrid phụ huynh và loại bỏ một hằng số của 9. Điều này làm việc lúc đầu tiên nhưng thất bại khi thanh cuộn dọc trở nên nhìn thấy được vì vậy tôi đã phải sử dụng một MultiBinding.

<DataGrid.RowDetailsTemplate> 
    <DataTemplate> 
     <Border HorizontalAlignment="Left" CornerRadius="5" 
       BorderBrush="Red" BorderThickness="2" Background="Black"> 
      <Border.Width> 
       <MultiBinding Converter="{StaticResource RowDetailsWidthMultiConverter}" 
           ConverterParameter="9"> 
        <Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGrid}}" 
          Path="ActualWidth"/> 
        <Binding RelativeSource="{RelativeSource AncestorType={x:Type ScrollViewer}}" 
          Path="ComputedVerticalScrollBarVisibility"/> 
       </MultiBinding> 
      </Border.Width> 
      <TextBlock Foreground="White" Text="{Binding RowDetails}" TextWrapping="Wrap"/> 
     </Border> 
    </DataTemplate> 
</DataGrid.RowDetailsTemplate> 

Và trong bộ chuyển đổi, tôi đã sử dụng một hằng số khác (16) để bù cho thanh cuộn dọc có thể nhìn thấy (nếu có thể nhìn thấy).

public class RowDetailsWidthMultiConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     double originalWidth = (double)values[0]; 
     Visibility verticalScrollbarVisibility = (Visibility)values[1]; 
     double subtractWidth = System.Convert.ToDouble(parameter); 
     double returnWidth = originalWidth - subtractWidth; 
     if (verticalScrollbarVisibility == Visibility.Visible) 
     { 
      return returnWidth - 16; 
     } 
     return returnWidth; 
    } 
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return null; 
    } 
} 

Cập nhật

tôi cải thiện trên các giải pháp một chút, sử dụng ActualWidth cho ItemsPresenter thay vì sau đó DataGrid (nơi ActualWidth không thay đổi tùy thuộc vào một ScrollBar nhìn thấy được), do đó loại bỏ các cần cho một MultiConverter và hai hằng số.

<DataGrid.Resources> 
    <local:SubtractConstantConverter x:Key="SubtractConstantConverter"/> 
</DataGrid.Resources> 
<DataGrid.RowDetailsTemplate> 
    <DataTemplate> 
     <Border HorizontalAlignment="Left" CornerRadius="5" 
       BorderBrush="Red" BorderThickness="2" Background="Black" 
       Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsPresenter}}, 
           Path=ActualWidth, 
           Converter={StaticResource SubtractConstantConverter}, 
           ConverterParameter=6}"> 
      <TextBlock Foreground="White" Text="{Binding RowDetails}" TextWrapping="Wrap"/> 
     </Border> 
    </DataTemplate> 
</DataGrid.RowDetailsTemplate> 

SubtractConstantConverter

public class SubtractConstantConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     double originalValue = (double)value; 
     double subtractValue = System.Convert.ToDouble(parameter); 
     return originalValue - subtractValue; 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return null; 
    } 
} 
+0

với phiên bản cập nhật của bạn với ItemsPresenter làm tổ tiên thanh cuộn dọc không được tôn trọng. Tôi trừ 22 để tránh thanh cuộn ngang. – user2452157

2

Bạn có thể liên kết MaxWidth với ElementName=PART_ColumnHeadersPresenter, Path=ActualWidth hoặc có thể là RenderSize.Width. Tôi tin rằng đó là một phần của mẫu DataGrid hiển thị các cột nên theo lý thuyết nó sẽ hoạt động

+0

Cảm ơn bạn đã tip! Điều này khá gần với những gì tôi đã làm. –

2

Cảm ơn Meleak, giải pháp của bạn làm việc tốt cho tôi. Một bổ sung nhỏ cho chúng tôi WPF người mới. Hãy chắc chắn khai báo lớp Converter của bạn như là một tài nguyên để nó có thể được tham chiếu trong biểu thức Binding.

Tôi đặt mỏ trong ứng dụng.XAML như thế này:

<Application x:Class="ISCBilling.App" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:conv="clr-namespace:my.application.namespace" 
      StartupUri="IscBillingWindow.xaml"> 
    <Application.Resources> 

     <conv:RowDetailsWidthMultiConverter x:Key="RowDetailsWidthMultiConverter" /> 

    </Application.Resources> 
</Application> 
+0

Cảm ơn bạn đã trả lời, tôi đã thêm phần này vào giải pháp được cập nhật của tôi, điều này đã loại bỏ nhu cầu về một MultiConverter. –

1

Để lưu folks khác một số người đứng đầu gãi và thử-và-lỗi thời gian:

Sau nhặng xị với Fredrik Hedblad của gần đây nhất (1/1/11) solution một thời gian tôi figured Giá trị ConverterParameter phải là 6 + [lề trái} + [lề phải] (tức là lề của thùng chứa ngoài cùng bên ngoài trong mẫu.) Sau khi kiểm tra ảnh chụp màn hình, tôi mong đợi là chiều rộng của thanh dọc ở bên trái của mỗi hàng.

+0

Giải pháp này có mở rộng quy mô cho các cài đặt DPI khác nhau không! – Ahmad

13

Câu trả lời ở đây cảm thấy giống như một giải pháp thay thế vì vậy tôi đã thực hiện một số nghiên cứu và tìm giải pháp trên diễn đàn Telerik, vì chúng tôi sử dụng RadGridView của họ. Hóa ra giải pháp đã làm việc cho DataGrid.

Điều quan trọng là đặt thuộc tính ScrollViewer.HorizontalScrollBarVisibility thành Tắt, xem ví dụ bên dưới.

<DataGrid ScrollViewer.HorizontalScrollBarVisibility="Disabled"> 
<DataGrid.RowDetailsTemplate> 
    <DataTemplate> 
     <Border> 
      <TextBlock Foreground="White" Text="{Binding RowDetails}" 
         TextWrapping="Wrap"/> 
     </Border> 
    </DataTemplate> 
</DataGrid.RowDetailsTemplate> 

Edit: Một tác dụng phụ là nếu các cột cần thêm dung lượng theo chiều ngang hơn có chỗ cho họ sẽ được cắt bớt. Vì vậy, nếu đây là một vấn đề thì giải pháp này không phải là tối ưu.

+0

Hoạt động như một sự quyến rũ! Cảm ơn rất nhiều, tôi sẽ không tự tìm ra điều đó ... – Ash

+0

Giải pháp này không mở rộng khi bạn thực sự yêu cầu ScrolBar ngang để cuộn đến các cột ẩn! – Ahmad

2

Đây là những gì tôi đã thực hiện: liên kết chiều rộng chi tiết hàng với chiều rộng thực của người trình bày và sau đó thêm đường viền có độ dày khác nhau để bù cho sự hiện diện/vắng mặt của thanh cuộn dọc trong trình bày . Cách tiếp cận này làm việc hoàn hảo cho tôi. Mẫu xaml:

<DataGrid.RowDetailsTemplate> 
    <DataTemplate> 
     <Border BorderThickness="2,2,8,2" 
       Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsPresenter}}, Path=ActualWidth}" 
       HorizontalAlignment="Left" > 
      <!-- add the row details view contents here --> 
     </Border> 
    </DataTemplate> 
</DataGrid.RowDetailsTemplate> 
Các vấn đề liên quan