我已将ObservableCollection绑定到DataGrid
并在带有MVVM应用程序的WPF中将AutoGenerateColumns
设置为true。
那么我如何stop
specific column
出现在DataGrid中?
我见过同样的问题here。但我正在寻找更多的MVVM方法。
答案 0 :(得分:10)
MVVM意味着您的UI和您的数据层完全分离,View层只是您数据层的可视反射。
因此排除列的“MVVM方式”取决于排除的位置:
如果您的数据图层要排除列,请从数据图层中删除该列。
这通常意味着修改DataGrid.ItemsSource
绑定的集合,因此它不再包含不应显示的数据。
或者取决于您的应用程序是什么以及什么算作“应用程序逻辑”,这可能意味着要保留要排除的string
或List<string>
列,并让View找到某种绑定方式到那些字符串并修改它的显示以排除那些列(自定义依赖属性,转换器,重用Tag
属性+ AutoGeneratingColumn
事件,触发器等)
如果您的View图层应该排除列,请从视图图层中删除该列。
这通常是通过设置AutoGenerateColumns="False"
并自己指定<DataGrid.Columns>
来完成的,但您也可以使用DataGrid
ColumnName
事件从视图图层中排除该列,如果列private void DataGrid_AutoGeneratingColumn(
object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if ((string)e.Column.Header == "ID")
{
e.Cancel = true;
}
}
等于您要排除的值,则取消列的生成,例如建议的AutoGeneratingColumn。
{{1}}
请记住,MVVM的重点是分离UI和数据层。在MVVM中使用代码隐藏完全没有问题,只要代码只与UI特定的逻辑相关,而不是数据/特定于应用程序的逻辑
答案 1 :(得分:2)
或者你可以这样做......
您通常可以使用附加属性来解决此问题 事件到
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);
}
}
在你的XAML ......
<DataGrid
local:Attach.AutoGenerateColumnEvent="{Binding AutoGeneratingColumnCommand}" AutoGenerateColumns="True" />
在您的视图模型中......
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));
}
}
...您可以在网上找到RelayCommand : ICommand
实施(广泛使用)
答案 2 :(得分:1)
它可以像MVVM一样。我没有看到任何错误。我已经在我的MVVM项目中使用它,它的效果非常好。
虽然我不使用AutoGeneratedColumns,但附加了“可绑定”列技巧。
<DataGrid Name="dataGrid"
local:DataGridColumnsBehavior.BindableColumns="{Binding ColumnCollection}"
AutoGenerateColumns="False"
...>
然后是实际行为:
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);
}
}
那么,究竟构成“MVVM”的是什么?拥有XAML中的所有内容并不是“MVVM”模式的内容。
还有另外一个技巧可以做。它主要围绕模板化DataGridColumn并编写特定的触发器,根据某些条件将崩溃列。我没有“准备好”的解决方案,但它会起作用。