tutoriales - Error de WPF: no se puede encontrar FrameworkElement de gobierno para el elemento de destino
tutoriales de wpf (1)
Tengo una cuadrícula de datos con una fila que tiene una imagen. Esta imagen está vinculada con un disparador a un cierto estado. Cuando el estado cambia, quiero cambiar la imagen.
La plantilla en sí está configurada en HeaderStyle de DataGridTemplateColumn. Esta plantilla tiene algunos enlaces. El primer día vinculante muestra qué día es y el estado cambia la imagen con un desencadenador.
Estas propiedades se establecen en un ViewModel.
Propiedades:
public class HeaderItem
{
public string Day { get; set; }
public ValidationStatus State { get; set; }
}
this.HeaderItems = new ObservableCollection<HeaderItem>();
for (int i = 1; i < 15; i++)
{
this.HeaderItems.Add(new HeaderItem()
{
Day = i.ToString(),
State = ValidationStatus.Nieuw,
});
}
Cuadrícula de datos:
<DataGrid x:Name="PersoneelsPrestatiesDataGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
AutoGenerateColumns="False" SelectionMode="Single" ItemsSource="{Binding CaregiverPerformances}" FrozenColumnCount="1" >
<DataGridTemplateColumn HeaderStyle="{StaticResource headerCenterAlignment}" Header="{Binding HeaderItems[1]}" Width="50">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{ Binding Performances[1].Duration,Converter={StaticResource timeSpanConverter},Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock TextAlignment="Center" Text="{ Binding Performances[1].Duration,Converter={StaticResource timeSpanConverter}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGrid>
Datagrid HeaderStyleTemplate:
<Style x:Key="headerCenterAlignment"
TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Day}" />
<Image x:Name="imageValidation" Grid.Row="1" Width="16" Height="16" Source="{StaticResource imgBevestigd}" />
</Grid>
<ControlTemplate.Triggers>
<MultiDataTrigger >
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding State}" Value="Nieuw"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="imageValidation" Property="Source" Value="{StaticResource imgGeenStatus}"/>
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Ahora, cuando inicio el proyecto, las imágenes no se muestran y aparece este error:
Error de System.Windows.Data: 2: no se puede encontrar FrameworkElemento o FrameworkContentElement para el elemento de destino. BindingExpression: Path = HeaderItems [0]; DataItem = null; el elemento de destino es ''DataGridTemplateColumn'' (HashCode = 26950454); la propiedad de destino es ''Encabezado'' (escribe ''Objeto'')
¿Por qué se muestra este error?
Lamentablemente, cualquier DataGridColumn
alojado en DataGrid.Columns
no forma parte del árbol Visual
y, por lo tanto, no está conectado al contexto de datos de la cuadrícula de datos. Por lo tanto, las vinculaciones no funcionan con sus propiedades, como Visibility
o Header
etc. (¡aunque estas propiedades son propiedades de dependencia válidas!).
Ahora puedes preguntarte ¿cómo es posible? ¿No se supone que su propiedad de Binding
está vinculada al contexto de datos? Bueno, simplemente es un truco. El enlace realmente no funciona. ¡En realidad, las celdas de la cuadrícula de datos copian / clonan este objeto vinculante y lo utilizan para mostrar sus propios contenidos!
Ahora, volviendo a resolver su problema, supongo que HeaderItems
es una propiedad del objeto que está configurado como el DataContext
de su Vista padre. Podemos conectar el DataContext
de la vista a cualquier DataGridColumn
través de algo que llamamos un ProxyElement
.
El siguiente ejemplo ilustra cómo conectar un elemento secundario lógico como ContextMenu
o DataGridColumn
al DataContext
la Vista padre
<Window x:Class="WpfApplicationMultiThreading.Window5"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vb="http://schemas.microsoft.com/wpf/2008/toolkit"
Title="Window5" Height="300" Width="300" >
<Grid x:Name="MyGrid">
<Grid.Resources>
<FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
</Grid.Resources>
<Grid.DataContext>
<TextBlock Text="Text Column Header" Tag="Tag Columne Header"/>
</Grid.DataContext>
<ContentControl Visibility="Collapsed"
Content="{StaticResource ProxyElement}"/>
<vb:DataGrid AutoGenerateColumns="False" x:Name="MyDataGrid">
<vb:DataGrid.ItemsSource>
<x:Array Type="{x:Type TextBlock}">
<TextBlock Text="1" Tag="1.1"/>
<TextBlock Text="2" Tag="1.2"/>
<TextBlock Text="3" Tag="2.1"/>
<TextBlock Text="4" Tag="2.2"/>
</x:Array>
</vb:DataGrid.ItemsSource>
<vb:DataGrid.Columns>
<vb:DataGridTextColumn
Header="{Binding DataContext.Text,
Source={StaticResource ProxyElement}}"
Binding="{Binding Text}"/>
<vb:DataGridTextColumn
Header="{Binding DataContext.Tag,
Source={StaticResource ProxyElement}}"
Binding="{Binding Tag}"/>
</vb:DataGrid.Columns>
</vb:DataGrid>
</Grid>
</Window>
La vista anterior encontró el mismo error de enlace que ha encontrado si no hubiera implementado el hack de ProxyElement. El ProxyElement es cualquier FrameworkElement que roba el DataContext
de la Vista principal y lo ofrece al elemento secundario lógico, como ContextMenu
o DataGridColumn
. Para eso, debe alojarse como un Content
en un ContentControl
invisible que se encuentra bajo la misma Vista.
Espero que esto te guíe en la dirección correcta.