Ошибка WPF: не удается найти управляющий FrameworkElement для целевого элемента - PullRequest
74 голосов
/ 05 октября 2011

У меня есть сетка данных со строкой с изображением. Это изображение связано с триггером для определенного состояния. Когда состояние меняется, я хочу изменить изображение.

Сам шаблон устанавливается в HeaderStyle объекта DataGridTemplateColumn. Этот шаблон имеет некоторые привязки. Первый связующий день показывает, какой сегодня день, и штат меняет изображение с помощью триггера.

Эти свойства установлены в ViewModel.

Особенности:

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

Datagrid:

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

Заголовок DatagridStyleTemplate:

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

Теперь, когда я запускаю проект, изображения не отображаются, и я получаю эту ошибку:

System.Windows.Data Ошибка: 2: не удается найти управляющий FrameworkElement или FrameworkContentElement для целевого элемента. BindingExpression: Path = HeaderItems [0]; DataItem = NULL; целевой элемент - «DataGridTemplateColumn» (HashCode = 26950454); Свойство target - «Заголовок» (тип «Объект»)

Почему отображается эта ошибка?

1 Ответ

141 голосов
/ 05 октября 2011

К сожалению, любой DataGridColumn, размещенный в DataGrid.Columns, не является частью дерева Visual и поэтому не связан с контекстом данных сетки данных. Таким образом, привязки не работают со своими свойствами, такими как Visibility или Header и т. Д. (Хотя эти свойства являются допустимыми свойствами зависимости!).

Теперь вы можете задаться вопросом, как это возможно? Разве их свойство Binding не должно быть связано с контекстом данных? Ну, это просто взломать. Привязка на самом деле не работает. На самом деле именно ячейки данных копируют / клонируют этот объект привязки и используют его для отображения собственного содержимого!

Итак, теперь, возвращаясь к решению вашей проблемы, я предполагаю, что HeaderItems - это свойство объекта, которое установлено как DataContext вашего родительского View. Мы можем соединить DataContext вида с любым DataGridColumn через то, что мы называем ProxyElement.

В приведенном ниже примере показано, как подключить логический дочерний элемент, например ContextMenu или DataGridColumn, к родительскому представлению DataContext

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

Приведенное выше представление обнаружило ту же ошибку привязки, которую вы обнаружили, если я не реализовал взлом ProxyElement. ProxyElement - это любой FrameworkElement, который крадет DataContext из основного представления и предлагает его логическому дочернему элементу, например ContextMenu или DataGridColumn. Для этого он должен быть размещен как Content в невидимом ContentControl, который находится под тем же представлением.

Надеюсь, это направит вас в правильном направлении.

...