2011-10-05 13 views
57

Mam datagrid z wierszem, który ma obraz. Ten obraz jest związany z wyzwalaczem do pewnego stanu. Kiedy stan się zmienia, chcę zmienić obraz.Błąd WPF: Nie można znaleźć elementu FrameworkElement dla elementu docelowego

Sam szablon jest ustawiony na HeaderStyle klasy DataGridTemplateColumn. Ten szablon ma kilka powiązań. Pierwszy dzień wiążący pokazuje, jaki jest dzień, a stan zmienia obraz za pomocą spustu.

Te właściwości są ustawiane w ViewModel.

Właściwości:

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> 

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> 

Teraz kiedy uruchomieniem projektu obrazy nie pokazuje i otrzymuję ten błąd:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=HeaderItems[0]; DataItem=null; target element is 'DataGridTemplateColumn' (HashCode=26950454); target property is 'Header' (type 'Object')

Dlaczego ten błąd jest wyświetlany?

+1

Sprawdziłem powyżej rozwiązanie, ale nie działa w moim przypadku. Kiedy przełączam się na inne rozwiązanie, jak w linku http: //www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-dziedziczone /. Pomysł jest taki sam jak rozwiązanie, zamiast używać FrameworkElement, stworzyli kolejną klasę. To działa dla mnie. – leo5th

+0

Dla innych osób kończących się tutaj, szukając komunikatu o błędzie: Odpowiedź na to podobne pytanie pomogła mi rozwiązać problem dość łatwo http://stackoverflow.com/a/18657986/4961688 –

Odpowiedz

118

Niestety, każdy DataGridColumn hostowany pod numerem DataGrid.Columns nie jest częścią drzewa Visual i dlatego nie jest połączony z kontekstem danych datagridu. Zatem wiązania nie działają z ich właściwościami, takimi jak Visibility lub Header itd. (Chociaż te właściwości są poprawnymi właściwościami zależności!).

Teraz możesz zastanawiać się, czy to możliwe? Czy ich własność nie ma być związana z kontekstem danych? Cóż, to po prostu hack. Wiązanie tak naprawdę nie działa. W rzeczywistości jest to komórka datagrid, która to obiekt wiązania używa go do wyświetlania własnych treści!

Wracając teraz do rozwiązania problemu, zakładam, że HeaderItems jest właściwością obiektu ustawionego jako DataContext w widoku macierzystym. Możemy może podłączyć DataContext widoku do dowolnego DataGridColumn przez coś, co nazywamy ProxyElement.

Poniższy przykład ilustruje sposób podłączenia logicznego dziecka takiego jak ContextMenu lub DataGridColumn do rodzica Zobacz na 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> 

Widok powyżej napotkał ten sam błąd wiązania że znalazłeś jeśli nie mam wdrożyła Zażądaj hakowania ProxyElement. ProxyElement to dowolny obiekt FrameworkElement, który wykrada z widoku głównego i oferuje go logicznemu elementowi potomnemu, na przykład ContextMenu lub DataGridColumn. W tym celu musi być hostowany jako Content w niewidoczny ContentControl, który znajduje się w tym samym widoku.

Mam nadzieję, że to cię poprowadzi we właściwym kierunku.

+17

Uważam, że muszę używać tego hacky proxy Naprawdę rozczarowujące, ale nie mogę znaleźć innego sposobu na osiągnięcie tej samej funkcjonalności w przeciwnym razie ... Dziękuję. –

+2

To nie działało dla mnie, ale po przeczytaniu artykułu Josha Smitha o wirtualnych gałęziach próbowałem dodać wiązanie OneWayToSource na moim kontrolerze root, aby ustawić DataContext "ProxyElement" i to zadziałało. – jpierson

+0

@jpierson, używasz 'Silverlight'? Coz działa dla mnie w 'WPF'. Dla silverlight implementacja jest inna. –

Powiązane problemy