【问题标题】:how to stop a specific column to be generated in DataGrid when the AutoGenerateColumns is set to True?当 AutoGenerateColumns 设置为 True 时,如何停止在 DataGrid 中生成特定列?
【发布时间】:2013-03-27 15:34:59
【问题描述】:

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

那我怎样才能stopspecific column 出现在DataGrid 中呢?

我看到了同样的问题here。但我正在寻找更多的 MVVM 方法。

【问题讨论】:

  • 是的。我看了看答案。但我仍然对这些答案不满意。
  • 那么你应该把你的问题说清楚,比如“我已经阅读了这个......并正在寻找更多的 MVVM 方法”等

标签: c# wpf mvvm datagrid


【解决方案1】:

MVVM 意味着您的 UI 和数据层是完全分离的,而视图层只是数据层的视觉反映。

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

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

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

    或者根据您的应用程序的用途以及什么算作“应用程序逻辑”,这可能意味着维护要排除的列的 stringList<string>,并让视图找到某种方式绑定到这些字符串和修改它的显示以排除这些列(自定义依赖属性、转换器、Tag 属性的重用 + AutoGeneratingColumn 事件、触发器等)

  • 如果您的视图层应该排除一列,请从视图层中删除该列。

    这通常通过设置AutoGenerateColumns="False" 并自己指定<DataGrid.Columns> 来完成,但是您也可以使用DataGridAutoGeneratingColumn 事件从视图层中排除列,并取消列的生成如果 ColumnName 等于您要排除的值,例如建议的 question you linked

    private void DataGrid_AutoGeneratingColumn(
        object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if ((string)e.Column.Header == "ID")
        {
            e.Cancel = true;
        }
    }
    

请记住,MVVM 的全部意义在于分离您的 UI 和数据层。在 MVVM 中使用代码隐藏视图绝对没有错,只要代码仅与特定于 UI 的逻辑相关,而不是与特定于数据/应用程序的逻辑相关

【讨论】:

  • 赞成明智而不是教条地认为“代码隐藏中没有任何东西!”
【解决方案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 的实现可以在网上找到(广泛使用)

【讨论】:

    【解决方案3】:

    它就像 MVVM'ish 一样。我看不出这有什么问题。我已经在我的 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 和编写特定的触发器,该触发器将根据某些条件折叠列。我没有“现成”的解决方案,但它会起作用。

    【讨论】:

      猜你喜欢
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-21
      • 1970-01-01
      • 2011-11-25
      • 2019-03-11
      • 1970-01-01
      相关资源
      最近更新 更多