Tengo un ListBox
que se une a una colección secundaria en un ViewModel. Los elementos del cuadro de lista tienen un estilo en una plantilla de datos basada en una propiedad en el ViewModel principal:
<Style x:Key="curveSpeedNonConstantParameterCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified,
ElementName=someParentElementWithReferenceToRootDataContext}"
Value="True">
<Setter Property="Control.Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Recibo el siguiente error de salida:
System.Windows.Data Error: 39 : BindingExpression path error:
'CurveSpeedMustBeSpecified' property not found on
'object' ''BindingListCollectionView' (HashCode=20467555)'.
BindingExpression:Path=DataContext.CurveSpeedMustBeSpecified;
DataItem='Grid' (Name='nonConstantCurveParametersGrid');
target element is 'TextBox' (Name='');
target property is 'NoTarget' (type 'Object')
Entonces, si cambio la expresión de enlace a "Path=DataContext.CurrentItem.CurveSpeedMustBeSpecified"
que funciona, pero solo mientras el contexto de datos del control de usuario principal sea un BindingListCollectionView
. Esto no es aceptable porque el resto del control de usuario se une a las propiedades del CurrentItem
en BindingList
automáticamente.
¿Cómo puedo especificar la expresión de enlace dentro del estilo para que funcione independientemente de que el contexto de datos principal sea una vista de colección o un solo elemento?
Puede usar
RelativeSource
para encontrar el elemento padre, así:Consulte esta pregunta SO para obtener más detalles sobre
RelativeSource
.fuente
Mode=FindAncestor
que funcionara, pero esto funciona y es mucho mejor en un escenario MVVM porque evita los controles de nombres.Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:YourParentElementType}}}"
RelativeSource frente a ElementName
Estos dos enfoques pueden lograr el mismo resultado,
RelativeSrouce
Este método busca un control de un tipo Window (en este ejemplo) en el árbol visual y cuando lo encuentra, básicamente puede acceder a él
DataContext
usandoPath=DataContext....
. Las ventajas de este método es que no es necesario estar vinculado a un nombre y es algo dinámico; sin embargo, los cambios realizados en su árbol visual pueden afectar este método y posiblemente romperlo.ElementName
Este método se refiere a una estática sólida,
Name
por lo que siempre que su osciloscopio pueda verlo, está bien. Debería ceñirse a su convención de nomenclatura para no romper este método, por supuesto. El enfoque es bastante simple y todo lo que necesita es especificar aName="..."
para su Window / UserControl.Aunque los tres tipos (
RelativeSource, Source, ElementName
) son capaces de hacer lo mismo, pero según el siguiente artículo de MSDN, es mejor utilizar cada uno en su propia área de especialidad.Cómo: especificar el origen de enlace
Encuentre la descripción breve de cada uno más un enlace a uno más detalles en la tabla en la parte inferior de la página.
fuente
Estaba buscando cómo hacer algo similar en WPF y obtuve esta solución:
Espero que esto funcione para alguien más. Tengo un contexto de datos que se establece automáticamente en ItemsControls, y este contexto de datos tiene dos propiedades:
MyItems
-que es una colección- y un comando 'CustomCommand'. Debido a queItemTemplate
se usa aDataTemplate
,DataContext
no se puede acceder directamente a los niveles superiores. Luego, la solución para obtener el DC del padre es usar una ruta relativa y filtrar porItemsControl
tipo.fuente
el problema es que un DataTemplate no es parte de un elemento que se le aplica.
esto significa que si se vincula a la plantilla, se vincula a algo que no tiene contexto.
sin embargo, si coloca un elemento dentro de la plantilla, cuando ese elemento se aplica al padre, obtiene un contexto y el enlace funciona
entonces esto no funcionará
pero esto funciona perfectamente
porque después de que se aplica la plantilla de datos, el cuadro de grupo se coloca en el padre y tendrá acceso a su contexto
así que todo lo que tiene que hacer es eliminar el estilo de la plantilla y moverlo a un elemento en la plantilla
tenga en cuenta que el contexto para un control de elementos es el elemento, no el control, es decir, ComboBoxItem para ComboBox, no el ComboBox en sí, en cuyo caso debe usar los controles ItemContainerStyle en su lugar
fuente
Sí, puedes solucionarlo usando el
ElementName=Something
como sugiere la Juve.¡PERO!
Si un elemento secundario (en el que usa este tipo de enlace) es un control de usuario que usa el mismo nombre de elemento que usted especifica en el control principal, entonces el enlace va al objeto equivocado.
Sé que esta publicación no es una solución, pero pensé que todos los que usan ElementName en el enlace deberían saber esto, ya que es un posible error de tiempo de ejecución.
fuente