wpf 当 AutoGenerateColumns 设置为 True 时,如何停止在 DataGrid 中生成的特定列?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15830214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to stop a specific column to be generated in DataGrid when the AutoGenerateColumns is set to True?
提问by Haritha
I have bound a ObservableCollection to a DataGridand set the AutoGenerateColumnsto true in a WPF with MVVM application.
我已将 ObservableCollection 绑定到 aDataGrid并AutoGenerateColumns在带有 MVVM 应用程序的 WPF 中设置为 true。
Then how can I stopa specific columnto be appeared in the DataGrid?
那我怎么才能stop一specific column要在DataGrid中出现?
I have seen a same question here. But I'm looking for more MVVM approach.
我在这里看到了同样的问题。但我正在寻找更多的 MVVM 方法。
回答by Rachel
MVVM means your UI and your Data layers are completely separate, with the View layer merely being a visual reflection of your Data layer.
MVVM 意味着您的 UI 和您的数据层是完全独立的,而视图层只是您数据层的视觉反映。
So the "MVVM way" of excluding a column depends on where this exclusion should occur:
因此,排除列的“MVVM 方式”取决于此排除发生的位置:
If your Data layer is supposed to exclude a column, remove that column from the data layer.
This typically means modifying the collection your
DataGrid.ItemsSourceis binding to so it no longer includes the data that should not be visible.Or depending on what your application is for and what counts as "application logic", it may mean maintaining a
stringorList<string>of columns to exclude, and have the View find some way of binding to those strings and modifying it's display to exclude those columns (a custom dependency property, a converter, re-use of theTagproperty +AutoGeneratingColumnevent, triggers, etc)If your View layer is supposed to exclude a column, remove that column from the view layer.
This is usually done by setting
AutoGenerateColumns="False"and specifying your<DataGrid.Columns>yourself, however you can also exclude the column from the View layer using the AutoGeneratingColumnevent of theDataGrid, and cancelling the generation of the column if it'sColumnNameequals to the value you want to exclude, like the question you linkedsuggested.private void DataGrid_AutoGeneratingColumn( object sender, DataGridAutoGeneratingColumnEventArgs e) { if ((string)e.Column.Header == "ID") { e.Cancel = true; } }
如果您的数据层应该排除一列,请从数据层中删除该列。
这通常意味着修改您
DataGrid.ItemsSource要绑定的集合,使其不再包含不应该可见的数据。或者根据您的应用程序的用途以及什么算作“应用程序逻辑”,这可能意味着维护一个
string或List<string>多个要排除的列,并让视图找到某种方式绑定到这些字符串并修改它的显示以排除这些列(a自定义依赖属性、转换器、重用Tag属性 +AutoGeneratingColumn事件、触发器等)如果您的视图层应该排除一列,请从视图层中删除该列。
这通常是通过设置
AutoGenerateColumns="False"和指定您<DataGrid.Columns>自己来完成的,但是您也可以使用 的AutoGeneratingColumn事件从 View 层中排除该列,DataGrid如果它ColumnName等于您要排除的值,则取消该列的生成,如问题你链接的建议。private void DataGrid_AutoGeneratingColumn( object sender, DataGridAutoGeneratingColumnEventArgs e) { if ((string)e.Column.Header == "ID") { e.Cancel = true; } }
Remember, the whole point of MVVM is to separate your UI and Data layers. There's absolutely nothing wrong with using code-behind the view in MVVM, providing that code is related to UI-specific logic only, and not data/application-specific logic
请记住,MVVM 的重点是分离您的 UI 和数据层。在 MVVM 中使用代码隐藏视图绝对没有错,前提是代码仅与 UI 特定的逻辑相关,而不是数据/应用程序特定的逻辑
回答by NSGaga-mostly-inactive
Or you could do this...
或者你可以这样做...
You can usually work around this using attached properties to bind events to
Command-s - and then straight to your view-model.
您通常可以使用附加属性将事件绑定到
Command-s - 然后直接绑定到您的视图模型来解决此问题。
namespace YourNamespace // wrap that into e.g. 'xmlns:local="clr-namespace:YourNamespace"'
public static class Attach
{
public static ICommand GetAutoGenerateColumnEvent(DataGrid grid) { return (ICommand)grid.GetValue(AutoGenerateColumnEventProperty); }
public static void SetAutoGenerateColumnEvent(DataGrid grid, ICommand value) { grid.SetValue(AutoGenerateColumnEventProperty, value); }
public static readonly DependencyProperty AutoGenerateColumnEventProperty =
DependencyProperty.RegisterAttached("AutoGenerateColumnEvent", typeof(ICommand), typeof(Attach), new UIPropertyMetadata(null, OnAutoGenerateColumnEventChanged));
static void OnAutoGenerateColumnEventChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
DataGrid grid = depObj as DataGrid;
if (grid == null || e.NewValue is ICommand == false)
return;
ICommand command = (ICommand)e.NewValue;
grid.AutoGeneratingColumn += new EventHandler<DataGridAutoGeneratingColumnEventArgs>((s, args) => OnAutoGeneratingColumn(command, s, args));
// handle unsubscribe if needed
}
static void OnAutoGeneratingColumn(ICommand command, object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (command.CanExecute(e)) command.Execute(e);
}
}
And in your XAML...
在你的 XAML 中......
<DataGrid
local:Attach.AutoGenerateColumnEvent="{Binding AutoGeneratingColumnCommand}" AutoGenerateColumns="True" />
And in your view-model...
在你的视图模型中......
RelayCommand _autoGeneratingColumnCommand;
public RelayCommand AutoGeneratingColumnCommand
{
get
{
return _autoGeneratingColumnCommand ?? (_autoGeneratingColumnCommand = new RelayCommand(param =>
{
var e = param as DataGridAutoGeneratingColumnEventArgs;
if (e != null)
{
switch (e.PropertyName)
{
case "ID":
e.Cancel = true;
break;
default:
break;
}
}
},
param => true));
}
}
...where RelayCommand : ICommandimplementation you can find on the web (widely used)
...RelayCommand : ICommand您可以在网络上找到的实现(广泛使用)
回答by Erti-Chris Eelmaa
It is as MVVM'ish as it can get. I don't see anything wrong with this. I've used it in my MVVM project and it works really well.
它尽可能地具有 MVVM 风格。我看不出这有什么问题。我已经在我的 MVVM 项目中使用过它,而且效果非常好。
Though I don't use AutoGeneratedColumns, but "bindable" columns attached trick.
虽然我不使用 AutoGeneratedColumns,但“可绑定”列附加了技巧。
<DataGrid Name="dataGrid"
local:DataGridColumnsBehavior.BindableColumns="{Binding ColumnCollection}"
AutoGenerateColumns="False"
...>
and then the actual behavior:
然后是实际行为:
public class DataGridColumnsBehavior
{
public static readonly DependencyProperty BindableColumnsProperty =
DependencyProperty.RegisterAttached("BindableColumns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridColumnsBehavior),
new UIPropertyMetadata(null, BindableColumnsPropertyChanged));
private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = source as DataGrid;
ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
dataGrid.Columns.Clear();
if (columns == null)
{
return;
}
foreach (DataGridColumn column in columns)
{
dataGrid.Columns.Add(column);
}
columns.CollectionChanged += (sender, e2) =>
{
NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
if (ne.Action == NotifyCollectionChangedAction.Reset)
{
dataGrid.Columns.Clear();
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Add)
{
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Move)
{
dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
}
else if (ne.Action == NotifyCollectionChangedAction.Remove)
{
foreach (DataGridColumn column in ne.OldItems)
{
dataGrid.Columns.Remove(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Replace)
{
dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn;
}
};
}
public static void SetBindableColumns(DependencyObject element, ObservableCollection<DataGridColumn> value)
{
element.SetValue(BindableColumnsProperty, value);
}
public static ObservableCollection<DataGridColumn> GetBindableColumns(DependencyObject element)
{
return (ObservableCollection<DataGridColumn>)element.GetValue(BindableColumnsProperty);
}
}
So, what exactly constitues as "MVVM"ish approach to you? Having everything in XAML is not what "MVVM" pattern is about.
那么,对您来说,什么才是“MVVM”式的方法呢?在 XAML 中拥有一切并不是“MVVM”模式的意义所在。
There is also one another trick that you can do. It basically revolves around templating DataGridColumn and writing specific trigger that will collapse column based on some condition. I have no "ready" solution, but it will work.
您还可以使用另一种技巧。它基本上围绕着模板 DataGridColumn 和编写特定的触发器来根据某些条件折叠列。我没有“现成”的解决方案,但它会起作用。

