1

I've just tried to start with MVVM after years of using code behind. I'm trying to get ThisClaimValue to update when PercentageComplete changes. ThisClaimValue is meant to show the percentage of ContractAmt, based on PercentageComplete. Either while people are putting in the value, or when they leave the cell. I'm trying to do this with zero code behind, so no built in events.

I'm using EF Database First for Description, ContractAmt, and BillCurrentAmt. PercentageComplete and ThisClaimValue are located in a seperate solution as a partial class to the class that EF created.

View:

   <DataGrid Margin="10,10,10,0" RowDetailsVisibilityMode="VisibleWhenSelected" EnableRowVirtualization="True" AutoGenerateColumns="False" ItemsSource="{Binding JCCISelectedList, UpdateSourceTrigger=PropertyChanged}" SelectedValue="{Binding JCCI}" Grid.Row="3">
        <DataGrid.Columns>
            <DataGridTextColumn   Binding="{Binding Description}" Header="Description" Width="Auto" IsReadOnly="True"/>
            <DataGridTextColumn  Binding="{Binding ContractAmt}" Header="Value" Width="Auto" IsReadOnly="True"/>
            <DataGridTextColumn  Binding="{Binding PercentageComplete, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="% Complete" Width="Auto"/>
            <DataGridTextColumn  Binding="{Binding BillCurrentAmt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="$ Complete" Width="Auto"/>
            <DataGridTextColumn  Binding="{Binding ThisClaimValue}" Header="This Claim Value" Width="Auto" IsReadOnly="True"/>
        </DataGrid.Columns>
    </DataGrid>

ViewModel:

  public class JBProgressBillItemsViewModel : INotifyPropertyChanged, IPageViewModel
    {
        public AcceptCommand AcceptEvent { get; set; }
        public BackCommand BackEvent { get; set; }
        public string Name => "JBProgressBillItems";

        public JBProgressBillItemsViewModel()
        {
            HQCOList = Facade.GetVistaHQCO();
            AcceptEvent = new AcceptCommand(this);
            BackEvent = new BackCommand(this);
        }
        private bHQCO _hqco;
        private bJCCM _jccm;
        private bJCCI _jcciSection;
        private bJCCI _jcci;

        public ObservableCollection<bHQCO> HQCOList { get; }
        public ObservableCollection<bJCCM> JCCMList { get; private set; }
        public ObservableCollection<bJCCI> JCCISectionList { get; private set; }
        public ObservableCollection<bJCCI> JCCIList { get; private set; }
        public ObservableCollection<bJCCI> JCCISelectedList { get; private set; }

        public bHQCO HQCO
        {
            get { return _hqco; }
            set
            {
                _hqco = value;
                JCCMList = Facade.GetVistaActiveProjects(_hqco.HQCo);
                RaisePropertyChanged(nameof(HQCO));
                RaisePropertyChanged(nameof(JCCMList));
            }
        }

        public bJCCM JCCM
        {
            get { return _jccm; }
            set
            {
                _jccm = value;
                JCCIList = Facade.GetVistaContractItems(_hqco.HQCo, _jccm.Contract);
                JCCISectionList =
                    new ObservableCollection<bJCCI>(JCCIList.Where(x => x.SICode == "H" || x.SICode == "SH"));
                RaisePropertyChanged(nameof(JCCM));
                RaisePropertyChanged(nameof(JCCISectionList));
            }
        }

        public bJCCI JCCISection
        {
            get { return _jcciSection; }
            set
            {
                _jcciSection = value;
                try
                {
                    JCCISelectedList = new ObservableCollection<bJCCI>(JCCIList.Where(x => _jcciSection.BillGroup == x.BillGroup && string.IsNullOrWhiteSpace(x.SICode)));
                }
                catch (ArgumentNullException)
                {
                }
                RaisePropertyChanged(nameof(JCCISection));
                RaisePropertyChanged(nameof(JCCISelectedList));
            }
        }

        public bJCCI JCCI
        {
            get { return _jcci; }
            set
            {
                _jcci = value;
                _jcci.ThisClaimValue = value.PercentageComplete * value.ContractAmt / 100;
                RaisePropertyChanged(nameof(JCCI));
                RaisePropertyChanged(nameof(JCCISelectedList));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public string Error => null;

    }

EDIT: Added full view model code above.

Phalanx
  • 55
  • 1
  • 9

2 Answers2

0

For it to work make sure JCCISelectedList is specified as ObservableCollection which would fix your problem.
Else you would need to raise Property changed event for each
Description
ContractAmt
....
each element separately as raiseproperty changed event doesnt generate any event for element changes as the property of JCCISelectedList remains same when element changes its the datacontext that is changing.

Jerin
  • 3,657
  • 3
  • 20
  • 45
  • I've added my full view model code above. I had it as an ObservableCollection. My issue is that datagrid isn't updating with the value. Even though the value is saved in memory. – Phalanx Jan 07 '16 at 21:03
  • Looks like @abhishek answered your question. If you are still facing a problem then a sample project with sample json would be great. – Jerin Jan 08 '16 at 05:49
0

So bJCCI is a table in EF and you want ThisClaimValue to update when PercentageComplete changes, where ThisClaimValue and PercentageComplete is a field in this table. Here you're calling RaisePropertyChanged for table object and collection changed not for particular field value changed like ThisClaimValue or PercentageComplete.

So the solution is create a Model class wrap your table fields with Model class Property like this

public class Model
{
    private bJCCI _jcci;
    public Double PerComplete
    {
        get { return _jcci.PercentageComplete ; }
        set
        {
            _jcci.PercentageComplete  = value;
            RaisePropertyChanged(nameof(PerComplete));
            RaisePropertyChanged(nameof(ClaimValue )); //Model property of ThisThisClaimValue field
        }
    }
}

Now, here when PerComplete property will be changed, ClaimValue property will be updated and notified. Bind these Model's property in Xaml, don't directly use EF model class.

Also In ViewModel create

public ObservableCollection<Model> MyCollection { get; set; }

and bind this with DataGrid item source.

Please refer this link; WPF MVVM INotifyPropertyChanged Implementation - Model or ViewModel

Hope this will give an idea :)

Community
  • 1
  • 1