Updating data binded with DataGrid control (MaterialDesign Theme) with attached behaviors using WPF MVVM?

1.2k Views Asked by At

I have a DataGrid front-end code looks like:

<DataGrid  ItemsSource="{Binding DTDisplayData}" x:Name="dgReport"
                   attached:DataGridColumnsAttched.BindableColumns="{Binding ColumnCollection}"
                   AutoGenerateColumns="False" CanUserDeleteRows="False" IsReadOnly="False"
                   CanUserSortColumns="True" CanUserAddRows="False" Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="3" BorderBrush="#89000000" BorderThickness="1"
                   >

            <DataGrid.Style>
                <Style TargetType="DataGrid" BasedOn="{StaticResource MaterialDesignDataGrid}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding SelectedBox}" Value="{x:Null}">
                            <Setter Property="Visibility" Value="Collapsed"></Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.Style>

        </DataGrid>

With a class Attched in back-end .CS Code:

public class DataGridColumnsAttched
{
public static readonly DependencyProperty BindableColumnsProperty =
        DependencyProperty.RegisterAttached("BindableColumns",
                                            typeof(ObservableCollection<DataGridColumnMetaData>),
                                            typeof(DataGridColumnsAttched),
                                            new UIPropertyMetadata(null, BindableColumnsPropertyChanged));
        private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            DataGrid dataGrid = source as DataGrid;
            ObservableCollection<DataGridColumnMetaData> columns = e.NewValue as ObservableCollection<DataGridColumnMetaData>;
            dataGrid.Columns.Clear();
            if (columns == null)
            {
                return;
            }

            foreach (DataGridColumnMetaData column in columns)
            {
                dataGrid.Columns.Add(CreateColumnFromMetaData(column));
            }

            columns.CollectionChanged += (sender, e2) =>
            {
                NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
                if (ne.Action == NotifyCollectionChangedAction.Reset)
                {
                    dataGrid.Columns.Clear();
                    if(ne.NewItems != null)
                    { 
                        foreach (DataGridColumnMetaData column in ne.NewItems)
                        {
                            dataGrid.Columns.Add(CreateColumnFromMetaData(column));
                        }
                    }
                }
                else if (ne.Action == NotifyCollectionChangedAction.Add)
                {
                    foreach (DataGridColumnMetaData column in ne.NewItems)
                    {
                        dataGrid.Columns.Add(CreateColumnFromMetaData(column));
                    }
                }
                else if (ne.Action == NotifyCollectionChangedAction.Move)
                {
                    dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
                }
                else if (ne.Action == NotifyCollectionChangedAction.Remove)
                {
                    foreach (DataGridColumnMetaData column in ne.OldItems)
                    {
                        dataGrid.Columns.Remove(CreateColumnFromMetaData(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);
        }

        public static DataGridColumn CreateColumnFromMetaData(DataGridColumnMetaData columnMetaData)
        {
            DataGridColumn newColumn;
            switch (columnMetaData.Type)
            {
                case SuperTapiModel.ColumnType.DataGridTextColumn:
                    {
                        DataGridTextColumn dgcText = new DataGridTextColumn();
                       //set parameters....
                        newColumn = dgcText;
                    }
                    break;
                case SuperTapiModel.ColumnType.DataGridTemplateColumn:
                    { 
                        DataGridTemplateColumn dgcTemplate = new DataGridTemplateColumn();
                        newColumn = dgcTemplate;
                    }
                    break;
                case SuperTapiModel.ColumnType.DataGridHyperlinkColumn:
                    {
                        DataGridHyperlinkColumn dgcHyperlink = new DataGridHyperlinkColumn();
                        newColumn = dgcHyperlink;
                    }
                    break;
                case SuperTapiModel.ColumnType.DataGridComboBoxColumn:
                    {
                        DataGridComboBoxColumn dgcComboBox = new DataGridComboBoxColumn();
                        newColumn = dgcComboBox;
                    }
                    break;
                case SuperTapiModel.ColumnType.DataGridCheckBoxColumn:
                    {
                        DataGridCheckBoxColumn dgcCheckBox = new DataGridCheckBoxColumn();
                        newColumn = dgcCheckBox;
                    }
                    break;
                default:
                    {
                        DataGridTextColumn dgcText = new DataGridTextColumn();
                       //set parameters....
                        newColumn = dgcText;
                    }
                    break;
            }
            return newColumn;
        }
}

I want to edit data in the datagrid, and I assume I then have to catch the editing event PropertyChanged when cell is edited.

Then, I want to set parameter EditingElementStyle in back-end .CS Code.

How can I acheive it using WPF and MVVM?

It worth to mention the source of my code is based on MaterialDesign Theme, which lacks some resources I can play with, I think.

Any help would be really appreciated!

1

There are 1 best solutions below

1
On

For the first part of your problem, the editing part, you will have to bind the "Binding" property of your columns to the related ViewModel property you want to be modified when the user edits the cell. Since you are creating your columns from the .cs file, you would do it like so :

case SuperTapiModel.ColumnType.DataGridTextColumn:
{
    DataGridTextColumn dgcText = new DataGridTextColumn();
    dgcText.Binding = new Binding("The name of the property");
    newColumn = dgcText;
}
break;

Please note that I never actually did this before, so the syntax might be a bit different, but you get the idea.

For the second part, so setting the EditingElementStyle, you would do the same as the Binding. Create your style in the Xaml file, then use the FindResource method to set the value of EditingElementStyle in the .cs file. It would look something like this :

case SuperTapiModel.ColumnType.DataGridTextColumn:
{
    DataGridTextColumn dgcText = new DataGridTextColumn();
    dgcText.EditingElementStyle = FindResource("YourResourceKey") as Style;
    newColumn = dgcText;
}
break;

I hope that helps!