Home > other >  How can I compose the static text "new Operation Class“ with the databound objects listed in da
How can I compose the static text "new Operation Class“ with the databound objects listed in da

Time:01-04

I have a datagrid in my WPF application.

This datagrid is bound to an ObservableCollection which is called OperationClasses as defined below.

The type OperationClass consists of 3 properties which are Name, Start and End respectively.

I would like to know how to add OperationClass as a datagrid row to the DataGridList by clicking into the last row with the text "new Operation Class“ as shown in the image as an attached file.
DataGrid picture with example values:
enter image description here

After the end user has entered a name and a start and end value then the text "new Operation Class" will be displayed in the next line, which is the new last line.

How can I compose the static text "new Operation Class" with the databound objects listed in DataGrid?

public ObservableCollection<OperationClass> OperationClasses
{
    get
    {
        return _operationClasses;
    }
    set
    {
        SetProperty(ref _operationClasses, value);
    }
}

I tried to find a way to use CompositeCollection so as to compose databound objects(OperationClass) and the static text "New Operation Class". But i couldnt succeed in for the current stage..

CodePudding user response:

You need to provide a DataTemplateSelector to apply a dedicated DataTemplate to the placeholder column.

First of all, the placeholder item (or placeholder table row) must be enabled by setting DataGrid.CanUserAddRows to true. The value is true by default so just make sure you don't explicitly set it to false.

The following example assumes that you want the placeholder text to fill the first column. However, you can follow the below pattern to add a placeholder text for any column.

Following your code, the example assumes that the data model used to populate the DataGrid is the OperationClass with two fictional properties to make two columns:

OperationClass.cs

class OperationClass : INotifyPropertyChanegd
{
  public string TextDataFirstColumn { get; set; }
  public string TextDataSecondColumn { get; set; }
}

First, define the DataTemplateSelector:

OperationClassTemplateSelector.cs

class OperationClassTemplateSelector : DataTemplateSelector
{
  public DataTemplate DefaultTemplate { get; set; }
  public DataTemplate PlaceholderTemplate { get; set; }

  public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    => item switch
    {
      OperationClass _ => this.DefaultTemplate,
      var dataItem when dataItem is not null => this.PlaceholderTemplate,
      _ => base.SelectTemplate(item, container),
    };
}

Second step is to explicitly define column templates.
It is important to define the column that should contain the placeholder text as DataGridTemplateColumn. This is required in order to allow the assignment of a DataTemplateSelector implementation.

The first column of the placeholder row will display "Add new item..." as placeholder text:

<DataGrid ItemsSource="{Binding OperationClassItems}"
          AutoGenerateColumns="False">
  <DataGrid.Columns>
    <DataGridTemplateColumn Header="1st Column">
      <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate DataType="{x:Type local:OperationClass}">
          <TextBox Text="{Binding TextDataFirstColumn}" />
        </DataTemplate>
      </DataGridTemplateColumn.CellEditingTemplate>

      <!-- Instead of defining the CellTemplate explicitly, 
           we assign the CellTemplateSelector instead -->
      <DataGridTemplateColumn.CellTemplateSelector>
        <local:OperationClassTemplateSelector>
          <local:OperationClassTemplateSelector.DefaultTemplate>
            <DataTemplate DataType="{x:Type local:OperationClass}">
              <TextBlock Text="{Binding TextDataFirstColumn}" />
            </DataTemplate>
          </local:OperationClassTemplateSelector.DefaultTemplate>

          <local:OperationClassTemplateSelector.PlaceholderTemplate>
            <DataTemplate>
              <TextBlock Text="Add new item..." />
            </DataTemplate>
          </local:OperationClassTemplateSelector.PlaceholderTemplate>
        </local:OperationClassTemplateSelector>
      </DataGridTemplateColumn.CellTemplateSelector>
    </DataGridTemplateColumn>

    <DataGridTextColumn Header="2nd Column" 
                        Binding="{Binding TextDataSecondColumn}" />
  </DataGrid.Columns>
</DataGrid>

CodePudding user response:

First off all, I would like to thank you for valuable post. But I have some issues regarding add new item operation. I defined the issues by sharing the corresponding images as shown below. After user has entered a name and a start and end value then the text "new Operation Class“ should be displayed in the next line, which is the new last line. In other words, the properties which are Name,Start and End are compulsory columns to be filled for the placeholder to be displayed in the next line. In addition to this, even though I can select the new Item place holder row as a selected row, I cant do it for data bound records. I will be very delighted if you can have the opportunity to inform me.

Before adding new Item

After adding new item

Selected New Item Row

Selected Data Bound Item Row

  • Related