Caliburn Micro:在ViewModel之间传递对象

3

我正在使用Caliburn Micro 2.0.0-alpha2开发一个简单的Crud应用程序(一个Windows 8.1商店应用程序),但在视图模型之间进行导航并传递对象方面遇到了困难。

我多次阅读了Anders Gustafsson提出的解决方案,试图将其调整为我的范围,但对象始终为null。

我需要将listView中选择的单个对象传递给我的crudPage。 crudPage由一个用户控件组成,显示FormView。因此,我希望使用传递对象的值初始化此表单。

我认为问题是“参数”只有在视图模型创建后才被初始化,但我不知道如何解决这个问题。

以下是根据Anders Gustafsson的想法编写的代码:TransporterListViewModel(来自数据库的Transporters列表)

public class TransporterListViewModel : ViewModelBase
{
    public string Title { get; set; }
    public TransporterListViewModel(INavigationService navigationService)
        : base(navigationService)
    {
        LoadData();
    }

    public async void LoadData() {

        _transporters = await TransporterService.GetAll();
    }

    private BindableCollection<Transporter> _transporters;

    public BindableCollection<Transporter> Transporters
    {
        get
        {
            return this._transporters;
        }
        set
        {
            this._transporters = value;
            NotifyOfPropertyChange(() => this.Transporters);
        }
    }

    private Transporter _selectedItem;
    public Transporter SelectedItem
    {
        get 
        {

            return _selectedItem;
        }

        set
        {
            _selectedItem = value;
            NotifyOfPropertyChange(() => this.SelectedItem);

            navigationService.Navigated += NavigationServiceOnNavigated;
            navigationService.NavigateToViewModel<TransporterCrudPageViewModel>(_selectedItem;);
            navigationService.Navigated -= NavigationServiceOnNavigated;
        }
    }

    private static void NavigationServiceOnNavigated(object sender, NavigationEventArgs args)
    {
        FrameworkElement view;
        TransporterCrudPageViewModel transporterCrudPageViewModel;
        if ((view = args.Content as FrameworkElement) == null ||
            (transporterCrudPageViewModel = view.DataContext as TransporterCrudPageViewModel) == null) return;

        transporterCrudPageViewModel.InitializeTransporterForm(args.Parameter as Transporter);
    } 

TransporterCrudViewModel(包含初始化用户控件的页面)

public class TransporterCrudPageViewModel : ViewModelBase
{
    public string Title { get; set; }

    public Transporter Parameter { get; set; }
    public TransporterFormViewModel TransporterFormVM { get; set; }

    public async void InitializeTransporterForm(Transporter enumerable)
    {
        TransporterFormVM = new TransporterFormViewModel(navigationService, enumerable);
        await SetUpForm(enumerable);
    }

    public async Task SetUpForm(Transporter t){
        TransporterFormVM.trName = t.trName;
        TransporterFormVM.trUrl = t.trUrl;

    }
    public TransporterCrudPageViewModel(INavigationService navigationService)
        : base(navigationService)
    {
        Title = "TransporterCrud Page";
        //this.navigationService = navigationService;

        this.InitializeTransporterForm(Parameter);

    }

运输器表单视图模型(用于初始化用户控件)
    public class TransporterFormViewModel :ViewModelBase
{


    public string Title { get; set; }

    public Transporter Transporter { get; set; }

    public TransporterFormViewModel(INavigationService navigationService,Transporter trans)
        : base(navigationService)
    {
        Transporter = trans;
    }



    private string _trName;
    public string trName 
    {
        get
        {
            return _trName;
        }
        set
        {
            _trName = value;
            NotifyOfPropertyChange(() => trName);
        }
    }


    public string trCode { get; set; }
    public string trUrl { get; set; }

    public int trId { get; set; }
1个回答

0
在构造函数TransporterCrudViewModel类中,您有以下内容:

this.InitializeTransporterForm(Parameter);

其中Parameter是类型为Transporter的属性,未初始化,您将使用null参数调用方法InitializeTransporterForm。然后,您将使用参数Transporter t的空值调用SetUpForm方法。我认为您应以某种方式对此属性进行初始化。

假设您在TransporterListViewModel类中继续执行以下操作:

transporterCrudPageViewModel.InitializeTransporterForm(args.Parameter as Transporter);

在方法InitializeTransporterForm中,您没有将传递的参数设置为属性Parameter的值,类似于这样:
public async void InitializeTransporterForm(Transporter enumerable)
{
     TransporterFormVM = new TransporterFormViewModel(navigationService, enumerable);
     this.Parameter = enumerable; //setting the Parameter property..
     await SetUpForm(enumerable);
}

除了这些注释,你应该在代码行中使用IDE设置断点

transporterCrudPageViewModel.InitializeTransporterForm(args.Parameter as Transporter);

请确保NavigationEventArgs对象的Parameter属性不为null。


@ArghArgh,这个实现中有一些我不理解的事情,我认为它们与null参数有关,这是我的观点。请查看TransporterListViewModel类的SelectedItem属性值。该值作为args对象的参数传递给您的事件处理程序。 - Alberto Solano
我插入了几行代码,展示Transporter对象的一些属性。 Transporter tmp = new Transporter(); tmp = args.Parameter as Transporter; if (tmp != null) Debug.WriteLine(tmp.trName); 输出显示我在值之前看到异常(对象的值是正确的)。输出如下:“A first chance exception of type 'System.NullReferenceException' occurred in CrudSampleMVVM.exe Object reference not set to an instance of an object. marco”。 - ArghArgh
问题在于我尝试在参数初始化之前获取其值。我不知道为什么Setup先被调用了。 - ArghArgh
好的,我尝试简化我的问题。根据Anders Gustaffson的解决方案,我不知道在TrasporterCrudViewModel中如何初始化参数值。 - ArghArgh
我只是想将一个对象从一个viewModel传递到另一个viewModel,并使用该对象初始化视图(与第二个viewModel相关联的视图)。感谢您的帮助。我希望有人能帮助我找到可行的解决方案。 - ArghArgh
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接