使用Observable Collection MVVM绑定Pivot控件(Windows Phone 8)

我是WP8和MVVM的新手。 我创建了wp8应用程序,一旦用户登录就会请求各种数据。我只是不能让我的pivotots标头动态创建,我不知道是不是因为我在绑定中做了一些事情, INotifyPropertyChanged,两者或其他!

这是我到目前为止所做的:

我在App.cs中定义了一个全局MainViewModel,它将存储在登录时返回的所有数据。

一旦登录成功并且数据已加载到MainViewModel中,我将其重定向到包含数据透视控件的测试页面,并且我正在尝试动态创建数据透视表项。

这是我的测试页面的xaml,即MainPivotPage.xaml和我的MainPivotViewModel被初始化,因为它被定义为本地资源,并被设置为Pivot控件的datacontext,我不知道我是否正确这样做但我将“Name”属性分配给PivotItem的Header,它是存储在我的可观察集合Pivots中的对象。 属性Name是我在名为Pivot的类中包含的2个属性之一,它包含PivotId和Name。

         <!---->     

创建MainPivotViewModel时,我将Pivots observable集合设置为存储在MainViewModel中的相同可观察集合,该集合包含登录时返回的所有数据。 正如您所看到的,我将它分配给属性而不是内部变量,以确保它将触发INotifyPropertyChanged(好吧……,我认为)

 public class MainPivotViewModel : BaseViewModel { private ObservableCollection _pivots = null; public MainPivotViewModel() { Pivots = App.MainViewModel.Pivots; } public ObservableCollection Pivots { get { return _pivots; } set { if (_pivots != value) this.SetProperty(ref this._pivots, value); } } } 

我使用SetProperty函数,它包含在我的基类中,用于生成INotifyPropertyChanged事件,并允许我这样做,而无需在每次需要INotifyPropertyChanged事件时设置属性名称。

这是我的BaseView的代码:

 public class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty(ref T storage, T value, [CallerMemberName] String propertyName = null) { if (object.Equals(storage, value)) return false; storage = value; this.OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { var eventHandler = this.PropertyChanged; if (eventHandler != null) { eventHandler(this, new PropertyChangedEventArgs(propertyName)); } } } 

我的Pivot类看起来像这样:

 public class Pivot: BaseModel { private int _pivotId; private string _name = string.Empty; public Pivot() { } public Pivot(int pivotId, string name) { PivotId = pivodId; Name = name; } public int PivotId { get { return _pivotId; } set { if (_pivotId != value) this.SetProperty(ref this._pivotId, value); } } public string Name { get { return _name; } set { if (_name != value) this.SetProperty(ref this._name, value); } } } 

您可能会注意到这个是从BaseModelinheritance的。 这与BaseViewModel中的代码完全相同,但我想将两者分开。 我不确定在我的Pivot课上需要这个,但是我正在尝试不同的场景并暂时保留它。

我不知道我做错了什么,但无论我尝试什么,我都无法将“Name”属性显示为Header的文本。 我很确定MainPivotViewModel在被指定为本地资源时被初始化,因为我正在正确地调用我的构造函数,然后初始化我的可观察集合,但这就是它。

但它绝对没有显示!

我注意到的另一件事是当我在BaseViewModel类中的OnPropertyChanged方法中的“Set”中放置断点时,eventHandler始终为null,无论我认为应该是什么情况,但是我看不出我是什么做错了。

我有很多关于stackoverflow和其他文章的文章,我只是看不出我做错了什么? 有人有任何想法吗?

谢谢。

问题解决!!!

我的代码一直都是正确的,但XAML不是!

我想是陡峭而痛苦的学习曲线! 无论如何,我在找到一篇关于stackoverflow的文章后找到了一个解决方案,它基本上向我展示了我编写xaml的方式是不恰当的。

我会说实话,我不明白为什么这不会按照定义的方式工作但简而言之,我必须使用HeaderTemplate和ItemTemplate才能在绑定到ViewModel时正确显示数据!

这是post: Databound pivot没有加载Windows Phone 8中的第一个PivotItem

不,你回答错了,你的代码错了。

错误1:

  set { if (_pivots != value) this.SetProperty(ref this._pivots, value); } 

在这里,如果你改变属性或变量绑定将丢失无关紧要。

错误2:从ItemsControl派生的所有UIElements都忽略了INotifyPropertyChanged,因为它不会仅仅更新ItemsSource DataContext。

工作实例

  public ObservableCollection LstLog { get; set; } private ObservableCollection _lstContent = new ObservableCollection(); public ObservableCollection LstContent { get { LstLog.Add("get"); return _lstContent; } set { LstLog.Add("set"); _lstContent = value; } } public MainWindow() { LstLog = new ObservableCollection(); InitializeComponent(); this.DataContext = this; } private void Add_Click(object sender, RoutedEventArgs e) { LstContent.Add("Value added"); } private void New_Click(object sender, RoutedEventArgs e) { _lstContent = new ObservableCollection(); } private void NewBind_Click(object sender, RoutedEventArgs e) { _lstContent = new ObservableCollection(); listObj.ItemsSource = _lstContent; } private void NewProp_Click(object sender, RoutedEventArgs e) { LstContent = new ObservableCollection(); } private void NewPropBind_Click(object sender, RoutedEventArgs e) { LstContent = new ObservableCollection(); listObj.ItemsSource = LstContent; } 

和ui

                             

LstLog只是为了查看事件列表,如果单击add它将更新两个列表,但是如果单击NewNew Prop ,绑定将丢失,直到您更新它,就像在New BindNew Prop Bind

希望这会澄清XAML List事件的反复出现问题。

PS:这是在WPF中,但在WP8和Windowsapp store应用相同。

这一切对我来说都很好,所以我认为App.MainViewModel.Pivots在调用构造函数时为null或为空(因此Pivot控件为空),并且最终在MainViewModel中创建了一个新的Pivots实例在MainPivotViewModel实例化之后。

您是否尝试在MainPivotViewModel.Pivots的getter中设置一个断点来确认是否有一些项目?