Se unen a ActualHeight de Elemento ItemsControl
-
15-11-2019 - |
Pregunta
Tengo dos separados ItemsControl
s que aparecen al lado.El ItemsControl
s se unen a la misma ItemsSource
, pero que muestran los datos de manera diferente.
Cada elemento que aparece en la izquierda más probable es que sea más pequeño que el mismo artículo en el derecho.Esto provoca un problema debido a que las filas no se alinean, así que necesito el elemento de la izquierda para enlazar con el elemento de la derecha.
ItemsControl ItemsControl
|Item 1 |Item 1
|Item 2 |Item 2
|Item 3 |
|Item 4 |Item 3
Como se puede ver, el Punto 2 de la derecha es más grande, por lo que se produce fuera de la alineación.Así que si me puede obligar a la izquierda del Punto 2 a la derecha del Punto 2 del ActualHeight
el problema estaría resuelto.¿Cómo puedo hacer esto en XAML?
Editar: Para hacer las cosas más complicadas, el ItemsControl
en la derecha necesita para desplazarse de derecha a izquierda, pero ambos ItemsControls
necesidad de desplazarse arriba y abajo juntos.Básicamente, el de la izquierda proporciona un encabezado de tipo de los elementos a la derecha.
Solución
El seguimiento de los Trabajoi de Alegría respuesta
Usted no puede hacer un directo OneWayToSource
Enlace en el código Xaml de la Propiedad de Dependencia de sólo lectura de la ActualHeight pero hay muchas soluciones.La respuesta por Kent Boogaart en esta pregunta es mi favorito.Lo que se hace es que se utiliza, se Adjunta un Comportamiento que escucha a la SizeChanged
evento de cualquier FrameworkElement
y las actualizaciones de dos de las Propiedades Adjuntas, la Anchura y la Altura, respectivamente.
Con un TextBlock
por ejemplo, ActualHeight
puede ser utilizado para empujar a una Altura de propiedad de la Perspective como
<TextBlock local:ActualSizeBehavior.ObserveActualSize="True"
local:ActualSizeBehavior.ActualHeight="{Binding Path=Height,
Mode=OneWayToSource}"
.../>
Synkronize dos ScrollViewers
También se puede usar un DependencyPropertyDescriptor
para escuchar los cambios en la VerticalOffsetProperty
propiedad o suscribirse a la ScrollChanged
evento y llamar ScrollToVerticalOffset
.Ejemplo
Xaml
<ScrollViewer Name="scrollViewerLeft"
ScrollChanged="scrollViewerLeft_ScrollChanged">
<ScrollViewer Name="scrollViewerRight"
ScrollChanged="scrollViewerRight_ScrollChanged">
Código detrás de los controladores de eventos
private void scrollViewerLeft_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
scrollViewerRight.ScrollToVerticalOffset(scrollViewerLeft.VerticalOffset);
}
private void scrollViewerRight_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
scrollViewerLeft.ScrollToVerticalOffset(scrollViewerRight.VerticalOffset);
}
ActualSizeBehavior
public static class ActualSizeBehavior
{
public static readonly DependencyProperty ActualSizeProperty =
DependencyProperty.RegisterAttached("ActualSize",
typeof(bool),
typeof(ActualSizeBehavior),
new UIPropertyMetadata(false, OnActualSizeChanged));
public static bool GetActualSize(DependencyObject obj)
{
return (bool)obj.GetValue(ActualSizeProperty);
}
public static void SetActualSize(DependencyObject obj, bool value)
{
obj.SetValue(ActualSizeProperty, value);
}
private static void OnActualSizeChanged(DependencyObject dpo,
DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = dpo as FrameworkElement;
if ((bool)e.NewValue == true)
{
element.SizeChanged += element_SizeChanged;
}
else
{
element.SizeChanged -= element_SizeChanged;
}
}
static void element_SizeChanged(object sender, SizeChangedEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
SetActualWidth(element, element.ActualWidth);
SetActualHeight(element, element.ActualHeight);
}
private static readonly DependencyProperty ActualWidthProperty =
DependencyProperty.RegisterAttached("ActualWidth", typeof(double), typeof(ActualSizeBehavior));
public static void SetActualWidth(DependencyObject element, double value)
{
element.SetValue(ActualWidthProperty, value);
}
public static double GetActualWidth(DependencyObject element)
{
return (double)element.GetValue(ActualWidthProperty);
}
private static readonly DependencyProperty ActualHeightProperty =
DependencyProperty.RegisterAttached("ActualHeight", typeof(double), typeof(ActualSizeBehavior));
public static void SetActualHeight(DependencyObject element, double value)
{
element.SetValue(ActualHeightProperty, value);
}
public static double GetActualHeight(DependencyObject element)
{
return (double)element.GetValue(ActualHeightProperty);
}
}
Otros consejos
Desde el ItemsSource
es igual en ambos, usted puede usar una sola ItemsControl
y toda una fila representado como dos secciones (Dos columnas de una Cuadrícula) en el interior que solo DataTemplate
, entonces heights se alinean automáticamente.Siempre se puede dar el estilo para que parezca que es parte de dos diferentes ItemsControl
pero, técnicamente, uno.
Otra manera de ir con esto es, la adición de una Altura de propiedad en el ViewModel (supuesto, no es muy correcto diseño, ya que la adición de Vista de la dependencia de la VM).TwoWay obligar a la altura de la ActualHeight de la izquierda-itemsControl ItemContainerStyle.Y a la derecha-itemscontrol se unen a la Altura de la propiedad a la Altura de ItemsContainerStyle {Una Manera}.Por lo tanto será en la sincronización.
Otra idea basada en su actualización de la Necesidad de desplazamiento en el lado derecho' :El uso de un ListView único y tiene dos columnas, y de los dos GridViewColumn.CellTemplate tener dos DataTemplates.Esta es la idea que sigue necesidades de la columna de la congelación en la primera columna.Pero que puede ser más complicado.
De todos modos me gustaría ir con el primer enfoque aquí.
Echa un vistazo a mi artículo: http://www.codeproject.com/KB/WPF/BindingHub.aspx
Que trata de cómo se puede enlazar a la Dependencia de Sólo Lectura usando las Propiedades de BindingHub:
<bindings:BindingHub
Visibility="Hidden"
Socket1="{Binding ActualWidth, ElementName=Item, Mode=OneWay}"
Socket2="{Binding ItemWidth, Mode=OneWayToSource}"
Connect="(1 in, 2 out)"/>