Is it possible to get dynamic columns on wpf datagrid in mvvm pattern?

前端 未结 2 1641
逝去的感伤
逝去的感伤 2020-12-24 09:21

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, a

相关标签:
2条回答
  • 2020-12-24 09:38

    I would like to extend the previous example (answer) the ability to subscribe and unsubscribe on event CollectionChanged.

    Behavior (add reference on System.Windows.Interactivity):

     public class ColumnsBindingBehaviour : Behavior<DataGrid>
    {
        public ObservableCollection<DataGridColumn> Columns
        {
            get { return (ObservableCollection<DataGridColumn>) base.GetValue(ColumnsProperty); }
            set { base.SetValue(ColumnsProperty, value); }
        }
    
        public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns",
            typeof(ObservableCollection<DataGridColumn>), typeof(ColumnsBindingBehaviour),
                new PropertyMetadata(OnDataGridColumnsPropertyChanged));
    
        private static void OnDataGridColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            var context = source as ColumnsBindingBehaviour;
    
            var oldItems = e.OldValue as ObservableCollection<DataGridColumn>;
    
            if (oldItems != null)
            {
                foreach (var one in oldItems)
                    context._datagridColumns.Remove(one);
    
                oldItems.CollectionChanged -= context.collectionChanged;
            }
    
            var newItems = e.NewValue as ObservableCollection<DataGridColumn>;
    
            if (newItems != null)
            {
                foreach (var one in newItems)
                    context._datagridColumns.Add(one);
    
                newItems.CollectionChanged += context.collectionChanged;
            }
        }
    
        private ObservableCollection<DataGridColumn> _datagridColumns;
    
        protected override void OnAttached()
        {
            base.OnAttached();
    
            this._datagridColumns = AssociatedObject.Columns;
        }
    
    
        private void collectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    if (e.NewItems != null)
                        foreach (DataGridColumn one in e.NewItems)
                            _datagridColumns.Add(one);
                    break;
    
                case NotifyCollectionChangedAction.Remove:
                    if (e.OldItems != null)
                        foreach (DataGridColumn one in e.OldItems)
                            _datagridColumns.Remove(one);
                    break;
    
                case NotifyCollectionChangedAction.Move:
                    _datagridColumns.Move(e.OldStartingIndex, e.NewStartingIndex);
                    break;
    
                case NotifyCollectionChangedAction.Reset:
                    _datagridColumns.Clear();
                    if (e.NewItems != null)
                        foreach (DataGridColumn one in e.NewItems)
                            _datagridColumns.Add(one);
                    break;
            }
        }
    }
    

    View:

    <Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
        xmlns:loc="clr-namespace:WpfApplication1"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="_dataGrid">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Test" />
            </DataGrid.Columns>
            <i:Interaction.Behaviors>
                <loc:ColumnsBindingBehaviour Columns="{Binding DataGridColumns}"/>        
            </i:Interaction.Behaviors>
        </DataGrid>
    </Grid>
    

    ViewModel:

         private ObservableCollection<DataGridColumn> _dataGridColumns;
         public ObservableCollection<DataGridColumn> DataGridColumns
         {
             get
             {
                 if (_dataGridColumns == null)
                     _dataGridColumns = new ObservableCollection<DataGridColumn>()
                     {
                         new DataGridTextColumn()
                         {
                             Header = "Column1"
                         }
                     };
    
                 return _dataGridColumns;
             }
             set
             {
                 _dataGridColumns = value;
                 OnPropertyChanged("DataGridColumns");
             }
         }
    
    0 讨论(0)
  • 2020-12-24 09:43

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

    here its..(full wpf mvvm)

    In my command file:

    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);
            }
        }
    

    in my xaml:

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

    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");
                }
            }
    

    and in my constructor:

    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);
        }
    
    0 讨论(0)
提交回复
热议问题