-1

I have two UserControls Payroll and TabLayout. Payroll contains a ToolBar and TabControl and TabLayout contains a Grid. The TabItems for TabControl in Payroll are populated with TabLayout via ObservableCollection in my MainViewModel.

About an hour ago, I asked this question: WPF Unable to retrieve binding values MVVM, and got it resolved.

Now I'm faced with a problem where, because the ViewModel is now a single instance, the information in one Tab is being carried over to another. Therefore all Tabs show the same thing.

If I create a new instance of the ViewModel for each Tab then I won't be able to retrieve the binding values anymore.

MainViewModel:

namespace OcelotPayroll.ViewModel
{
    public class MainViewModel : ViewModelBase
    {    
        public ObservableCollection<WorkspaceViewModel> Workspaces { get; set; }            

        public MainViewModel()
        {
            Workspaces = new ObservableCollection<WorkspaceViewModel>();
        }


        private DelegateCommand _newWorkspaceCommand;
        public ICommand NewWorkspaceCommand
        {
            get { return _newWorkspaceCommand ?? (_newWorkspaceCommand = new DelegateCommand(NewWorkspace)); }
        }

        private void NewWorkspace()
        {

            var workspace = new WorkspaceViewModel
            {
                LoadedControl = new TabLayout() { DataContext = this }
            };
            Workspaces.Add(workspace);
            SelectedIndex = Workspaces.IndexOf(workspace);
        }
    }
}

Payroll DataContext is set:

public Payroll()
    {
        InitializeComponent();
        DataContext = new PayslipModel();
    }

PayslipModel/VM:

namespace OcelotPayroll
{
    public class PayslipModel : EmployeeModel
    {    
        private decimal _amount;

        public decimal Amount
        {
            get
            {
                return _amount;
            }
            set
            {
                _amount = value;
                OnPropertyChanged("Amount");
            }
        }

        public string NisName
        {
            get
            {
                return _nis;
            }
            set
            {
                _nis = value;
                OnPropertyChanged("NisName");
            }
        }

        public string EdTaxName
        {
            get
            {
                return _edtax;
            }
            set
            {
                _edtax = value;
                OnPropertyChanged();
            }
        }

        public string NhtName
        {
            get
            {
                return _nht;
            }
            set
            {
                _nht = value;
                OnPropertyChanged();
            }
        }

        public string PayeName
        {
            get
            {
                return _paye;
            }
            set
            {
                _paye = value;
                OnPropertyChanged();
            }
        }

        public string NisVal
        {
            get
            {
                return _nisVal;
            }
            set
            {
                _nisVal = value;
                OnPropertyChanged();
            }
        }

        public string EdTaxVal
        {
            get
            {
                return _edVal;
            }
            set
            {
                _edVal = value;
                OnPropertyChanged();
            }
        }

        public string NhtVal
        {
            get
            {
                return _nhtVal;
            }
            set
            {
                _nhtVal = value;
                OnPropertyChanged();
            }
        }

        public string PayeVal
        {
            get
            {
                return _payeVal;
            }
            set
            {
                _payeVal = value;
                OnPropertyChanged();
            }
        }

        public decimal StautoryIncome
        {
            get
            {
                return statIncome;
            }
            set
            {
                statIncome = value;
            }
        }

        public string TotalDeduction
        {
            get
            {
                return totalDed;
            }
            set
            {
                totalDed = value;
                OnPropertyChanged();
            }
        }

        public string NetPay
        {
            get
            {
                return _netpay;
            }
            set
            {
                _netpay = value;
                OnPropertyChanged();
            }
        }

        public bool NisChecked
        {
            get
            {
                return nisIsChecked;
            }
            set
            {
                nisIsChecked = value;

                OnPropertyChanged("NisChecked");

                CalcNis();
            }
        }

        public bool EdTaxChecked
        {
            get
            {
                return edtaxIsChecked;
            }
            set
            {
                edtaxIsChecked = value;
                OnPropertyChanged();
                CalcEdTax();
            }
        }

        public bool NhtChecked
        {
            get
            {
                return nhtIsChecked;
            }
            set
            {
                nhtIsChecked = value;
                OnPropertyChanged();
                CalcNht();
            }
        }

