gpt4 book ai didi

WPF 数据网格 : Binding DataGridColumn visibility to ContextMenu MenuItems IsChecked (MVVM)

转载 作者:行者123 更新时间:2023-12-02 03:56:05 30 4
gpt4 key购买 nike

我要控制DataGrid通过 ContextMenu 的列可见性用户可以通过右键单击列标题来使用。 ContextMenu显示所有可用列的名称。我正在使用 MVVM 设计模式。

我的问题是:如何绑定(bind)DataGridColumnVisibility属性(property)IsChecked MenuItem 的属性位于ContextMenu .

一些模型代码:

<UserControl.Resources>         
<ContextMenu x:Key="ColumnHeaderContextMenu">
<MenuItem Header="Menu Item..1" IsCheckable="True" />
</ContextMenu>
<Style x:Key="ColumnHeaderStyle"
TargetType="{x:Type toolkit:DataGridColumnHeader}">
<Setter Property="ContextMenu"
Value="{StaticResource ColumnHeaderContextMenu}" />
</Style>
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</UserControl.Resources>

...啦啦啦啦啦

<toolkit:DataGrid x:Name="MyGrid" AutoGenerateColumns="False" 
ItemsSource="{Binding MyCollection, Mode=Default}"
EnableColumnVirtualization="True" IsReadOnly="True"
ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}">
<toolkit:DataGrid.Columns>
<toolkit:DataGridTextColumn Binding="{Binding Path=MyEntry}"
Header="MyEntry" Visibility="{Binding IsChecked, Converter=
{StaticResource booleanToVisibilityConverter}.... />
</toolkit:DataGrid.Columns>
</toolkit:DataGrid>

如果我不清楚,请告诉我,我会尽力详细说明。

干杯,

最佳答案

2021-09-29更新:粘贴了我旧博客中的代码。我已经很多年没有使用 WPF 了,我对它一无所知。该网站对帖子长度有限制,因此我不得不使用 CodePile 分享一些示例代码。请参阅底部的链接以了解使用方法。我相信这个想法是我制作的示例适用于许多场景,而不仅仅是自动生成的列。我正在开发一个项目,其中的列直到运行时才知道并且可以动态更改。另请注意,“眼睛”图形有一个 png 文件,您可能需要自己的文件。

DataGridAPs.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
using System.Windows.Media;
using Microsoft.Windows.Controls;
using Microsoft.Windows.Controls.Primitives;

