WPF Hatası: Hedef öğe için geçerli FrameworkElement bulunamıyor


88

Resim DataGridolan bir satırım var. Bu görüntü, bir tetikleyici ile belirli bir duruma bağlıdır. Durum değiştiğinde resmi değiştirmek istiyorum.

Şablonun kendisi, HeaderStylebir DataGridTemplateColumn. Bu şablonda bazı bağlamalar var. İlk ciltleme Günü hangi gün olduğunu gösterir ve Devlet bir tetikleyici ile imajı değiştirir.

Bu özellikler bir ViewModel'de ayarlanır.

Özellikleri:

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

Veri şebekesi:

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

Şimdi projeyi başlattığımda görüntüler gösterilmiyor ve şu hatayı alıyorum:

System.Windows.Data Hatası: 2: Hedef öğe için yöneten FrameworkElement veya FrameworkContentElement bulunamıyor. BindingExpression: Yol = HeaderItems [0]; DataItem = boş; hedef öğe 'DataGridTemplateColumn' (HashCode = 26950454); hedef özellik 'Üstbilgi'dir (' Nesne 'türü)

Bu hata neden gösteriliyor?


4
Yukarıda cevaplanan çözümü kontrol ettim, ancak benim durumumda çalışmıyor. Thomaslevesque.com/2011/03/21/… linkindeki gibi başka bir çözüme geçtiğimde . Fikir çözümle aynı, FrameworkElement kullanmak yerine başka bir sınıf oluşturdular. O zaman benim için çalışıyor.
leo5.

Hata mesajını arayarak burada sona eren diğerleri için: Bu benzer sorunun cevabı, sorunu oldukça kolay bir şekilde
çözmeme

Yanıtlar:


166

Ne yazık ki DataGridColumnaltında barındırılan herhangi bir ağ ağacın DataGrid.Columnsparçası değildir Visualve bu nedenle datagrid'in veri bağlamına bağlı değildir. Bu nedenle bağlamalar, Visibilityveya Headeretc gibi özellikleriyle çalışmaz (bu özellikler geçerli bağımlılık özellikleridir!).

Şimdi bunun nasıl mümkün olduğunu merak edebilirsiniz. Onların değil mi Bindingmülkiyet veri bağlamına bağlı olması gerekiyordu? Bu sadece bir hack. Bağlama gerçekten çalışmıyor. Aslında bu bağlanma nesnesini kopyalayan / klonlayan ve kendi içeriklerini görüntülemek için kullanan , datagrid hücreleridir !

Şimdi sorununuzu çözmeye geri dönelim, bunun üst Görünümünüzün HeaderItemsolarak ayarlanan nesnenin bir özelliği olduğunu varsayıyorum DataContext. Biz yapabilirsiniz bağlamak DataContextherhangi birine bakış DataGridColumndediğimiz şey aracılığıyla ProxyElement.

Aşağıdaki örnek, ContextMenuveya DataGridColumnüst View öğesinin gibi mantıksal bir alt öğeye nasıl bağlanılacağını gösterir.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>

Yukarıdaki görünüm, ProxyElement hackini uygulamadıysam bulduğunuz aynı bağlama hatasıyla karşılaştı. ProxyElement herhangi FrameworkElement olduğunu çaldıDataContext ana Görünüm ve bu şekilde mantıksal çocuğa teklifler bunu gelen ContextMenuveya DataGridColumn. Bunun için , aynı Görünüm altında Contentgörünmez olarak barındırılması gerekir ContentControl.

Umarım bu sizi doğru yönde yönlendirir.


26
Bu hacky proxy işini kullanmak zorunda kalmayı gerçekten hayal kırıklığı yaratan buluyorum ama aynı işlevi başka türlü elde etmenin başka bir yolunu bulamıyorum ... Teşekkürler.
Alex Hope O'Connor

2
Bu benim için işe yaramadı, ancak Josh Smith'in Sanal Dallar hakkındaki makalesini okuduktan sonra, "ProxyElement" DataContext'i ayarlamak için kök denetimime OneWayToSource bağını eklemeyi denedim ve işe yaradı.
jpierson

1
Hayır! Yukarıdaki çözüm .NET 3.5 için çok iyi uyuyor.
WPF-it

1
Bu yanıt eski, ancak yine de .NET 4.0'a karşı kullanışlıdır. DataContext'in sütuna kopyalanmasını içeren birçok cevap işe yaramıyor gibi görünüyor. Görünüm modeli özelliğine bağlı olarak bir sütunu göstermem / gizlemem gerekiyordu ve bu çözüm iyi çalıştı. Ve arkasında hiçbir kod olmaması, kod incelemesinde diplomatik bir olaya neden olmaz.
James_UK_DEV

3
Bilginize Bağlam menüsü aynı değildir ve proxy olmayan bir çalışma vardır. Bağlam menüsü sahip, maruz kalan özelliğine sahiptir Parentoysa DataGridTextColumnonun göstermiyor DataGridOwnerözelliği. Bağlam öğeleri bağlamanın RelativeSource bağlamasıyla nasıl gerçekleştirildiğini, cevabım Bağlam Menüsü Ebeveyn Penceresinin
Veri

8

StaticResourceKabul edilen cevapta olduğu gibi a kullanmaktan biraz daha kısa bir alternatif şudur x:Reference:

<StackPanel>

    <!--Set the DataContext here if you do not want to inherit the parent one-->
    <FrameworkElement x:Name="ProxyElement" Visibility="Collapsed"/>

    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn
                Header="{Binding DataContext.Whatever, Source={x:Reference ProxyElement}}"
                Binding="{Binding ...}" />
        </DataGrid.Columns>
    </DataGrid>

</StackPanel>

Bunun ana avantajı şudur: DataGrid'in atası olmayan bir öğeniz zaten varsa (ör. değilStackPanel yukarıdaki örnekte), sadece ona bir ad verebilir ve olarak kullanmak x:Referencedolayısıyla herhangi mankeni tanımlamaya gerek yok, bunun yerine FrameworkElementhiç.

Bir ataya XamlParseExceptionbaşvurmayı denerseniz, döngüsel bağımlılık nedeniyle çalışma zamanında alırsınız .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.