I have been trying to make a an editable DataGrid
with dynamic columns in a WPF MVVM project. The dynamic columns would be the same type, i.e: decimal
.
The aim is to collect department totals of shops with indefinite number of departments. I tried to demonstrate it below.
Day Dept1 Dept2 Dept3... TotalOfDepartments CashTotal CreditTotal
=====================================================================
1 100 200 50 350 50 300
2 75 100 0 175 25 150
So, there are numerous shops with indefinite departments and my goal is to collect month
I want to make Department, CashTotal & CreditTotal Columns editable. I've had several approaches that I tried like:
- populate dynamic datagrid column and binding with editable using mVVm
- Populating a DataGrid with Dynamic Columns in a Silverlight Application using MVVM
- How do I bind a WPF DataGrid to a variable number of columns?
This is my last try from the last approach. As follows:
Model:
public class DailyRevenues
{
public int ShopId { get; set; }
public int Day { get; set; }
public ObservableCollection<Department> DepartmentList { get; set; }
public DailyRevenues()
{
this.DepartmentList = new ObservableCollection<Department>();
}
}
public class Department
{
public string Name { get; set; }
private decimal total;
public decimal Total
{
get { return total; }
set { total = value; }
}
}
ViewModel:
public class DataItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public DataItemViewModel()
{
this.MonthlyRevenues = new ObservableCollection<DailyRevenues>();
var d1 = new DailyRevenues() { ShopId = 1, Day = 1 };
d1.DepartmentList.Add(new Department() { Name = "Deapartment1", Total = 100 });
d1.DepartmentList.Add(new Department() { Name = "Deapartment2", Total = 200 });
var d2 = new DailyRevenues() { ShopId = 1, Day = 2 };
d2.DepartmentList.Add(new Department() { Name = "Deapartment1", Total = 75 });
d2.DepartmentList.Add(new Department() { Name = "Deapartment2", Total = 150 });
d2.DepartmentList.Add(new Department() { Name = "Deapartment3", Total = 100 });
this.MonthlyRevenues.Add(d1);
this.MonthlyRevenues.Add(d2);
}
private ObservableCollection<DailyRevenues> monthlyRevenues;
public ObservableCollection<DailyRevenues> MonthlyRevenues
{
get { return monthlyRevenues; }
set
{
if (monthlyRevenues != value)
{
monthlyRevenues = value;
OnPropertyChanged(nameof(MonthlyRevenues));
}
}
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
And the XAML:
<DataGrid ItemsSource="{Binding MonthlyRevenues}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Day" Binding="{Binding Path=Day}" />
<DataGridTextColumn Header="{Binding Path=MonthlyRevenues[0].DepartmentList[0].Name}" Binding="{Binding Path=DepartmentList[0].Total, Mode=TwoWay}" />
<DataGridTextColumn Header="{Binding Path=DepartmentList[1].Name}" Binding="{Binding Path=DepartmentList[1].Total, Mode=TwoWay}" />
<DataGridTextColumn Header="Department Total"/>
<DataGridTextColumn Header="Cash Total" />
<DataGridTextColumn Header="Credit Total" />
</DataGrid.Columns>
</DataGrid>
Unfortunately, on this last try using the indexers on XAML does not help me on dynamic columns and I can not find a way to bind them any other way.
More info: The datagrid (and the data demonstration) above belongs to shop1 and I want to collect monthly revenues of it`s departments on a window/user control . Each shop has the same count of departments throughout the month, but this does not mean that every department should have revenues each day, it can be zero. The department may be closed for any day, so does not raise any revenue for the day. Shop2 might have entirely different departments for the same month, so I will not handle all shops in the same screen.
EDIT 1: More info about scenario added.