我是MVVM的新手,并通过遵循教程和使代码适应一个简单项目的方法来弄清楚它是如何工作的。但是我遇到了一个问题,即使它正在切换CurrentViewModel,MainWindow
也会而不是加载其他 View 。
Visual Studio在 MainWindow.xaml 代码的XAML中突出显示以下错误:
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
Value cannot be null. Parameter name: path
出于这个问题的目的,我专门询问此错误的原因以及它对该项目有什么影响。
这是当前项目的代码:
模型:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Address_Manager.Model
{
public class StoreAddressModel { }
public class StoreAddress : INotifyPropertyChanged
{
private string _storeCode;
private string _storeName;
private string _address1;
private string _address2;
private string _city;
private string _state;
private string _postCode;
private string _phone;
private string _email;
private string _country;
private string _manager;
private string _areaManager;
private List<string> _openingHours;
public string StoreCode
{
get { return _storeCode; }
set
{
if (_storeCode != value) { _storeCode = value; RaisePropertyChanged("StoreCode"); }
}
}
public string StoreName
{
get { return _storeName; }
set
{
if (_storeName != value) { _storeName = value; RaisePropertyChanged("StoreName"); }
}
}
public string Address1
{
get { return _address1; }
set
{
if (_address1 != value) { _address1 = value; RaisePropertyChanged("Address1"); }
}
}
public string Address2
{
get { return _address2; }
set
{
if (_address2 != value) { _address2 = value; RaisePropertyChanged("Address2"); }
}
}
public string City
{
get { return _city; }
set
{
if (_city != value) { _city = value; RaisePropertyChanged("City"); }
}
}
public string State
{
get { return _state; }
set
{
if (_state != value) { _state = value; RaisePropertyChanged("State"); }
}
}
public string PostCode
{
get { return _postCode; }
set
{
if (_postCode != value) { _postCode = value; RaisePropertyChanged("PostCode"); }
}
}
public string Phone
{
get { return _phone; }
set
{
if (_phone != value) { _phone = value; RaisePropertyChanged("Phone"); }
}
}
public string Email
{
get { return _email; }
set
{
if (_email != value) { _email = value; RaisePropertyChanged("Email"); }
}
}
public string Country
{
get { return _country; }
set
{
if (_country != value) { _country = value; RaisePropertyChanged("Country"); }
}
}
public string Manager
{
get { return _manager; }
set
{
if (_manager != value) { _manager = value; RaisePropertyChanged("Manager"); }
}
}
public string AreaManager
{
get { return _areaManager; }
set
{
if (_areaManager != value) { _areaManager = value; RaisePropertyChanged("AreaManager"); }
}
}
public List<string> OpeningHours
{
get { return _openingHours; }
set
{
if (_openingHours != value) { _openingHours = value; RaisePropertyChanged("OpeningHours"); }
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Address_Manager.ViewModel;
namespace Address_Manager
{
class MainWindowViewModel : BindableBase
{
public MainWindowViewModel()
{
NavCommand = new MyICommand<string>(OnNav);
}
private StoreAddressViewModel storeAddressViewModel = new StoreAddressViewModel();
private OfficeAddressViewModel officeAddressViewModel = new OfficeAddressViewModel();
private BindableBase _CurrentViewModel;
public BindableBase CurrentViewModel
{
get { return _CurrentViewModel; }
set { SetProperty(ref _CurrentViewModel, value); }
}
public MyICommand<string> NavCommand { get; private set; }
private void OnNav(string destination)
{
switch (destination)
{
case "office":
CurrentViewModel = officeAddressViewModel;
break;
case "stores":
CurrentViewModel = storeAddressViewModel;
break;
case "exit":
Application.Current.Shutdown();
break;
default:
CurrentViewModel = storeAddressViewModel;
break;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Address_Manager.ViewModel
{
class OfficeAddressViewModel : BindableBase
{
}
}
using Address_Manager.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Address_Manager.ViewModel
{
class StoreAddressViewModel : BindableBase
{
public StoreAddressViewModel()
{
LoadStores();
}
public ObservableCollection<StoreAddress> StoreDetails { get; set; }
public ObservableCollection<string> Stores { get; set; }
public void LoadStores()
{
ObservableCollection<StoreAddress> _StoreDetails = new ObservableCollection<StoreAddress>();
ObservableCollection<string> _Stores = new ObservableCollection<string>();
string addressRepository = "";
addressRepository = ConfigurationManager.AppSettings["ReferenceFilePath"];
List<string> rawStoreData = new List<string>();
rawStoreData = File.ReadAllLines(addressRepository).ToList();
foreach (string line in rawStoreData)
{
string[] segments = line.Split(',');
StoreAddress store = new StoreAddress
{
StoreCode = segments[0],
StoreName = segments[1],
Address1 = segments[2],
Address2 = segments[3],
City = segments[4],
State = segments[5],
PostCode = segments[6],
Country = segments[7],
Phone = segments[8],
Email = segments[9],
Manager = segments[10],
AreaManager = segments[11],
OpeningHours = segments[12].Split('|').ToList()
};
_StoreDetails.Add(store);
_Stores.Add(store.StoreName);
}
if (_Stores != null)
StoreDetails = _StoreDetails;
}
}
}
观看次数:
<UserControl x:Class="Address_Manager.Views.OffcieAddressView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Address_Manager.Views"
mc:Ignorable="d"
d:DesignHeight="440" d:DesignWidth="800">
<Grid>
<TextBlock Text="PlaceHolder"/>
</Grid>
</UserControl>
<UserControl x:Class="Address_Manager.Views.StoreAddressView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Address_Manager.Views"
xmlns:data="clr-namespace:Address_Manager.Model"
mc:Ignorable="d"
d:DesignHeight="440" d:DesignWidth="850">
<Grid Margin="10,10,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Content="Test"/>
</StackPanel>
</Grid>
</UserControl>
<Window x:Class="Address_Manager.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:Address_Manager"
xmlns:views ="clr-namespace:Address_Manager.Views"
xmlns:viewModels ="clr-namespace:Address_Manager.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:StoreAddressViewModel}">
<views:StoreAddressView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:OfficeAddressViewModel}">
<views:OffcieAddressView/>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="NavBar">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Content="Stores"
Command="{Binding NavCommand}"
CommandParameter="stores"
Grid.Column="1"/>
<Button Content="Office"
Command="{Binding NavCommand}"
CommandParameter="office"
Grid.Column="3"/>
<Button Content="Exit"
Command="{Binding NavCommand}"
CommandParameter="exit"
Grid.Column="5"/>
</Grid>
<Grid Grid.Column="1">
<ContentControl Content="{Binding CurrentView}"/>
</Grid>
</Grid>
</Window>
ICommand和BindableBase类:
using System;
using System.Windows.Input;
namespace Address_Manager
{
public class MyICommand<T> : ICommand
{
Action<T> _TargetExecuteMethod;
Func<T, bool> _TargetCanExecuteMethod;
public MyICommand(Action<T> executeMethod)
{
_TargetExecuteMethod = executeMethod;
}
public MyICommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
{
_TargetExecuteMethod = executeMethod;
_TargetCanExecuteMethod = canExecuteMethod;
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged(this, EventArgs.Empty);
}
bool ICommand.CanExecute(object parameter)
{
if (_TargetCanExecuteMethod != null)
{
T tparm = (T)parameter;
return _TargetCanExecuteMethod(tparm);
}
if (_TargetExecuteMethod != null)
{
return true;
}
return false;
}
// Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
// Prism commands solve this in their implementation
public event EventHandler CanExecuteChanged = delegate { };
void ICommand.Execute(object parameter)
{
_TargetExecuteMethod?.Invoke((T)parameter);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Address_Manager
{
class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T member, T val, [CallerMemberName] string propertyName = null)
{
if (Equals(member, val))
return false;
member = val;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
最佳答案
重写您的StoreAddressViewModel:
using Address_Manager.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Address_Manager.ViewModel
{
class StoreAddressViewModel : BindableBase
{
public StoreAddressViewModel()
{
LoadStores();
}
public ObservableCollection<StoreAddress> _StoreDetails = new ObservableCollection<StoreAddress>();
public ObservableCollection<StoreAddress> StoreDetails
{
get
{
return _StoreDetails;
}
set
{
_StoreDetails = value;
OnPropertyChanged();
}
}
public ObservableCollection<string> _Stores = new ObservableCollection<string>();
public ObservableCollection<string> Stores
{
get
{
return _Stores;
}
set
{
_Stores = value;
OnPropertyChanged();
}
}
public void LoadStores()
{
StoreDetails.Clear();
Stores.Clear();
string addressRepository = ConfigurationManager.AppSettings["ReferenceFilePath"];
if(!string.IsNullOrWhiteSpace(addressRepository) && File.Exists(addressRepository))
{
List<string> rawStoreData = new List<string>();
rawStoreData = File.ReadAllLines(addressRepository).ToList();
foreach (string line in rawStoreData)
{
string[] segments = line.Split(',');
StoreAddress store = new StoreAddress
{
StoreCode = segments[0],
StoreName = segments[1],
Address1 = segments[2],
Address2 = segments[3],
City = segments[4],
State = segments[5],
PostCode = segments[6],
Country = segments[7],
Phone = segments[8],
Email = segments[9],
Manager = segments[10],
AreaManager = segments[11],
OpeningHours = segments[12].Split('|').ToList()
};
StoreDetails.Add(store);
Stores.Add(store.StoreName);
}
}
}
}
}
附言:此代码始终返回true,因为_Stores工作表已在尺寸为0的方法中定义
if (_Stores != null)
StoreDetails = _StoreDetails;
关于c# - 路径上的Window.DataContext错误不能为null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59148014/