简体   繁体   中英

Listening to dependency property changes on one viewmodel from another viewmodel

I have a view model for a data entry view in my WPF app. Using MVVM, I am trying to account for a scenario in which there is a possibility to have a "shipped to customer" and a different "billed to customer" if need be.

My view has 2 sections: Billing Customer and Shipping Customer. The shipping customer can be automatically filled from the billing customer, or not filled at all (if not being shipped) or manually filled in (if the shipping to is different).

查看镜头

The bill to is currently bound to my MainWindowViewModel.BilledCustomer's properties via XAML. the "BeingShipped" checkbox is regulating the stackpanel that holds all the fields for Ship to via data binding on IsChecked property.

 public class MainWindowViewModel : ViewViewModelBase
{
    public bool Validated = false;
    public bool Saved = false;

    private MenuViewModel _menumodel;

    public ObservableCollection<BillablePartViewModel> WorkOrderParts { get; set; }

    public ObservableCollection<BillableServiceViewModel> WorkOrderServices { get; set; }

    public CustomerViewModel BilledCustomer { get; set; }

    public CustomerViewModel ShippedCustomer { get; set; }

    public WorkOrderViewModel WorkOrder { get; set; }

    //App.config fields
    public string Company_Name { get; set; }
    public string Company_Address { get; set; }
    public string Company_Phone { get; set; }
    public string Company_Fax { get; set; }
    public string Company_Site { get; set; }
    public string Company_Department { get; set; }

    public MainWindowViewModel(ObservableCollection<BillablePartViewModel> parts, ObservableCollection<BillableServiceViewModel> services
        , CustomerViewModel billedCustomer, CustomerViewModel shippedCustomer, WorkOrderViewModel workOrder
        , CommandBindingCollection bindings) : base(bindings)
    {
        this.WorkOrderParts = parts;
        this.WorkOrderServices = services;
        this.BilledCustomer = billedCustomer;
        this.ShippedCustomer = shippedCustomer;
        this.WorkOrder = workOrder;
        GetCompanyInfo();
    }
    public MainWindowViewModel(CommandBindingCollection bindings) : base(bindings)
    {
        _menumodel = new MenuViewModel(bindings);
        this.WorkOrder = new WorkOrderViewModel();
        GetCompanyInfo();
    }  

Customer View Model###

 public class CustomerViewModel : Accu_Base_Lib.Bases.ModelViewModelBase<DAL.Customer>
{



    public string Name
    {
        get { return (string)GetValue(NameProperty); }
        set { SetValue(NameProperty, value);
        string[] names = value.Split(' ');
            if (names.Length > 1)
            {
                this.FirstName = names[0];
                this.LastName = names[1];
            }

            else if (names.Length == 1)
            {
                this.FirstName = names[0];
            }
            else
            {
                //name deleted
                this.FirstName = string.Empty;
                this.LastName = string.Empty;
            }
        }
    }

    // Using a DependencyProperty as the backing store for Name.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty NameProperty =
        DependencyProperty.Register("Name", typeof(string), typeof(CustomerViewModel));




    public string Id
    {
        get { return (string)GetValue(IdProperty); }
        set { SetValue(IdProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Id.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IdProperty =
        DependencyProperty.Register("Id", typeof(string), typeof(CustomerViewModel));




    public string FirstName
    {
        get { return (string)GetValue(FirstNameProperty); }
        set { SetValue(FirstNameProperty, value);
        this.Name = this.FirstName + " " + this.LastName;
        }
    }

    // Using a DependencyProperty as the backing store for FirstName.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FirstNameProperty =
        DependencyProperty.Register("FirstName", typeof(string), typeof(CustomerViewModel));




    public string CompanyName
    {
        get { return (string)GetValue(CompanyNameProperty); }
        set { SetValue(CompanyNameProperty, value); }
    }

    // Using a DependencyProperty as the backing store for CompanyName.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CompanyNameProperty =
        DependencyProperty.Register("CompanyName", typeof(string), typeof(CustomerViewModel));





    public string StreetAddress
    {
        get { return (string)GetValue(StreetAddressProperty); }
        set { SetValue(StreetAddressProperty, value); }
    }

    // Using a DependencyProperty as the backing store for StreetAddress.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StreetAddressProperty =
        DependencyProperty.Register("StreetAddress", typeof(string), typeof(CustomerViewModel));







    public string City
    {
        get { return (string)GetValue(CityProperty); }
        set { SetValue(CityProperty, value); }
    }

    // Using a DependencyProperty as the backing store for City.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CityProperty =
        DependencyProperty.Register("City", typeof(string), typeof(CustomerViewModel));





    public string State
    {
        get { return (string)GetValue(StateProperty); }
        set { SetValue(StateProperty, value); }
    }

    // Using a DependencyProperty as the backing store for State.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StateProperty =
        DependencyProperty.Register("State", typeof(string), typeof(CustomerViewModel));




    public string Zip
    {
        get { return (string)GetValue(ZipProperty); }
        set { SetValue(ZipProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Zip.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ZipProperty =
        DependencyProperty.Register("Zip", typeof(string), typeof(CustomerViewModel));




    public string Phone
    {
        get { return (string)GetValue(PhoneProperty); }
        set { SetValue(PhoneProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Phone.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PhoneProperty =
        DependencyProperty.Register("Phone", typeof(string), typeof(CustomerViewModel));




    public string LastName
    {
        get { return (string)GetValue(LastNameProperty); }
        set { SetValue(LastNameProperty, value);
        this.Name = this.FirstName + " " + this.LastName;
        }
    }

    // Using a DependencyProperty as the backing store for LastName.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty LastNameProperty =
        DependencyProperty.Register("LastName", typeof(string), typeof(CustomerViewModel));




    public string Email
    {
        get { return (string)GetValue(EmailProperty); }
        set { SetValue(EmailProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Email.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty EmailProperty =
        DependencyProperty.Register("Email", typeof(string), typeof(CustomerViewModel));













    public CustomerViewModel(DAL.Customer model)

    {
        base.Init(model);
        //Fills this viewmodel based off the model supplied.
        UpdateViewModelFromModel();
    }

    public CustomerViewModel() 
    {
        base.Init();
        this.Model.Id = Guid.NewGuid().ToString();
        UpdateViewModelFromModel();
    }  

I thought about setting conditions in the Setters for this scenario within the actual CustomerViewModel but I don't want to add logic to a class if it's logic will only be used in one view. I want to keep the logic within my actual MainWindowViewModel . How can I accomplish this using an MVVM approach?

For your class CustomerViewModel I can see only fields of type string in it, so you can use MemberwiseClone() method to create a clone object for CustomerViewModel.

public class CustomerViewModel
{
   .....

   public CutomerViewModel Clone()
   {
      return (CustomerViewModel)MemberwiseClone();
   }

   .....
}

And in your MainWindowViewModel when Being Shipped checkBox get checked:

ShippedCustomer = BilledCustomer.Clone();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM