Ответ 1
Прежде всего DataGridTextColumn
или любые другие поддерживаемые столбцы dataGrid не лежат в визуальном дереве DataGrid
. Следовательно, по умолчанию он не наследует DataContext
от DataGrid
. Но он работает только для Binding
DP и для другого DP на DataGridColumn.
Поскольку они не лежат в одном и том же VisualTree, поэтому любая попытка получить DataContext с помощью RelativeSource
не будет работать, потому что DataGrid не сможет перейти к DataGrid.
Есть два способа добиться этого:
Первый, используя объекты Freezable
- Freezable
, может наследовать DataContext, даже если они не находятся в визуальном или логическом дереве. Таким образом, мы можем воспользоваться этим для нашего использования.
Сначала создайте класс, наследующий от Freezable
и Data
DP, который мы можем использовать для привязки в XAML:
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));
}
Теперь добавьте экземпляр из него в ресурсы DataGrid, чтобы он мог наследовать DataGrid DataContext, а затем может связываться с его Data DP:
<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>
Второй, вы можете обратиться к любому элементу пользовательского интерфейса в XAML, используя ElementName
или x:Reference
. Но ElementName
работает только в одном визуальном дереве, тогда как x: Reference не имеет такого ограничения.
Итак, мы можем использовать это и в наших интересах. Создайте манекен FrameworkElement
в XAML с установленной видимостью для свертывания. FrameworkElement наследует DataContext от родительского контейнера, который может быть Window или UserControl.
И может использовать это в DataGrid:
<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>