Erstens DataGridTextColumn
oder andere unterstützte dataGrid-Spalten liegen nicht im visuellen Baum vonDataGrid
. Daher erbt esDataContext
DataGrid
standardmäßig nicht von . Es funktioniert jedoch nur für Binding
DP und nicht für andere DPs in DataGridColumn.
Da sie nicht in demselben VisualTree liegen, funktioniert jeder Versuch, DataContext zu verwenden RelativeSource
, nicht so gut, da DataGrid nicht in der Lage ist, zu DataGrid zu wechseln.
Es gibt jedoch zwei Möglichkeiten, dies zu erreichen:
Erste Verwendung von Freezable
Klassenobjekten Freezable
kann den DataContext erben, auch wenn sie sich nicht im visuellen oder logischen Baum befinden. So können wir das für unsere Nutzung nutzen.
Erstellen Sie zuerst eine Klasse, die von Freezable
und Data
DP erbt, die wir zum Binden in XAML verwenden können:
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object),
typeof(BindingProxy));
}
Fügen Sie nun eine Instanz davon in DataGrid-Ressourcen hinzu, damit es den DataContext von DataGrid erben und dann mit seinem Data DP binden kann:
<DataGrid>
<DataGrid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Visibility="{Binding Data.MyColumnVisibility,
Source={StaticResource proxy}}"/>
</DataGrid.Columns>
</DataGrid>
Zweitens können Sie mit ElementName
oder auf jedes UI-Element in XAML verweisen x:Reference
. Funktioniert jedoch ElementName
nur im selben visuellen Baum, während x: Reference keine solche Einschränkung aufweist.
Das können wir also auch zu unserem Vorteil nutzen. Erstellen Sie einen Dummy FrameworkElement
in XAML, wobei die Sichtbarkeit auf "Reduziert" gesetzt ist. FrameworkElement erbt DataContext von seinem übergeordneten Container, der Window oder UserControl sein kann.
Und kann das in DataGrid verwenden:
<FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Test"
Binding="{Binding Name}"
Visibility="{Binding DataContext.IsEnable,
Source={x:Reference dummyElement}}"/>
</DataGrid.Columns>
</DataGrid>
x:Name
und einen Verweis auf seineVisibility
Eigenschaft geben kann. Nicht wirklich geradlinig, mehr seitwärts drehend, aber immer noch einfach. Ich denke, wenn Sie an die DataContext-Eigenschaft des referenzierten Elements binden, "entführen" Sie das andere Element, um seinen DataContext für die ansonsten nicht erreichbare DataGridColumn freizugeben, oder? Das DummyElement ist nur die Brücke.x:Reference
- in WPF 4.0 kann zumindest für Visual Studio 2010 immer noch eine Ausnahme auftreten :Service provider is missing the INameResolver service
, kann ignoriert werden. Und so wie ich es verstehe, wurde es in WPF 4.5 behoben.<Window.Resources> <ResourceDictionary> <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}" /> </ResourceDictionary> </Window.Resources> <!-- Necessary for binding to resolve: adds reference to ProxyElement to tree.--> <ContentControl Content="{StaticResource ProxyElement}" Visibility="Collapsed" /> <mch:MCHDataGrid Height="350" AutoGenerateColumns="False" FlowDirection="LeftToRight" ItemsSource="{Binding PayStructures}" SelectedItem="{Binding SelectedItem}"> <DataGrid.Columns> <DataGridTemplateColumn Width="70" Header="name" IsReadOnly="True" Visibility="{Binding DataContext.IsShowName, Source={StaticResource ProxyElement}}"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding FieldName}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </mch:MCHDataGrid>
Beispiel für eine gebundene Eigenschaft im Ansichtsmodell:
quelle
<TextBlock Text="{Binding DataContext, Source={StaticResource ProxyElement}}"></TextBlock>