Click here to Skip to main content
15,868,010 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am new to WPF development. I've referred to many solutions online but still have no idea.
I have a Listbox and a Datagrid. The Listbox loads data and displays selectable items dynamically. The Datagrid shows static table with a checkbox column. I first load data of Datagrid from an Excel file and bind the ItemsSource of Datagrid to the dataset. Each line in the Datagrid is a class:
C#
public class ExcelDataEntry
{
    public bool isChecked { get; set; }
    public string note { get; set; }
    public ExcelDataEntry(string note)
    {
        this.isChecked = false;
        this.note = note;
    }
}

Displayed in the GUI are a Listbox and a Datagrid, in the backend they make a viewModelObj:
C#
class viewModelObj : INotifyPropertyChanged
{
    public string displayName { get; set; }

    private List<ExcelDataEntry> _generalNoteList;
    public List<ExcelDataEntry> generalNoteList
    {
        get { return _generalNoteList; }
        set
        {
            _generalNoteList = value;
            OnPropertyChanged("generalNoteList");
            MessageBox.Show($"generalNoteList changed from model.");
        }
    }

    public viewModelObj(string name)
    {
        displayName = name;
    }

    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}

The ChangeRequestViewModel function executes the data loading and data binding:
C#
class ChangeRequestViewModel
{
    public ObservableCollection<ExcelDataEntry> generalNoteSource { get; set; } = new ObservableCollection<ExcelDataEntry>();
    public ObservableCollection<viewModelObj> viewModelSource { get; set; } = new ObservableCollection<viewModelObj>();

    public ChangeRequestViewModel()
    {
        List<ExcelDataEntry> dataPool = Default.GenerateDataPool("data.xlsx", 1, 4, 1, 71, 5);
        foreach (var entry in dataPool.Where(x => x.note == "GN").ToList())
        {
            this.generalNoteSource.Add(entry);
        }
        CatDocFactory catDocFactory = new CatDocFactory();
        foreach (var entry in catDocFactory.GetAllOpenedDocs())
        {
            this.viewModelSource.Add(new viewModelObj(entry.displayName));
        }
    }
}

The XAML is:
XML
...
<Window.DataContext>
    <changeRequestVM:ChangeRequestViewModel/>
</Window.DataContext>
...
<ListBox x:Name="catDocListView" Grid.Column="0" Grid.RowSpan="2" Margin="16" ItemContainerStyle="{StaticResource ContainerStyle}"  ItemsSource="{Binding viewModelSource}" DisplayMemberPath="displayName"/>
...
<DataGrid x:Name="generalNoteDG" CanUserAddRows="False" AutoGenerateColumns="False" ItemsSource="{Binding generalNoteSource}">
    <DataGrid.Columns>
        <DataGridCheckBoxColumn Binding="{Binding isChecked, UpdateSourceTrigger=PropertyChanged}"/>
        <DataGridTextColumn Header="Note" Binding="{Binding note}" Width="Auto"/>
    </DataGrid.Columns>
</DataGrid>
...

The DataContext has been set to the viewModel in the main window initialization function:
C#
this.DataContext = changeRequestDataContext;

Expected:
Situation is no matter which item in the Listbox is selected, the data content in the data grid reamins the unchanged. But I can select the data row under each selection of a Listbox item. Assuming I select the first item and select the first row of data grid then select the second item with the second row of the data grid. Expected is that in the backend, the note list of first item should have the first data row object in the note list property and the note list of second item should have the second data row object in the note list property.

You can imagine that the Datagrid is a data pool for selection.

How could I set the property of the DataGrid,DataGridTextColumn and DataGridCheckBoxColumn and code in the backend?

Thank you guys for the help.

What I have tried:

I have googled for solutions but most of them bind the ItemsSource to the list of objects. In my case I need to set the data source of Datagrid to a List of data object and the List of viewModelObj is another thing but needs to contain the selection result of each element in the list.
Posted
Updated 5-Oct-22 22:02pm
v4

1 solution

The rows / columns of the DataGrid are binding to ExcelDataEntry ... That's where you implement INotifyPropertChanged for the "data items in your data source". When an ExcelDataEntry item is changed, you call "its" OnPropertyChanged handler.

If you used an Observable Collection (OC) for the Item Source, the inherent "notify" behavior of the OC is to inform when changes are made to the "data set"; i.e. adds and deletes.
 
Share this answer
 
Comments
BabyHai 5-Oct-22 11:30am    
I don't want to delete or add rows in the Datagrid. Actually I use the Datagrid as a data pool. Rows inside it are available for me to select by checking the checkbox. Even I change values in the Datagrid, the modification only works for current runtime. That's why I didn't add INotifyPropertChanged to the ExcelDataEntry and vise versa by unchecking.
What I want to implement is, when I check one row, the instance representing the row will be added to the List<exceldataentry> generalNoteList of the item in the Listbox.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900