2010-11-18 11 views
11

Supongamos que tengo una cuadrícula de datos que se define como estoRowDetails DataGrid problemas Ancho

<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> 

Y se parece a esto con y sin RowDetails

alt text

En el cuadro a la derecha consigo una muy largo DataGridRow que nunca se envuelve.
¿Es posible obtener los RowDetails utilizar el mismo ancho que la cuadrícula de datos y no efectuar la misma anchura?

cosas que he intentado que logra envolver, pero no de una manera satisfactoria

  • Establecer anchura o MaxWidth en la frontera o TextBlock. No muy dinámico
  • Conjunto ScrollViewer.HorizontalScrollBarVisibility = "discapacitados" en la cuadrícula de datos. No es muy bueno cuando las columnas no encajan.

Respuesta

10

Esto es lo que terminé haciendo. Prefiero utilizar una propiedad en la cuadrícula de datos para esto, pero ya que no existen tales Propiedad necesitaba una solución.

alt text

Primera acabo de utilizar ActualWidth de la cuadrícula de datos de los padres y sacó una constante de 9. Esto funcionó al principio, pero no cuando la barra de desplazamiento vertical se hizo visible así que tuve que utilizar un 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> 

Y en el convertidor usé otra constante (16) para compensar una barra de desplazamiento vertical visible (si está visible).

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; 
    } 
} 

actualización

I mejorada sobre la solución un poco, utilizando ActualWidth para la ItemsPresenter en lugar de DataGrid (donde ActualWidth no cambió en función de una barra de desplazamiento visible), por lo tanto la eliminación de la necesidad de un MultiConverter y dos constantes.

<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

con su versión actualizada con ItemsPresenter como ancestro, la barra de desplazamiento vertical no se respeta. Restamos 22 para evitar la barra de desplazamiento horizontal. – user2452157

2

Es posible que pueda vincular el MaxWidth a ElementName=PART_ColumnHeadersPresenter, Path=ActualWidth o quizás a RenderSize.Width. Creo que es la parte de la plantilla de cuadrícula de datos que muestra las columnas así que en teoría debería funcionar

+0

¡Gracias por su consejo! Esto es bastante parecido a lo que terminé haciendo. –

2

Gracias Meleak, su solución funcionó bien para mí. Una pequeña adición para nosotros los novatos de WPF. Asegúrese de declarar su clase Convertidor como un recurso para que pueda ser referenciado en la expresión Vinculante.

puse la mía en la aplicación.XAML como esto:

<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

Gracias por su respuesta, agregué esto a mi solución actualizada que eliminó la necesidad de un MultiConverter. –

1

para salvar a otras personas un poco de rascarse la cabeza y el tiempo de ensayo y error:

Después de quejarse con Fredrik Hedblad más reciente (1/1/11) solution desde hace algún tiempo me di que el ConverterParameter valor debe ser 6 + [margen izquierdo} + [margen derecho] (es decir, los márgenes del contenedor más externo en la plantilla.) Después de examinar una ampliación de una captura de pantalla, espero que el ancho de la barra vertical a la izquierda de cada fila.

+0

¿Escalará esta solución para diferentes configuraciones de DPI? – Ahmad

13

Las respuestas aquí se sentía como una solución así que hice algunas investigaciones y encontré la solución en los foros de Telerik, ya que utilizamos su RadGridView. Resultó que la solución también funcionaba para DataGrid.

La clave es establecer la propiedad ScrollViewer.HorizontalScrollBarVisibility para personas de movilidad reducida, véase el ejemplo a continuación.

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

Editar: Un efecto secundario es que si las columnas necesita más espacio horizontal que hay espacio para que se recortan. Entonces, si esto es un problema, esta solución no es óptima.

+0

¡Funciona como un encanto! Muchas gracias, no me lo hubiera imaginado por mi cuenta ... – Ash

+0

¡Esta solución no se escala cuando realmente se necesita una ScrolBar horizontal para desplazarse a columnas ocultas! – Ahmad

2

Esto es lo que terminé haciendo: encuadernación del ancho de los detalles de la fila hasta el ancho real de su presentador y luego agregué un borde con un grosor variado para compensar la presencia/ausencia de una barra de desplazamiento vertical en el presentador . Este enfoque funcionó perfectamente para mí. Muestra 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>