【问题标题】:Listening to dependency property changes on one viewmodel from another viewmodel从另一个视图模型侦听一个视图模型上的依赖项属性更改
【发布时间】:2014-05-28 17:16:08
【问题描述】:

我的 WPF 应用程序中有一个数据输入视图的视图模型。使用 MVVM,我试图说明一种情况,在这种情况下,如果需要,可能会有“运送给客户”和不同的“向客户收费”。

我的视图有 2 个部分:计费客户和运输客户。发货客户可以从计费客户那里自动填写,也可以完全不填写(如果没有发货)或手动填写(如果发货地址不同)。

帐单当前通过 XAML 绑定到我的 MainWindowViewModel.BilledCustomer 的属性。 “BeingShipped”复选框通过 IsChecked 属性上的数据绑定来调节包含 Ship 的所有字段的堆栈面板。

 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();
    }  

客户视图模型###

 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();
    }  

我考虑在实际的CustomerViewModel 中为该场景在 Setter 中设置条件,但如果逻辑仅用于一个视图,我不想将逻辑添加到类中。我想将逻辑保留在我的实际MainWindowViewModel 中。如何使用 MVVM 方法完成此任务?

【问题讨论】:

  • 首先你为什么要在 ViewModel 上创建这么多 DP? ViewModel 应该具有可以从 View 绑定到的普通 CLR 属性。无论如何,对于您的问题,为什么不在您的 Customer 类中使用 Clone() 方法,一旦 checkBox 被选中,设置ShippedCustomer = BilledCustomer.Clone()
  • ehhmmmm...DependencyProperties don't belong into ViewModels。删除所有这些。
  • 我读过的所有 MSDN 文档都使用 DP 而不是 CLR 属性。只需阅读那篇文章,并不能真正适用于这种情况。这是一个非常小的应用程序,最多 3 个窗口,我看到的唯一真正的问题是 DP 的线程关联问题。我认为 clone() 在这种情况下就足够了。感谢@HighCore 的文章,我会将其记录下来以用于更大的项目。
  • @Adrian PLEASE.. 给我看一个 MSDN 文档,使用 DPs for ViewModels(而不是 UI)。

标签: c# wpf mvvm


【解决方案1】:

对于你的类CustomerViewModel我只能看到其中的字符串类型的字段,所以你可以使用MemberwiseClone()方法为CustomerViewModel创建一个克隆对象。

public class CustomerViewModel
{
   .....

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

   .....
}

在您的 MainWindowViewModel 中,当被运送时复选框被选中:

ShippedCustomer = BilledCustomer.Clone();

【讨论】:

    猜你喜欢
    • 2011-07-04
    • 2011-08-09
    • 2014-10-06
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 1970-01-01
    相关资源
    最近更新 更多