namespace CanUserHideColumnDemo
{
public static class DataGridAPs
{
#region HideColumns
#region HideColumnsHeader
public static readonly DependencyProperty HideColumnsHeaderProperty =
DependencyProperty.RegisterAttached("HideColumnsHeader",
typeof(object), typeof(DataGridAPs));

public static object GetHideColumnsHeader(DataGrid obj)
{
return obj.GetValue(HideColumnsHeaderProperty);
}

public static void SetHideColumnsHeader(DataGrid obj, object value)
{
obj.SetValue(HideColumnsHeaderProperty, value);
}
#endregion HideColumnsHeader

#region HideColumnsHeaderTemplate
public static readonly DependencyProperty HideColumnsHeaderTemplateProperty =
DependencyProperty.RegisterAttached("HideColumnsHeaderTemplate",
typeof(DataTemplate), typeof(DataGridAPs));

public static DataTemplate GetHideColumnsHeaderTemplate(DataGrid obj)
{
return (DataTemplate)obj.GetValue(HideColumnsHeaderTemplateProperty);
}

public static void SetHideColumnsHeaderTemplate(DataGrid obj, DataTemplate value)
{
obj.SetValue(HideColumnsHeaderTemplateProperty, value);
}
#endregion HideColumnsHeaderTemplate

#region HideColumnsIcon
public static readonly DependencyProperty HideColumnsIconProperty =
DependencyProperty.RegisterAttached("HideColumnsIcon",
typeof(object), typeof(DataGridAPs));

public static object GetHideColumnsIcon(DataGrid obj)
{
return obj.GetValue(HideColumnsIconProperty);
}

public static void SetHideColumnsIcon(DataGrid obj, object value)
{
obj.SetValue(HideColumnsIconProperty, value);
}
#endregion HideColumnsIcon

#region CanUserHideColumns
public static readonly DependencyProperty CanUserHideColumnsProperty =
DependencyProperty.RegisterAttached("CanUserHideColumns",
typeof(bool), typeof(DataGridAPs),
new UIPropertyMetadata(false, OnCanUserHideColumnsChanged));

public static bool GetCanUserHideColumns(DataGrid obj)
{
return (bool)obj.GetValue(CanUserHideColumnsProperty);
}

public static void SetCanUserHideColumns(DataGrid obj, bool value)
{
obj.SetValue(CanUserHideColumnsProperty, value);
}

private static void OnCanUserHideColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = d as DataGrid;
if (dataGrid == null)
return;

if ((bool)e.NewValue == false)
{
dataGrid.Loaded -= new RoutedEventHandler(dataGrid_Loaded);
RemoveAllItems(dataGrid);
return;
}

if (!dataGrid.IsLoaded)
{
dataGrid.Loaded -= new RoutedEventHandler(dataGrid_Loaded);
dataGrid.Loaded += new RoutedEventHandler(dataGrid_Loaded);
}
else
SetupColumnHeaders(dataGrid);
}

private static void dataGrid_Loaded(object sender, RoutedEventArgs e)
{
DataGrid dataGrid = sender as DataGrid;
if (dataGrid == null)
return;

if (BindingOperations.IsDataBound(dataGrid, DataGrid.ItemsSourceProperty))
{
Binding b = BindingOperations.GetBinding(dataGrid, DataGrid.ItemsSourceProperty);
dataGrid.TargetUpdated += new EventHandler<DataTransferEventArgs>(dataGrid_TargetUpdated);

string xaml = XamlWriter.Save(b);
Binding b2 = XamlReader.Parse(xaml) as Binding;
if (b2 != null)
{
b2.NotifyOnTargetUpdated = true;
BindingOperations.ClearBinding(dataGrid, DataGrid.ItemsSourceProperty);
BindingOperations.SetBinding(dataGrid, DataGrid.ItemsSourceProperty, b2);
}
}
else
SetupColumnHeaders(dataGrid);
}

private static void dataGrid_TargetUpdated(object sender, DataTransferEventArgs e)
{
if (e.Property != DataGrid.ItemsSourceProperty)
return;

DataGrid dataGrid = sender as DataGrid;
if (dataGrid == null)
return;

EventHandler handler = null;
handler = delegate
{
RemoveAllItems(dataGrid);
if (SetupColumnHeaders(dataGrid))
dataGrid.LayoutUpdated -= handler;
};

dataGrid.LayoutUpdated += handler;
}

private static DataGridColumnHeader[] GetColumnHeaders(DataGrid dataGrid)
{
if (dataGrid == null)
return null;

dataGrid.UpdateLayout();
DataGridColumnHeader[] columnHeaders = CustomVisualTreeHelper<DataGridColumnHeader>.FindChildrenRecursive(dataGrid);


return (from DataGridColumnHeader columnHeader in columnHeaders
where columnHeader != null && columnHeader.Column != null
select columnHeader).ToArray();
}

private static string GetColumnName(DataGridColumn column)
{
if (column == null)
return string.Empty;

if (column.Header != null)
return column.Header.ToString();
else
return string.Format("Column {0}", column.DisplayIndex);
}

private static MenuItem GenerateItem(DataGrid dataGrid, DataGridColumn column)
{
if (column == null)
return null;

MenuItem item = new MenuItem();
item.Tag = column;

item.Header = GetColumnName(column);
if (string.IsNullOrEmpty(item.Header as string))
return null;

item.ToolTip = string.Format("Toggle column '{0}' visibility.", item.Header);

item.IsCheckable = true;
item.IsChecked = column.Visibility == Visibility.Visible;

item.Checked += delegate
{
SetItemIsChecked(dataGrid, column, true);
};

item.Unchecked += delegate
{
SetItemIsChecked(dataGrid, column, false);
};

return item;
}

public static MenuItem[] GetAttachedItems(DataGridColumnHeader columnHeader)
{
if (columnHeader == null || columnHeader.ContextMenu == null)
return null;

ItemsControl itemsContainer = (from object i in columnHeader.ContextMenu.Items
where i is MenuItem && ((MenuItem)i).Tag != null && ((MenuItem)i).Tag.ToString() == "ItemsContainer"
select i).FirstOrDefault() as MenuItem;

if (itemsContainer == null)
itemsContainer = columnHeader.ContextMenu;

return (from object i in itemsContainer.Items
where i is MenuItem && ((MenuItem)i).Tag is DataGridColumn
select i).Cast<MenuItem>().ToArray();
}

private static DataGridColumn GetColumnFromName(DataGrid dataGrid, string columnName)
{
if (string.IsNullOrEmpty(columnName))
return null;

foreach (DataGridColumn column in dataGrid.Columns)
{
if (GetColumnName(column) == columnName)
return column;
}

return null;
}

private static DataGridColumnHeader GetColumnHeaderFromColumn(DataGrid dataGrid, DataGridColumn column)
{
if (dataGrid == null || column == null)
return null;

DataGridColumnHeader[] columnHeaders = GetColumnHeaders(dataGrid);
return (from DataGridColumnHeader columnHeader in columnHeaders
where columnHeader.Column == column
select columnHeader).FirstOrDefault();
}

public static void RemoveAllItems(DataGrid dataGrid)
{
if (dataGrid == null)
return;

foreach (DataGridColumn column in dataGrid.Columns)
{
RemoveAllItems(dataGrid, column);
}
}

public static void RemoveAllItems(DataGrid dataGrid, DataGridColumn column)
{
if (dataGrid == null || column == null)
return;

DataGridColumnHeader columnHeader = GetColumnHeaderFromColumn(dataGrid, column);
List<MenuItem> itemsToRemove = new List<MenuItem>();

if (columnHeader == null)
return;

// Mark items and/or items container for removal.
if (columnHeader.ContextMenu != null)
{
foreach (object item in columnHeader.ContextMenu.Items)
{
if (item is MenuItem && ((MenuItem)item).Tag != null
&& (((MenuItem)item).Tag.ToString() == "ItemsContainer" || ((MenuItem)item).Tag is DataGridColumn))
itemsToRemove.Add((MenuItem)item);
}
}

// Remove items and/or items container.
foreach (MenuItem item in itemsToRemove)
{
columnHeader.ContextMenu.Items.Remove(item);
}
}

public static void ResetupColumnHeaders(DataGrid dataGrid)
{
RemoveAllItems(dataGrid);
SetupColumnHeaders(dataGrid);
}

private static void SetItemIsChecked(DataGrid dataGrid, DataGridColumn column, bool isChecked)
{
if (dataGrid == null || column == null)
return;

// Deny request if there are no other columns visible. Otherwise,
// they'd have no way of changing the visibility of any columns
// again.
//if (!isChecked && (from DataGridColumn c in dataGrid.Columns
// where c.Visibility == Visibility.Visible
// select c).Count() < 2)
// return;

if (isChecked && column.Visibility != Visibility.Visible)
{
ShowColumn(dataGrid, column);
}
else if (!isChecked)
column.Visibility = Visibility.Hidden;

DataGridColumnHeader[] columnHeaders = GetColumnHeaders(dataGrid);
ItemsControl itemsContainer = null;
object containerHeader = GetHideColumnsHeader(dataGrid);

foreach (DataGridColumnHeader columnHeader in columnHeaders)
{
itemsContainer = null;
if (columnHeader != null)
{
if (columnHeader.ContextMenu == null)
continue;

itemsContainer = (from object i in columnHeader.ContextMenu.Items
where i is MenuItem && ((MenuItem)i).Header == containerHeader
select i).FirstOrDefault() as MenuItem;
}

if (itemsContainer == null)
itemsContainer = columnHeader.ContextMenu;

foreach (object item in itemsContainer.Items)
{
if (item is MenuItem && ((MenuItem)item).Tag != null && ((MenuItem)item).Tag is DataGridColumn
&& ((MenuItem)item).Header.ToString() == GetColumnName(column))
{
((MenuItem)item).IsChecked = isChecked;
}
}
}
}

private static void SetupColumnHeader(DataGridColumnHeader columnHeader)
{
if (columnHeader == null)
return;

DataGrid dataGrid = CustomVisualTreeHelper<DataGrid>.FindAncestor(columnHeader);
if (dataGrid == null)
return;

DataGridColumnHeader[] columnHeaders = GetColumnHeaders(dataGrid);
if (columnHeaders == null)
return;

SetupColumnHeader(dataGrid, columnHeaders, columnHeader);
}

private static void SetupColumnHeader(DataGrid dataGrid, DataGridColumnHeader[] columnHeaders, DataGridColumnHeader columnHeader)
{
if (columnHeader.ContextMenu == null)
columnHeader.ContextMenu = new ContextMenu();

ItemsControl itemsContainer = null;
itemsContainer = columnHeader.ContextMenu;

object containerHeader = GetHideColumnsHeader(dataGrid);
if (containerHeader != null)
{
MenuItem ic = (from object i in columnHeader.ContextMenu.Items
where i is MenuItem && ((MenuItem)i).Tag != null && ((MenuItem)i).Tag.ToString() == "ItemsContainer"
select i).FirstOrDefault() as MenuItem;

if (ic == null)
{
itemsContainer = new MenuItem()
{
Header = containerHeader,
HeaderTemplate = GetHideColumnsHeaderTemplate(dataGrid) as DataTemplate,
Icon = GetHideColumnsIcon(dataGrid),
Tag = "ItemsContainer"
};
columnHeader.ContextMenu.Items.Add(itemsContainer);
}
else
return;
}

foreach (DataGridColumnHeader columnHeader2 in columnHeaders)
{
if (columnHeader2 != columnHeader
&& itemsContainer is ContextMenu
&& columnHeader2.ContextMenu == itemsContainer)
{
continue;
}
itemsContainer.Items.Add(GenerateItem(dataGrid, columnHeader2.Column));
}
}

public static bool SetupColumnHeaders(DataGrid dataGrid)
{
DataGridColumnHeader[] columnHeaders = GetColumnHeaders(dataGrid);
if (columnHeaders == null || columnHeaders.Count() == 0)
return false;

RemoveAllItems(dataGrid);
columnHeaders = GetColumnHeaders(dataGrid);
foreach (DataGridColumnHeader columnHeader in columnHeaders)
{
SetupColumnHeader(dataGrid, columnHeaders, columnHeader);
}

return true;
}

/// <summary>
/// Shows a column within the datagrid, which is not straightforward
/// because the datagrid not only hides a column when you tell it to
/// do so, but it also completely destroys its associated column
/// header. Meaning we need to set it up again. Before we can do
/// so we have to turn all columns back on again so we can get a
/// complete list of their column headers, then turn them back off
/// again.
/// </summary>
/// <param name="dataGrid"></param>
/// <param name="column"></param>
private static void ShowColumn(DataGrid dataGrid, DataGridColumn column)
{
if (dataGrid == null || column == null)
return;

column.Visibility = Visibility.Visible;

// Turn all columns on, but store their original visibility so we
// can restore it after we're done.
Dictionary<DataGridColumn, Visibility> vis = new Dictionary<DataGridColumn, Visibility>();
foreach (DataGridColumn c in dataGrid.Columns)
{
vis.Add(c, c.Visibility);
c.Visibility = Visibility.Visible;
}
dataGrid.UpdateLayout();

DataGridColumnHeader columnHeader = GetColumnHeaderFromColumn(dataGrid, column);
SetupColumnHeader(columnHeader);

foreach (DataGridColumn c in vis.Keys)
{
if ((Visibility)vis[c] != Visibility.Visible)
{
c.Visibility = (Visibility)vis[c];
}
}
dataGrid.UpdateLayout();

// Now we need to uncheck items that are associated with hidden
// columns.
SyncItemsOnColumnHeader(columnHeader);
}

private static void SyncItemsOnColumnHeader(DataGridColumnHeader columnHeader)
{
bool isVisible;
foreach (MenuItem item in GetAttachedItems(columnHeader))
{
if (item.Tag is DataGridColumn)
{
isVisible = ((DataGridColumn)item.Tag).Visibility == Visibility.Visible ? true : false;
if (item.IsChecked != isVisible)
{
item.IsChecked = isVisible;
}
}
}
}
#endregion CanUserHideColumns

#region CustomVisualTreeHelper
private static class CustomVisualTreeHelper<TReturn> where TReturn : DependencyObject
{
public static TReturn FindAncestor(DependencyObject descendant)
{
DependencyObject parent = descendant;
while (parent != null && !(parent is TReturn))
{
parent = VisualTreeHelper.GetParent(parent);
}

if (parent != null)
{
return (TReturn)parent;
}
return default(TReturn);
}

public static TReturn FindChild(DependencyObject parent)
{
int childCount = VisualTreeHelper.GetChildrenCount(parent);
DependencyObject child = null;

for (int childIndex = 0; childIndex < childCount; childIndex++)
{
child = VisualTreeHelper.GetChild(parent, childIndex);
if (child is TReturn)
{
return (TReturn)(object)child;
}
}
return default(TReturn);
}

public static TReturn FindChildRecursive(DependencyObject parent)
{
int childCount = VisualTreeHelper.GetChildrenCount(parent);
DependencyObject child = null;

for (int childIndex = 0; childIndex < childCount; childIndex++)
{
child = VisualTreeHelper.GetChild(parent, childIndex);
if (child is TReturn)
{
return (TReturn)(object)child;
}
else
{
child = CustomVisualTreeHelper<TReturn>.FindChildRecursive(child);
if (child is TReturn)
{
return (TReturn)(object)child;
}
}
}
return default(TReturn);
}

public static TReturn[] FindChildren(DependencyObject parent)
{
int childCount = VisualTreeHelper.GetChildrenCount(parent);
DependencyObject child = null;
List<TReturn> children = new List<TReturn>(childCount);

for (int childIndex = 0; childIndex < childCount; childIndex++)
{
child = VisualTreeHelper.GetChild(parent, childIndex);
if (child is TReturn)
{
children[childIndex] = (TReturn)(object)child;
}
}
return children.ToArray();
}

public static TReturn[] FindChildrenRecursive(DependencyObject parent)
{
int childCount = VisualTreeHelper.GetChildrenCount(parent);
DependencyObject child = null;
List<TReturn> children = new List<TReturn>();

for (int childIndex = 0; childIndex < childCount; childIndex++)
{
child = VisualTreeHelper.GetChild(parent, childIndex);
if (child is TReturn)
{
children.Add((TReturn)(object)child);
}

children.AddRange(CustomVisualTreeHelper<TReturn>.FindChildrenRecursive(child));
}
return children.ToArray();
}
}
#endregion CustomVisualTreeHelper
#endregion HideColumns
}
}

Window1.xaml Window1.xaml.cs

关于WPF 数据网格 : Binding DataGridColumn visibility to ContextMenu MenuItems IsChecked (MVVM),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1560871/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com