        public bool PayeChecked
        {
            get
            {
                return payeIsChecked;
            }
            set
            {
                payeIsChecked = value;
                OnPropertyChanged();
                CalcPaye();
            }
        }

        public bool LevyChecked
        {
            get
            {
                return levyIsChecked;
            }
            set
            {
                levyIsChecked = value;
                OnPropertyChanged();
                CalcLevy();
            }
        }

        public bool WeeklyChecked
        {
            get
            {
                return wklyIsChecked;
            }
            set
            {
                wklyIsChecked = value;
                OnPropertyChanged();
            }
        }

        public bool FnChecked
        {
            get
            {
                return fnIsChecked;
            }
            set
            {
                if (fnIsChecked == value)
                    return;

                fnIsChecked = value;
                OnPropertyChanged();
            }
        }
        public bool MonthlyChecked
        {
            get
            {
                return monthlyIsChecked;
            }
            set
            {
                if (monthlyIsChecked == value)
                    return;

                monthlyIsChecked = value;
                OnPropertyChanged();
            }
        }

        private DateTime _date;
        public DateTime Date
        {
            get
            {
                return _date;

            }
            set
            {
                _date = value;
            }
        }

        private string _annualGross;

        public string AnnualGross
        {
            get
            {
                return _annualGross;
            }
            set
            {
                _annualGross = value;
                OnPropertyChanged();
            }
        }

        private string _annualNis;

        public string AnnualNis
        {
            get
            {
                return _annualNis;
            }
            set
            {
                _annualNis = value;
                OnPropertyChanged();
            }
        }

        private string _annualNht;

        public string AnnualNht
        {
            get
            {
                return _annualNht;
            }
            set
            {
                _annualNht = value;
                OnPropertyChanged();
            }
        }

        private string _annualEdtax;

        public string AnnualEdTax
        {
            get
            {
                return _annualEdtax;
            }
            set
            {
                _annualEdtax = value;
                OnPropertyChanged();
            }
        }

        private string _annualPaye;

        public string AnnualPaye
        {
            get
            {
                return _annualPaye;
            }
            set
            {
                _annualPaye = value;
                OnPropertyChanged();
            }
        }

        public PayslipModel()
        {    
            Date = DateTime.Today.Date;

            SelectAll = new DelegateCommand(Select, () => CanSelect);

            UnSelectAll = new DelegateCommand(UnSelect, () => CanUnSelect);

            SaveToDatabase = new DelegateCommand(Save, () => CanSave);

            scon = new MichaelAllenEntities();

        }

        public ICommand SelectAll
        {
            get; set;
        }

        private bool CanSelect
        {
            get { return Hide1 = true; }
        }

        private void Select()
        {
            if (Hide1 == true)
            {
                NisChecked = true;
                EdTaxChecked = true;
                NhtChecked = true;
                PayeChecked = true;
            }
        }

        public ICommand UnSelectAll
        {
            get; set;
        }

        private bool CanUnSelect
        {
            get { return Hide1 = true; }
        }

        private void UnSelect()
        {
            if (Hide1 == true)
            {
                NisChecked = false;
                EdTaxChecked = false;
                NhtChecked = false;
                PayeChecked = false;
            }
        }

        public ICommand SaveToDatabase
        {
            get; set;
        }

        private bool CanSave
        {
            get { return Workspaces.Count > 0; }
        }      

        private async void Save()
        {
            try
            {
                var salary = new SalaryInfo
                {
                    EmpId = SelectedEmployee.EmpId,
                    EmpName = SelectedEmployee.EmpName,
                    NIS = decimal.Parse(NisVal.ToString()),
                    NHT = decimal.Parse(NhtVal.ToString()),
                    EdTax = decimal.Parse(EdTaxVal.ToString()),
                    PAYE = decimal.Parse(PayeVal.ToString()),
                    TotalTax = decimal.Parse(TotalDeduction.ToString()),
                    StatutoryIncome = StautoryIncome,
                    GrossPay = Amount,
                    NetPay = decimal.Parse(NetPay.ToString()),
                    Date = Date,
                    Earnings = Earnings,
                    PayPeriod = SelectedValueOne.Value
                };
                scon.SalaryInfoes.Add(salary);
                scon.SaveChanges();
            }
            catch (DbEntityValidationException ex)
            {

            }
            catch(Exception ex)
            {
                var exceptionDialog = new MessageDialog
                {
                    Message = { Text = string.Format("{0}", ex) }
                };

                await DialogHost.Show(exceptionDialog, "RootDialog");
            }

        }

