Saya punya DataGrid
dengan baris yang memiliki gambar. Gambar ini terikat dengan pemicu ke keadaan tertentu. Ketika keadaan berubah, saya ingin mengubah gambar.
Template itu sendiri disetel di HeaderStyle
dari a DataGridTemplateColumn
. Template ini memiliki beberapa binding. Hari penjilidan pertama menunjukkan hari apa ini dan Negara bagian mengubah gambar dengan pemicu.
Properti ini disetel dalam ViewModel.
Properti:
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,
});
}
Kisi Data:
<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>
Sekarang ketika saya memulai proyek, gambar tidak muncul dan saya mendapatkan kesalahan ini:
System.Windows.Data Error: 2: Tidak dapat menemukan FrameworkElement yang mengatur atau FrameworkContentElement untuk elemen target. BindingExpression: Path = HeaderItems [0]; DataItem = null; elemen target adalah 'DataGridTemplateColumn' (HashCode = 26950454); properti target adalah 'Header' (ketik 'Object')
Mengapa kesalahan ini muncul?
Jawaban:
Sayangnya, setiap
DataGridColumn
host di bawahDataGrid.Columns
bukan bagian dariVisual
pohon dan karena itu tidak terhubung ke konteks data dari datagrid. Jadi binding tidak berfungsi dengan propertinya sepertiVisibility
atauHeader
dll (meskipun properti ini adalah properti dependensi yang valid!).Sekarang Anda mungkin bertanya-tanya bagaimana mungkin? Bukankah
Binding
properti mereka seharusnya terikat pada konteks data? Yah itu hanyalah sebuah retasan. Pengikatan tidak benar-benar berfungsi. Ini sebenarnya adalah sel datagrid yang menyalin / mengkloning objek pengikat ini dan menggunakannya untuk menampilkan isinya sendiri!Jadi sekarang kembali ke pemecahan masalah Anda, saya berasumsi bahwa itu
HeaderItems
adalah properti objek yang disetel sebagaiDataContext
Tampilan orang tua Anda. Kita dapat menghubungkanDataContext
tampilan ke apapunDataGridColumn
melalui sesuatu yang kita sebut aProxyElement
.Contoh di bawah ini mengilustrasikan cara menghubungkan anak logis seperti
ContextMenu
atauDataGridColumn
ke Tampilan indukDataContext
<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>
Tampilan di atas mengalami kesalahan pengikatan yang sama dengan yang Anda temukan jika saya tidak menerapkan peretasan ProxyElement. The ProxyElement adalah setiap FrameworkElement yang mencuri itu
DataContext
dari View utama dan menawarkan kepada anak logis sepertiContextMenu
atauDataGridColumn
. Untuk itu harus dihosting sebagai aContent
into a invisibleContentControl
yang berada di bawah View yang sama.Saya harap ini membimbing Anda ke arah yang benar.
sumber
Parent
sedangkan yangDataGridTextColumn
tidak mengeksposDataGridOwner
propertinya. Lihat bagaimana pengikatan item konteks dilakukan melalui pengikatan RelativeSource dalam jawaban saya Menu Konteks Mengikat ke Teksdata Jendela IndukAlternatif yang sedikit lebih pendek untuk menggunakan a
StaticResource
seperti pada jawaban yang diterima adalahx: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>
Keuntungan utama dari ini adalah: jika Anda sudah memiliki sebuah elemen yang tidak nenek moyang datagrid (yaitu tidak yang
StackPanel
dalam contoh di atas), Anda hanya bisa memberikan nama dan menggunakannya sebagaix:Reference
gantinya, maka tidak perlu mendefinisikan boneka setiapFrameworkElement
sama sekali.Jika Anda mencoba mereferensikan leluhur, Anda akan mendapatkan
XamlParseException
waktu proses karena ketergantungan siklis.sumber