MVVM视图切换-InitializeComponent之后未填充新视图数据上下文

问题描述 投票:0回答:1

我正在开发我的第一个WPF应用程序,并试图坚持使用MVVM方法。我正在使用MVVM Light。它是一个简单的应用程序,它仅显示一个称为“合并”的列表,并允许用户选择一个列表并进行编辑。

我有MainView就是这样:

<Window x:Class="FileMerger.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:FileMerger"
        xmlns:Views="clr-namespace:FileMerger.Views"
        xmlns:ViewModels="clr-namespace:FileMerger.ViewModels"
        mc:Ignorable="d"
        Title="File Merge" Height="450" Width="800">
    <Window.DataContext>
        <ViewModels:MainViewModel></ViewModels:MainViewModel>
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate DataType="{x:Type ViewModels:MergeListViewModel}">
            <Views:MergeList/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type ViewModels:EditMergeViewModel}">
            <Views:EditMergeView/>
        </DataTemplate>
    </Window.Resources>

    <ContentControl Content="{Binding CurrentPageViewModel}"></ContentControl>
</Window> 

和MainViewModel如下:

public class MainViewModel:ViewModelBase
    {
            private ViewModelBase _currentPageViewModel;
            private MergeListViewModel _mergeListViewModel=new MergeListViewModel();
            private EditMergeViewModel _editMergeViewModel = new EditMergeViewModel();

        public MainViewModel()
            {
                // Set starting page
                _mergeListViewModel.MergeSelected += navToMergeEdit;
                CurrentPageViewModel = _mergeListViewModel;
            }

            public ViewModelBase CurrentPageViewModel
            {
                get
                {
                    return _currentPageViewModel;
                }
                set
                {
                    if (_currentPageViewModel != value)
                    {
                        _currentPageViewModel = value;
                        RaisePropertyChanged(nameof(CurrentPageViewModel));
                    }
                }
            }

       public void navToMergeEdit(int mergeId)
        {
            _editMergeViewModel.MergeId = mergeId;
            CurrentPageViewModel = _editMergeViewModel;
        }
     }

我的第一个视图MergeListView在ViewModel(MergeListViewModel)中具有此事件

public event Action<int> MergeSelected = delegate { };

想法是,当选择“合并”时,将EditMergeView与ViewModel EditMergeViewModel一起加载,并传递mergeId作为参数。应该运行EditMergeViewModel中的LoadedCommand,它会获取数据以使用Merge填充ViewModel。

EditMergeView中的EventTrigger应该执行此操作:

<i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <command:EventToCommand Command="{Binding LoadedCommand}" PassEventArgsToCommand="True" />
        </i:EventTrigger>
</i:Interaction.Triggers>

虽然发现断点显示MainViewModel中的NavToMergeEdit是通过事件调用的,但我发现没有调用LoadedCommand。我在EditMergeView的构造函数中插入了一个断点,发现在调用InitializeComponent()之前,this.DataContext为null,而在InitializeComponent()之后则填充了它。我相信Loaded事件是在InitializeComponent()中触发的,但是此时未设置datacontext,这导致了问题。

这在VS的“输出”窗口中受到以下支持,这向我提示EditMergeView没有在正确的位置绑定到ViewModel

System.Windows.Data Error: 40 : BindingExpression path error: 'LoadedCommand' property not found on 'object' ''EditMergeViewModel' (HashCode=31475357)'. BindingExpression:Path=LoadedCommand; DataItem='EditMergeViewModel' (HashCode=31475357); target element is 'EventToCommand' (HashCode=41172271); target property is 'Command' (type 'ICommand')
Exception thrown: 'System.NullReferenceException' in FileMerger.exe
Exception thrown: 'System.Reflection.TargetInvocationException' in mscorlib.dll
System.Windows.Data Error: 17 : Cannot get 'MergeName' value (type 'String') from '' (type 'EditMergeViewModel'). BindingExpression:Path=MergeName; DataItem='EditMergeViewModel' (HashCode=31475357); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') TargetInvocationException:'System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at FileMerger.ViewModels.EditMergeViewModel.get_MergeName() in C:\Users\JonathanS\source\repos\FileMerger\FileMerger\ViewModels\EditMergeViewModel.cs:line 270
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
   at MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level)
   at MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)'
System.Windows.Data Error: 40 : BindingExpression path error: 'EditMergeCommand' property not found on 'object' ''EditMergeViewModel' (HashCode=31475357)'. BindingExpression:Path=EditMergeCommand; DataItem='EditMergeViewModel' (HashCode=31475357); target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')

我在做什么错?我是否需要调用它并在View构造函数中创建ViewModel并在那里设置DataContext? 。也许不太优雅,但可以避免这种情况。

c# .net wpf mvvm mvvm-light
1个回答
0
投票

幸运的是我有一点时间来解决这个问题。在EditMergeViewModel中,我没有在命令的getter和setter中使用属性。例如,我有

© www.soinside.com 2019 - 2024. All rights reserved.