5

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

那我怎么才能stop出现specific column在DataGrid中呢?

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

4

3 回答 3

16

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

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

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

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

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

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

    这通常是通过设置AutoGenerateColumns="False"和指定您<DataGrid.Columns>自己来完成的,但是您也可以使用的AutoGeneratingColumn事件从视图层中排除列,如果它等于您要排除的值,DataGrid则取消列的生成,例如问题你链接建议。ColumnName

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

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

于 2013-04-05T14:07:17.823 回答
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您可以在网络上找到的实现(广泛使用)

于 2013-04-05T12:08:45.437 回答
1

它就像 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 和编写特定的触发器,该触发器将根据某些条件折叠列。我没有“现成”的解决方案,但它会起作用。

于 2013-04-05T10:41:19.340 回答