问题
I am trying to hide colummns in a Datagrid
(bound to a DataTable
) with DataTrigger
. So that the user can choose which columns are displayed. My problem is that this only works once. Normaly I would say that I need the INotifyPropertyChanged
, however my ContextMenu
is defined in XAML so I am not sure if and how to do that.
Here my XAML
<ContextMenu >
....
<MenuItem Header="Apply" x:Name="ButtonApply" />
</ContextMenu>
<DataGrid ItemsSource="{Binding Path=TabDataTable}" AutoGenerateColumns="True" IsReadOnly="True" SelectionUnit="CellOrRowHeader" Margin="-5,-4,-5,-4" AlternatingRowBackground="Gainsboro" x:Name="MainDataGrid">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ButtonApply, Path=IsPressed}" Value="True">
<Setter Property="Visibility">
<Setter.Value>
<!--<Binding Path=" DataContext.IsTemplateColumnVisibile, Source={StaticResource ProxyElement}, Converter={StaticResource BooleanToVisibilityConverter}}" />-->
<MultiBinding Converter="{StaticResource BooleanToVisibilityConverter}">
<Binding Path="Column"
RelativeSource="{RelativeSource Self}"/>
<Binding Path="DataContext.visibility"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
Here the Converter
: (Sry for the misleading name)
public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value[0] == null)
{
return null;
}
if ((((ObservableCollection<bool>)value[1]).ToArray())[((System.Windows.Controls.DataGridTextColumn)value[0]).DisplayIndex])
{
//Column Visibility
((System.Windows.Controls.DataGridTextColumn)value[0]).Visibility = Visibility.Visible;
//Header Visibility
return Visibility.Visible;
}
((System.Windows.Controls.DataGridTextColumn)value[0]).Visibility = Visibility.Collapsed;
return Visibility.Collapsed;
}
If there is a better way to accomplish this, please feel free to point me in the right direction.
回答1:
You can use an Attached Property to control Column visibility and bind it to a list implementing INotifyPropertyChanged.
<Style TargetType="DataGrid">
<Setter Property="local:DataGridHelper.VisibilityList"
Value="{Binding NotifyingList}"/>
</Style>
Attached Property
public class DataGridHelper : DependencyObject
{
public static List<bool> GetVisibilityList(
DependencyObject obj)
{
return (List<bool>)obj.GetValue(VisibilityListProperty);
}
public static void SetVisibilityList(
DependencyObject obj, List<bool> value)
{
obj.SetValue(VisibilityListProperty, value);
}
public static readonly DependencyProperty
VisibilityListProperty =
DependencyProperty.RegisterAttached("VisibilityList",
typeof(List<bool>), typeof(DataGridHelper),
new PropertyMetadata(VisibilityListChanged));
private static void VisibilityListChanged(DependencyObject d,
DependencyPropertyChangedEventArgs args)
{
var grid = d as DataGrid;
if (grid == null
|| grid.Columns.Count == 0
|| grid.Columns[0].DisplayIndex == -1) return;
var visibilities = (List<bool>)grid.GetValue(VisibilityListProperty);
foreach (var column in grid.Columns)
{
if ((bool)visibilities[column.DisplayIndex])
column.Visibility = Visibility.Visible;
else
column.Visibility = Visibility.Collapsed;
}
}
}
Note that column.DisplayIndex is used, so DataGrid.CanUserReorderColumns should be false. This should get you going, I suggest you try it out before you tackle the ContextMenu.
来源:https://stackoverflow.com/questions/37876356/wpf-datatrigger-bound-to-a-contextmenu-menuitem-works-only-once