是否可以在mvvm模式下获取wpf datagrid上的动态列? [英] Is it possible to get dynamic columns on wpf datagrid in mvvm pattern?

查看:109
本文介绍了是否可以在mvvm模式下获取wpf datagrid上的动态列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在wpf(mvvm模式)中开发产品。我有一个场景,我花了一个多星期没有好的结果。请帮助我,如果你可以...
这是场景,根据用户的定制(用户选择列),我必须显示一组数据到datagrid。目前,我将一个ObservableCollection与一组属性绑定到datagrid的itemsource。这限制了我固定的列大小。
注意:列出n个列名称以供用户选择。
如果通过datagrid.columns.add()轻松地完成其后面的代码。在这种情况下,任何一个可以帮助我。

Im developing a product in wpf (mvvm pattern). I have a scenario in which i have spent more than a week for no good result. Pls help me if you can... Here is the scenario, according to the user's customization(user ll select the columns) i have to display a set of data into datagrid. Currently im binding a ObservableCollection with set of properties to the itemsource of datagrid. This limits me to fixed column size. Note: The n number of columns name is listed out for user's selection. If its done in code behind it is easy by "datagrid.columns.add()". Can any one out there help me in this scenario.

我的xaml:

<my:DataGrid AutoGenerateColumns="False" Margin="357,121.723,82,41" Name="dataGrid3" c:DataGridExtension.Columns="{Binding ColumnCollection}" />

我的命令类:

public static class DataGridExtension
{
    public static ObservableCollection<DataGridColumn> GetColumns(DependencyObject obj)
    {
        return (ObservableCollection<DataGridColumn>)obj.GetValue(ColumnsProperty);
    }

    public static void SetColumns(DependencyObject obj, ObservableCollection<DataGridColumn> value)
    {
        obj.SetValue(ColumnsProperty, value);
    }

    public static readonly DependencyProperty ColumnsProperty = 
        DependencyProperty.RegisterAttached("Columns", typeof(ObservableCollection<DataGridColumn>),typeof(DataGridExtension),
         new UIPropertyMetadata (new ObservableCollection<DataGridColumn>(), OnDataGridColumnsPropertyChanged));

    private static void OnDataGridColumnsPropertyChanged(DependencyObject d,
           DependencyPropertyChangedEventArgs e)
    {
        if (d.GetType() == typeof(DataGrid))
        {
            DataGrid myGrid = d as DataGrid;

            ObservableCollection<DataGridColumn> Columns = (ObservableCollection<DataGridColumn>)e.NewValue;

            if (Columns != null)
            {
                myGrid.Columns.Clear();

                if (Columns != null && Columns.Count > 0)
                {
                    foreach (DataGridColumn dataGridColumn in Columns)
                    {
                        myGrid.Columns.Add(dataGridColumn);
                    }
                }


                Columns.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs args)
                {
                    if (args.NewItems != null)
                    {
                        //foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
                        //{
                        //    myGrid.Columns.Add(column);
                        //}
                    }

                    if (args.OldItems != null)
                    {

                        //foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
                        //{
                        //    myGrid.Columns.Remove(column);
                        //}
                    }
                };

            }
        }
    }
}

和我在viewmodel中的属性:

and my property in viewmodel:

private ObservableCollection<DataGridColumn> _columnCollection = new ObservableCollection<DataGridColumn>();
public ObservableCollection<DataGridColumn> ColumnCollection
{
    get
    {
        return this._columnCollection;
    }
    set
    {
        _columnCollection = value;
        base.OnPropertyChanged("ColumnCollection");
        //Error
        //base.OnPropertyChanged<ObservableCollection<DataGridColumn>>(() => this.ColumnCollection);
    }
}


推荐答案

为了你的努力的人的...终于我找到了解决方案....

Thanks for your effort guy's... finally i have found the solution....

这里它的..(完整的wpf mvvm)

here its..(full wpf mvvm)

在我的命令文件中:

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();
                    if (ne.NewItems != null)
                    {
                        foreach (DataGridColumn column in ne.NewItems)
                        {
                            dataGrid.Columns.Add(column);
                        }
                    }
                }
                else if (ne.Action == NotifyCollectionChangedAction.Add)
                {
                    if (ne.NewItems != null)
                    {
                        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)
                {
                    if (ne.OldItems != null)
                    {
                        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);
        }
    }

在我的xaml:

