当AutoGenerateColumns设置为True时,如何停止在DataGrid中生成特定列?

时间:2013-04-05 09:22:53

标签: c# wpf mvvm datagrid

我已将ObservableCollection绑定到DataGrid并在带有MVVM应用程序的WPF中将AutoGenerateColumns设置为true。

那么我如何stop specific column出现在DataGrid中?

我见过同样的问题here。但我正在寻找更多的MVVM方法。

3 个答案:

答案 0 :(得分:10)

MVVM意味着您的UI和您的数据层完全分离,View层只是您数据层的可视反射。

因此排除列的“MVVM方式”取决于排除的位置:

  • 如果您的数据图层要排除列,请从数据图层中删除该列。

    这通常意味着修改DataGrid.ItemsSource绑定的集合,因此它不再包含不应显示的数据。

    或者取决于您的应用程序是什么以及什么算作“应用程序逻辑”,这可能意味着要保留要排除的stringList<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并编写特定的触发器,根据某些条件将崩溃列。我没有“准备好”的解决方案,但它会起作用。