从MVVM WPF中的视图属性组合复杂模型对象(在viewmodel中)的新模型对象[递归]

时间:2013-05-27 17:57:19

标签: wpf mvvm prism

我有一个名为Client的视图类,它的视图模型是ClientViewModel。 ClientViewModel有一个模型对象ClientInfo。此ClientInfo [Model]是复杂对象,具有名为Client&的Model类的属性。 ClientProfile。

我在View中绑定了我的UI元素的属性,如下所示(我使用xxx.yyy.zzz来到属性)

 <Label Content="First Name:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3,5,0,4" VerticalAlignment="Center" Height="26" Width="70" />
                <TextBox Grid.Column="1" Grid.Row="1" Height="24" HorizontalAlignment="Left" Margin="3,7,0,4" Name="firstNameTextBox" Text="{Binding Path=ClientInfo.Client.FirstName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
                <Label Content="Last Name:" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" Margin="3,3,0,6" VerticalAlignment="Center" Height="26" Width="69" />
                <TextBox Grid.Column="1" Grid.Row="2" Height="24" HorizontalAlignment="Left" Margin="3,5,0,6" Name="lastNameTextBox" Text="{Binding Path=ClientInfo.Client.LastName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
.. 
<Button Content="Save" Height="24" Grid.Column="0" Grid.Row="0"   Command="{Binding SubmitCommand}" Cursor="Hand" Margin="549,10,10,0" Name="button1" VerticalAlignment="Top" Width="75" RenderTransformOrigin="-0.137,-1.804" />

ClientViewModel:

[Export(typeof(ClientViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ClientViewModel : NotificationObject
{

    private readonly IClientService clientService;

    private ClientInfo clientInfoModel;
    private string currentState;
    public DelegateCommand<object> SubmitCommand { get; private set; }
    public DelegateCommand<object> UpdateCommand { get; private set; }
    public DelegateCommand<object> LoadCommand { get; private set; }

    [Import]
    public ClientInfo ClientInfoModel
    {
        get { return this.clientInfoModel; }
        set
        {
            clientInfoModel = value;
            this.RaisePropertyChanged(() => this.ClientInfoModel);
        }
    }

    [ImportingConstructor]
    public ClientViewModel(IClientService clientService)
    {
        this.clientService = clientService;


        this.SubmitCommand = new DelegateCommand<object>(this.Submit);
        this.UpdateCommand = new DelegateCommand<object>(this.Update);
        this.LoadCommand = new DelegateCommand<object>(this.Load);
    }

    private void Load(object obj)
    {
        throw new NotImplementedException();
    }

    private void Update(object obj)
    {
        //update
        throw new NotImplementedException();
    }

    private void Submit(object obj)
    {
        string s = this.ClientInfoModel.ClientBasic.FirstName;//<--- this where i get the NPE exception
    }

    public string ViewName
    {
        get { return "Client Details"; }
    }

    public string CurrentState
    {
        get
        {
            return this.currentState;
        }

        set
        {
            if (this.currentState == value)
            {
                return;
            }

            this.currentState = value;
            this.RaisePropertyChanged(() => this.CurrentState);
        }
    }

    public bool CanSubmit
    {
        get { return true; }
    }

    public void Submit()
    {
        this.CurrentState = "Submitting";
        //this.clientRepository.SaveClientAsync(this.ClientInfoModel, result => { SaveClient(); });

    }

    private object SaveClient()
    {
        this.CurrentState = "Saving";

        return null;
    }
}

ClientInfo(Model):

public class ClientInfo : DomainObject
    {
        public Client ClientBasic { get; set; }

        public ClientProfile Profile { get; set; }
    }

客户(型号):

public class Client : DomainObject
    {
        public int ID { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        ....
    }

在提交命令调用中:

private void Submit(object obj)
        {
            ClientInfo ci = new ClientInfo();
            ci.Client <-- (here i would want to get the new Client obj assigned from properties?)
            ci.ClientProfile <---(same as above)
        }

在保存命令中,视图有提交按钮以保存。我必须保存调用某些服务的新客户端对象。

这里的问题是,我需要用新的Client()&amp ;;填写ClientInfo模型。新的ClientProfile()对象。我怎么能用这个设置做到这一点。

1 个答案:

答案 0 :(得分:1)

我可以在这里看到几点,我会做的不同。但是,一般情况下,你发布的内容一切都很好,你没有发布的内容肯定有些错误。请发布完整的ViewModel类,并解释如何将M传递给VM,将VM传递给V,我将再看看它。

如果执行ClientInfoSubmit(..)为空,则表示您的ViewModel没有模型。在ViewModel上分配ClientInfo时,一定有问题。尝试在ClientInfos set accessor中设置断点,看看它是否只设置一次。尝试在例如FirstName的set访问器中设置断点,并在UI中输入名称时查看它是否被命中。输出控制台中是否显示任何BindingErrors?

话虽如此,你确定要做你想做的事吗?如果您创建新的ClientInfo类,并从另一个Client类分配属性ClientProfileClientInfo,则您的两个ClientInfo对象指向完全相同的{ {1}}和Client对象。由于ClientProfile只有这两个属性,我可以想到你为什么会复制ClientInfo对象。你可以很好地使用原始对象,这是你的ViewModel模型......

其次,你的ViewModel直接暴露了Model,这实际上并不是ViewModel的重点,特别是当你最终得到像

这样的链式绑定时
ClientInfo

ViewModels核心竞争力是聚合数据并允许从View轻松绑定。我将在ViewModel上公开Text="{Binding Path=ClientInfo.Client.FirstName}" FirstName等属性,让ViewModel找出从哪里获取数据并将数据推送到。请记住,您希望独立于后台的任何实现细节保持View。

也许这两个建议已经解决或完全避免了这个问题。否则请随时发布更多上下文,我会再看看。

修改

在你的ViewModel中,我希望像

这样的东西
LastName

您注入了服务,但是在哪里初始化ClientInfoModel = clientService.GetClientInfo(...);