        private bool _hide1 = true;

        public bool Hide1
        {
            get
            {
                return _hide1;
            }
            set
            {
                _hide1 = value;
                OnPropertyChanged();
            }
        }

        private bool _hide2 = false;

        public bool Hide2
        {
            get
            {
                return _hide2;
            }
            set
            {
                _hide2 = value;
                OnPropertyChanged();
            }
        }

        private EmployeeInfo _selectedEmployee;

        public new EmployeeInfo SelectedEmployee
        {
            get { return _selectedEmployee; }
            set
            {
                _selectedEmployee = value;
                OnPropertyChanged();

                if(SelectedEmployee.EmployedUnder == "Michael Allen")
                {
                    Hide1 = true;
                    Hide2 = false;
                }
                if(SelectedEmployee.EmployedUnder == "Barachel Ltd")
                {
                    Hide2 = true;
                    Hide1 = false;
                }
            }
        }

        private string _hours;

        public string Hours
        {
            get
            {
                return _hours;
            }
            set
            {
                _hours = value;
                OnPropertyChanged();
            }
        }

        private string _rate;

        public string Rate
        {
            get
            {
                return _rate;
            }
            set
            {
                _rate = value;
                OnPropertyChanged();
                if (Rate != string.Empty || Hours != string.Empty)
                {
                    Amount = decimal.Parse((double.Parse(Hours.ToString()) * double.Parse(Rate.ToString())).ToString());
                }else
                {
                    Amount = 0;
                }
            }
        }

        private string _selectedDate;

        public string SelectedDate
        {
            get
            {
                return _selectedDate;
            }
            set
            {
                _selectedDate = value;
                OnPropertyChanged();
            }
        }

        private string _earnings;

        public string Earnings
        {
            get
            {
                return _earnings;
            }
            set
            {
                _earnings = value;
                OnPropertyChanged();
            }
        }

        #region Calculations

        public async void CalcNis()
        {
            try
            {
                float nis = 0;

                NisName = "N.I.S.";

                SqlConnection con = new SqlConnection(scon.Database.Connection.ConnectionString);
                con.Open();
                SqlCommand cmd = new SqlCommand("select NIS from Deductions where TaxId='1'", con);

                SqlDataReader sdr = cmd.ExecuteReader();
                while (sdr.Read())
                {
                    nis = float.Parse(sdr.GetValue(0).ToString());
                }

                con.Close();

                if (Amount != 0)
                {
                     NisVal = (decimal.Parse(Amount.ToString()) * decimal.Parse(nis.ToString())).ToString("N2");
                     StautoryIncome = (decimal.Parse(Amount.ToString()) - decimal.Parse(NisVal.ToString()));
                }
            }
            catch(Exception ex)
            {
                var exceptionDialog = new MessageDialog
                {
                    Message = { Text = ex.ToString() }
                };

                await DialogHost.Show(exceptionDialog, "RootDialog");
            }
        }

        public async void CalcLevy()
        {
            try
            {
                if(LevyChecked == true)
                {
                    float levy = 0;

                    NisName = "Contractor's Levy";

                    SqlConnection con = new SqlConnection(scon.Database.Connection.ConnectionString);
                    con.Open();
                    SqlCommand cmd = new SqlCommand("select ContractorLevy from Deductions where TaxId='1'", con);

                    SqlDataReader sdr = cmd.ExecuteReader();
                    while (sdr.Read())
                    {
                        levy = float.Parse(sdr.GetValue(0).ToString());
                    }

                    con.Close();

                    if (Amount != 0)
                    {

                        NisVal = (double.Parse(Amount.ToString()) * double.Parse(levy.ToString())).ToString("N2");

                        TotalDeduction = double.Parse(NisVal.ToString()).ToString("N2");

                        NetPay = (double.Parse(Amount.ToString()) - double.Parse(NisVal.ToString())).ToString("N2");
                    }
                }else
                    if(LevyChecked == false)
                {
                    NisVal = string.Empty;
                    TotalDeduction = string.Empty;
                    NetPay = string.Empty;
                }
            }
            catch (Exception ex)
            {
                var exceptionDialog = new MessageDialog
                {
                    Message = { Text = ex.ToString() }
                };

                await DialogHost.Show(exceptionDialog, "RootDialog");
            }
        }

