Search code examples
c#wpfdatagridobservablecollection

Make column ReadOnly for ObservableCollection


I am new to C# wpf and uses an ObservableCollection to populate the columns and rows of a DataGrid. The user must be able to interact with the data in the cells with the exception of two specific columns, which should contain read-only/static content (e.g. a unique row ID).

Is there a way to make specific columns read-only in an ObservableCollection? Or should such data be in a separate DataGrid populated by a ReadOnlyObservableCollection (which in my opinion seems overcomplicated)?

In my *.xaml file I have the DataGrid as:

<DataGrid Name="OptionsGrid" ItemsSource="{Binding Options}">
</DataGrid>

And the corresponding code is:

public ObservableCollection<OptionsData> Options { get; init; }

Options = new ObservableCollection<OptionsData>
{
      new OptionsData() {Id = "123", IsActive = true, OptionCheck = true, OptionName = "Name"},
      new OptionsData() {Id = "456", IsActive = false, OptionCheck = false, OptionName = "Name2"},
};

DataContext = this;

//
public class OptionsData
{
      public string Id { get; set; }
      public bool IsActive { get; set; }
      public bool OptionCheck { get; set; }
      public string OptionName { get; set; }
}

Edit: Added code example


Solution

  • At the moment you are automatically generating the columns in your datagrid. This is the default behaviour for a wpf datagrid.

    You should set AutoGenerateColumns="False" in your datagrid tag.

    Add a DataGrid.Columns tag into the datagrid.

    Define your columns within that.

    https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.datagrid?view=windowsdesktop-7.0

    So from there

        <DataGrid Name="DG1" ItemsSource="{Binding}" AutoGenerateColumns="False" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name"  Binding="{Binding FirstName}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}" />
                <!--The Email property contains a URI.  For example "mailto:[email protected]"-->
                <DataGridHyperlinkColumn Header="Email" Binding="{Binding Email}"  ContentBinding="{Binding Email, Converter={StaticResource EmailConverter}}" />
                <DataGridCheckBoxColumn Header="Member?" Binding="{Binding IsMember}" />
                <DataGridComboBoxColumn Header="Order Status"  SelectedItemBinding="{Binding Status}" ItemsSource="{Binding Source={StaticResource myEnum}}" />
            </DataGrid.Columns>
        </DataGrid>
    

    Note there are several types of datagrid columns.

    You then have finer control of each of those columns. You can set specific ones IsReadOnly="True".

    There are some other potential options but that is your simplest approach and I suggest you give that a twirl first before complicating things.