<my:DataGrid AutoGenerateColumns="False" Margin="357,121.723,82,41" Name="dataGrid3" ItemsSource="{Binding Path=Datatable}" c:DataGridColumnsBehavior.BindableColumns="{Binding ColumnCollection}" />

和我的viewmodel中的finaly:

and finaly in my viewmodel:

private ObservableCollection<DataGridColumn> _columnCollection = new ObservableCollection<DataGridColumn>();
        public ObservableCollection<DataGridColumn> ColumnCollection
        {
            get
            {
                return this._columnCollection;
            }
            set
            {
                _columnCollection = value;
                base.OnPropertyChanged("ColumnCollection");
                //Error
                //base.OnPropertyChanged<ObservableCollection<DataGridColumn>>(() => this.ColumnCollection);
            }
        }
        private DataTable _datatable = new DataTable();
        public DataTable Datatable
        {
            get
            {
                return _datatable;
            }
            set
            {
                if (_datatable != value)
                {
                    _datatable = value;
                }
                base.OnPropertyChanged("Datatable");
            }
        }

在我的构造函数中:

public MainViewModel()
        {
Datatable.Columns.Add("Name",typeof(string));
            Datatable.Columns.Add("Color", typeof(string));
            Datatable.Columns.Add("Phone", typeof(string));
            Datatable.Rows.Add("Vinoth", "#00FF00", "456345654");
            Datatable.Rows.Add("lkjasdgl", "Blue", "45654");
            Datatable.Rows.Add("Vinoth", "#FF0000", "456456");
System.Windows.Data.Binding bindings = new System.Windows.Data.Binding("Name");
            System.Windows.Data.Binding bindings1 = new System.Windows.Data.Binding("Phone");
            System.Windows.Data.Binding bindings2 = new System.Windows.Data.Binding("Color");
            DataGridTextColumn s = new DataGridTextColumn();
            s.Header = "Name";
            s.Binding = bindings;
            DataGridTextColumn s1 = new DataGridTextColumn();
            s1.Header = "Phone";
            s1.Binding = bindings1;
            DataGridTextColumn s2 = new DataGridTextColumn();
            s2.Header = "Color";
            s2.Binding = bindings2;

            FrameworkElementFactory textblock = new FrameworkElementFactory(typeof(TextBlock));
            textblock.Name = "text";
            System.Windows.Data.Binding prodID = new System.Windows.Data.Binding("Name");
            System.Windows.Data.Binding color = new System.Windows.Data.Binding("Color");
            textblock.SetBinding(TextBlock.TextProperty, prodID);
            textblock.SetValue(TextBlock.TextWrappingProperty, TextWrapping.Wrap);
            //textblock.SetValue(TextBlock.BackgroundProperty, color);
            textblock.SetValue(TextBlock.NameProperty, "textblock");
            //FrameworkElementFactory border = new FrameworkElementFactory(typeof(Border));
            //border.SetValue(Border.NameProperty, "border");
            //border.AppendChild(textblock);
            DataTrigger t = new DataTrigger();
            t.Binding = new System.Windows.Data.Binding { Path = new PropertyPath("Name"), Converter = new EnableConverter(), ConverterParameter ="Phone" };
            t.Value = 1;
            t.Setters.Add(new Setter(TextBlock.BackgroundProperty, Brushes.LightGreen, textblock.Name));
            t.Setters.Add(new Setter(TextBlock.ToolTipProperty, bindings, textblock.Name));
            DataTrigger t1 = new DataTrigger();
            t1.Binding = new System.Windows.Data.Binding { Path = new PropertyPath("Name"), Converter = new EnableConverter(), ConverterParameter = "Phone" };
            t1.Value = 2;
            t1.Setters.Add(new Setter(TextBlock.BackgroundProperty, Brushes.LightYellow, textblock.Name));
            t1.Setters.Add(new Setter(TextBlock.ToolTipProperty, bindings, textblock.Name));

            DataTemplate d = new DataTemplate();
            d.VisualTree = textblock;
            d.Triggers.Add(t);
            d.Triggers.Add(t1);

            DataGridTemplateColumn s3 = new DataGridTemplateColumn();
            s3.Header = "Name 1";
            s3.CellTemplate = d;
            s3.Width = 140;

            ColumnCollection.Add(s); 
            ColumnCollection.Add(s1);
            ColumnCollection.Add(s2);
            ColumnCollection.Add(s3);
    }

这篇关于是否可以在mvvm模式下获取wpf datagrid上的动态列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