        public async void CalcEdTax()
        {
            try
            {
                float edtax = 0;

                EdTaxName = "EDUCATION TAX";

                SqlConnection con = new SqlConnection(scon.Database.Connection.ConnectionString);
                con.Open();
                SqlCommand cmd = new SqlCommand("select EdTax from Deductions where TaxId='1'", con);

                SqlDataReader sdr = cmd.ExecuteReader();
                while (sdr.Read())
                {
                    edtax = float.Parse(sdr.GetValue(0).ToString());
                }

                con.Close();

                if (EdTaxName != string.Empty)
                {
                    if (StautoryIncome != 0)
                    {
                        EdTaxVal = (statIncome * decimal.Parse(edtax.ToString())).ToString("N2");
                    }
                }
            }
            catch (Exception ex)
            {
                var exceptionDialog = new MessageDialog
                {
                    Message = { Text = ex.ToString() }
                };

                await DialogHost.Show(exceptionDialog, "RootDialog");
            }
        }

        public async void CalcNht()
        {
            try
            {
                float nht = 0;

                NhtName = "N.H.T.";

                SqlConnection con = new SqlConnection(scon.Database.Connection.ConnectionString);
                con.Open();
                SqlCommand cmd = new SqlCommand("select NHT from Deductions where TaxId='1'", con);

                SqlDataReader sdr = cmd.ExecuteReader();
                while (sdr.Read())
                {
                    nht = float.Parse(sdr.GetValue(0).ToString());
                }

                con.Close();

                if (Amount != 0)
                {
                    NhtVal = (decimal.Parse(Amount.ToString()) * decimal.Parse(nht.ToString())).ToString("N2");
                }
            }
            catch (Exception ex)
            {
                var exceptionDialog = new MessageDialog
                {
                    Message = { Text = ex.ToString() }
                };

                await DialogHost.Show(exceptionDialog, "RootDialog");
            }
        }

        private decimal _totalAmount;

        public decimal TotalAmount
        {
            get
            {
                return _totalAmount;
            }
            set
            {
                _totalAmount = value;
                OnPropertyChanged();
            }
        }

