我正在编写一个针对Windows 8.1的Universal应用程序,并且正在重新编写它以使用IoC容器。但是,我找到了令我困惑的东西。
在我使用IoC之前,我会在代码隐藏中创建我的VM实例并绑定到它,如下所示:
MainPage.xaml中
<ListBox ItemsSource="{Binding ItemList}" DisplayMemberPath="Title" />
MainPage.xaml.cs中
private MainPageVM Data = new MainPageVM();
public MainPage()
{
this.InitializeComponent();
this.DataContext = Data;
}
MainPageVM.cs
public ObservableCollection<MenuItem> ItemList { get; set; }
public MainPageVM()
{
ItemList = new ObservableCollection<MenuItem>();
}
这很好用。但是,现在我以非常不同的方式设置应用程序,如下所示:
App.xaml.cs
private IUnityContainer _Container;
public App()
{
_Container = new UnityContainer();
this.InitializeComponent();
}
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
_Container.RegisterType<MainPage>(new ContainerControlledLifetimeManager());
_Container.RegisterType<Frame>(new ContainerControlledLifetimeManager());
_Container.RegisterType<MainPageVM>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(typeof(Frame),
typeof(MainPage)));
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = _Container.Resolve<Frame>();
rootFrame.CacheSize = 1;
}
if (rootFrame.Content == null)
{
var mainPageVM = _Container.Resolve<MainPageVM>();
mainPageVM.Show();
}
Window.Current.Activate();
}
这将创建MainPageVM()
:
MainPageVM.cs
private Frame _Frame;
private Page _View;
public ObservableCollection<MenuItem> ItemList { get; set; }
public MainPageVM(
Frame frame,
Page view)
{
_Frame = frame;
_View = view;
_View.DataContext = this;
ItemList = new ObservableCollection<MenuItem>();
OnPropertyChanged("ItemList");
}
public void Show()
{
_Frame.Content = _View;
Window.Current.Content = _Frame;
}
MainPage.xaml.cs中
public MainPage()
{
this.InitializeComponent();
}
MainPage.xaml未更改。
我的问题是,为什么我必须发信号OnPropertyChanged("ItemList");
来激活第二个版本中的绑定,而不是第一个版本?我在这里做错了吗?
我可以在GitHub上找到我的整个存储库:Learn OneNote。
答案 0 :(得分:1)
在这两行之间切换应该解决这个问题:
_View.DataContext = this;
和
ItemList = new ObservableCollection<MenuItem>();
当前您首先设置DataContext,这会导致所有视图的绑定重新评估,然后才会修改ItemsList
。由于ItemsList
的setter不会调用OnPropertyChanged
,因此视图在更改时不会更新。通过在行之间切换,首先初始化数据上下文,然后再重新评估绑定。
更易读的解决方案是在您的设置器中包含对OnPropertyChanged
的调用(然后您不必切换线路):
private ObservableCollection<MenuItem> itemList
public ObservableCollection<MenuItem> ItemList
{
get { return itemsList; }
set
{
if (itemsList != value)
{
itemsList = value;
OnPropertyChanged("ItemsList");
}
}
}
虽然首先初始化数据上下文并将其设置为避免让控件尝试绑定两次总是一个好习惯。
答案 1 :(得分:1)
那是因为在第一个版本中,ItemList在视图模型构造函数中实例化,它在数据绑定之前在视图的初始化中构造。但是在第二个版本中,首先绑定数据,然后实例化ItemList。