Hi All,
I'm about 2 months new to C# and WPF. I am trying to solve the following situation that I need to accomplish. Any help would be appreciated.
The scenario is what I need to achieve as follows:
1) If I have a
Single Data Model object that has one or more properties, I need to display the properties as when they change - I have no issue with this as I am binding the properties using
INotifyPropertyChanged
2) If I have a
Composite Data Model, it is made up of two or more of the
Single Data Model objects. If there are 3 properties in the
Single Data Model such as Name, Score, Rank, then there are also 3 same properties in the
Composite Data Model. However, the property values of those in the
Composite Data Model are dependent on any change in value of those in the
Single Data Model
Both Models implement INotifyPropertyChanged and IBaseModel (see the List<ibasemodel> below in my source code)
For instance, if:
SDM1 (Single Data Model): [Name=Man, Score=50, Rank=5]
SDM2 (Single Data Model): [Name=Woman, Score=70, Rank=8]
The CDM (Composite Data Model) for this should be the following:
CDM : [Name=Man/Women, Score=(70+50)/2, Rank=(8-5).
3) In my Data Grid, I should see:
Man 50 5
Woman 70 8
Man/Woman 60 3
4) Now, if tomorrow, the Score for SDM1 (Man) should change to 30, my CDM should recalculate the value for Score to (70+30/2) and update the Data Grid display for:
Man/Woman 50 3
5) If again, SDM2 (Woman) the Rank changes to 10, my CDM should change to (10-5)
Man/Woman 50 5
The main problem I have having is the following:
a. How can I create any dependency on the SMD's such that if any property changes in it, it should trigger a a re-calculation in the CMD for those specific properties and change the property value in the data grid.
I know that I can use the Observer pattern and register the CMD as an Observer and the properties in the SDM's as Subjects and have the CMD properties observe the specific properties of the subject (SDM1 and SMD2).
However, what I'm seeing is that simply assigning the value of set method in the CDM for Score to the following is not enough to trigger any such change to the WPF
private double _score;
public double Score
{
get
{
Debug.WriteLine(this.ToString() + ": Score - (GET) - [_score=" + _score+ "]");
return _score;
}
set
{
Debug.WriteLine(this.ToString() + ": Score - (SET) - [value=" + value + "]");
this._score= (sdm1.Score - sdm2.Score)/2;
OnPropertyChanged("Score");
}
}
I have a simple Data Grid as follows:
<UserControl x:Class="ValueModelTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
Height="350" Width="503">
<UserControl.Resources>
<ResourceDictionary>
<CollectionViewSource x:Key="MyDataSource"/>
</ResourceDictionary>
</UserControl.Resources>
<DockPanel Name="DP" LastChildFill="False">
<dg:DataGrid x:Name="DG" ItemsSource="{Binding Source={StaticResource MyDataSource}}"
HeadersVisibility="Column"
CanUserAddRows="True"
AutoGenerateColumns="False">
<dg:DataGrid.Columns>
<dg:DataGridTextColumn Header="Name"
Binding="{Binding NAME}"
Width="150">
</dg:DataGridTextColumn>
<dg:DataGridTextColumn Header="A"
Binding="{Binding Score}"
Width="150">
</dg:DataGridTextColumn>
<dg:DataGridTextColumn Header="B"
Binding="{Binding Rank}"
Width="150">
</dg:DataGridTextColumn>
</dg:DataGrid.Columns>
</dg:DataGrid>
</DockPanel>
</UserControl>
In my MainView.xaml.cs, I have the following:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Markup;
using System.Diagnostics;
namespace ValueModelTest
{
public partial class MainWindow : UserControl
{
public MyDataModel s2Model;
public MyDataModel s5Model;
public MyCompositeModel scModel;
private static List<IBaseModel> dataSource;
private static CollectionViewSource dataViewSource;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
InitializeData();
}
public void InitializeData()
{
try
{
Debug.WriteLine(this.ToString() + ":InitializeData");
dataSource = new List<IBaseModel>();
s2Model = new MyModel();
s2Model.NAME = "Man";
s2Model.Score= 50;
s2Model.Rank= 5;
dataSource.Add(s2Model);
s5Model = new MyModel();
s5Model.NAME = "Woman";
s5Model.Score= 70;
s5Model.Rank= 8;
dataSource.Add(s5Model);
scModel = new MyCompositeModel (1, s2Model, s5Model);
scModel.NAME = s2Model.NAME + "/" + s5Model.NAME;
dataSource.Add(scModel);
dataViewSource = (CollectionViewSource)FindResource("MyDataSource");
dataViewSource.Source = dataSource;
}
catch (Exception ex)
{
Debug.WriteLine(this.ToString() + ": InitializeData Error - " + ex.StackTrace.ToString());
}
Debug.WriteLine("ValueModelTest: - Testing");
}
}
}