        public async void CalcPaye()
        {
            try
            {
                float paye = 0;
                decimal threshold = 0, taxable = 0, above = 0.3M;

                if (PayeChecked == true)
                {
                    PayeName = "P.A.Y.E.";

                    SqlConnection con = new SqlConnection(scon.Database.Connection.ConnectionString);
                    con.Open();
                    SqlCommand cmd = new SqlCommand("select PAYE, FNTaxThreshold from Deductions where TaxId='1'", con);

                    SqlDataReader sdr = cmd.ExecuteReader();

                    if (Amount != 0)
                    {
                        while (sdr.Read())
                        {
                            paye = float.Parse(sdr.GetValue(0).ToString());
                            threshold = decimal.Parse(sdr.GetValue(1).ToString());
                        }

                        con.Close();

                        //
                        //Fortnightly
                        //
                        if (FnChecked == true)
                        {

                            if (threshold <= decimal.Parse(Amount.ToString()))
                            {
                                if ((double.Parse(Amount.ToString()) * 2) * 12 <= 796536)
                                {
                                    taxable = StautoryIncome - threshold;
                                    PayeVal = (taxable * 0).ToString("N2");
                                }
                                else if ((double.Parse(Amount.ToString()) * 2) * 12 >= 796536 && (double.Parse(Amount.ToString()) * 2) * 12 <= 6000000)
                                {
                                    taxable = StautoryIncome - threshold;
                                    PayeVal = (taxable * decimal.Parse(paye.ToString())).ToString("N2");
                                }
                                else if ((double.Parse(Amount.ToString()) * 2) * 12 > 6000000)
                                {
                                    taxable = StautoryIncome - threshold;
                                    PayeVal = (taxable * above).ToString("N2");
                                }

                            }
                        }

                        //
                        //Monthly Checked
                        //
                        if (MonthlyChecked == true)
                        {
                            con.Open();

                            cmd = new SqlCommand("select MonthlyThreshold from Deductions where TaxId='1'", con);
                            sdr = cmd.ExecuteReader();

                            while (sdr.Read())
                            {
                                threshold = decimal.Parse(sdr.GetValue(0).ToString());
                            }

                            con.Close();

                            if (threshold <= decimal.Parse(Amount.ToString()))
                            {
                                if ((double.Parse(Amount.ToString()) * 2) * 12 <= 796536)
                                {
                                    taxable = StautoryIncome - threshold;
                                    PayeVal = (taxable * 0).ToString("N2");
                                }
                                else if ((double.Parse(Amount.ToString()) * 2) * 12 >= 796536 && (double.Parse(Amount.ToString()) * 2) * 12 <= 6000000)
                                {
                                    taxable = StautoryIncome - threshold;
                                    PayeVal = (taxable * decimal.Parse(paye.ToString())).ToString("N2");
                                }
                                else if ((double.Parse(Amount.ToString()) * 2) * 12 > 6000000)
                                {
                                    taxable = StautoryIncome - threshold;
                                    PayeVal = (taxable * above).ToString("N2");
                                }

                            }
                            else if (threshold > decimal.Parse(Amount.ToString()))
                            {
                                PayeVal = (0).ToString("N2");
                            }
                        }

                    }

                    if (EdTaxVal != string.Empty || NhtVal != string.Empty || NisVal != string.Empty || PayeVal != string.Empty)
                    {
                        double total = 0;


                        total = double.Parse(NisVal.ToString()) + double.Parse(PayeVal.ToString()) + double.Parse(NhtVal.ToString()) + double.Parse(EdTaxVal.ToString());

                        TotalDeduction = total.ToString("N2");

                        NetPay = (double.Parse(Amount.ToString()) - total).ToString("N2");
                    }
                }
                else if(PayeChecked == false)
                {
                    if (PayeVal != string.Empty)
                    {
                        PayeName = string.Empty;
                        taxable += decimal.Parse(PayeVal.ToString());
                        StautoryIncome += taxable;
                    }
                }
            }
            catch (Exception ex)
            {
                var exceptionDialog = new MessageDialog
                {
                    Message = { Text = ex.ToString() }
                };

                await DialogHost.Show(exceptionDialog, "RootDialog");
            }
        }

        #endregion
    }
}
Community
  • 1
  • 1
bruh1234
  • 67
  • 10
  • MVVM is meant to separate UI and Data layers, and you look like you're combining them. I don't have time to write a full answer + example now, but you can see an example of how MVVM is used in a TabControl structure [here](https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/). The only place I would ever expect to see the DataContext set is the initial binding for application startup. Anywhere else sends up red warning flags to me. – Rachel Feb 08 '17 at 19:48
  • @Rachel, The example you provided isn't really what I'm looking for, and you're right about the DataContext. I've removed it for now – bruh1234 Feb 08 '17 at 20:57

2 Answers2

0

If you want the tabs to be able to show different values you obviously need to create a new instance of your class for each TabLayout that you create. You could copy the property values one way or another:

var workspace = new WorkspaceViewModel
{
    LoadedControl = new TabLayout() { DataContext = new PayslipModel() { Amount = this.Amount, NisName = this.NisName, /* and so on for each property ... */} }
};

You can't set the DataContext of all items to the very same instance.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • That's partly the issue, `NewWorkspace()` is held within the MainViewModel and PayslipModel is a separate ViewModel that deals with what is displayed on tabs. So I'm not able to copy properties as you've suggested. If there is a much better way of handling Tabs in MVVM that you might suggest I try, then I don't mind :) – bruh1234 Feb 08 '17 at 19:41
  • If you don't think that someone will somehow be able to guess how your code looks like and what the relationship between your types is and you still want you, you should really read this: http://stackoverflow.com/help/mcve – mm8 Feb 08 '17 at 19:44
  • I've updated the question. Just as a side note, the UserControl Payroll is a child of the MainWindow, so it's referenced like `` and TabLayout would be a child of Payroll, thats when it gets added to Workspace. – bruh1234 Feb 08 '17 at 20:26
0

You can use ViewModelLocator pattern to resolve this. Basically this pattern consist of a Class ,which has all the required DataContext as Property. This can be static. And you dont have to set DataContext on CodeBehind, you can set in XAML with Resources.

Refer to: First
Second

WPFUser
  • 1,145
  • 7
  • 24