【发布时间】:2013-03-17 02:17:25
【问题描述】:
我是 WP8 和 MVVM 的新手。我创建了 wp8 应用程序,它会在用户登录后请求各种数据。我只是无法让我的数据透视表头动态创建,我不知道是不是因为我在绑定中做某事, INotifyPropertyChanged,两者或其他!
这是我到目前为止所做的:
我在 App.cs 中定义了一个全局 MainViewModel,它将存储登录时返回的所有数据。
一旦登录成功并且数据已加载到 MainViewModel 中,我会将其重定向到包含 Pivot Control 的测试页面,并且我正在尝试动态创建 Pivot Items。
这是我的测试页面的 xaml,即 MainPivotPage.xaml,我的 MainPivotViewModel 已初始化,因为它被定义为本地资源并设置为 Pivot 控件的数据上下文,我不知道我是否正在这样做对,但我将“名称”属性分配给 PivotItem 的 Header,这是存储在我的可观察集合 Pivots 中的对象。属性 Name 是我在名为 Pivot 的类中拥有的 2 个属性之一,该类包含 PivotId 和 Name。
<phone:PhoneApplicationPage
x:Class="TestApp.Views.MainPivotPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="clr-namespace:TestApp.ViewModels"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True" Loaded="PhoneApplicationPage_Loaded">
<!--LayoutRoot is the root grid where all page content is placed-->
<phone:PhoneApplicationPage.Resources>
<viewModel:MainPivotViewModel x:Key="MainPivotViewModel" />
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
<!--Pivot Control-->
<phone:Pivot Title="My Search Options" x:Name="MainPivots" ItemsSource="{Binding Pivots}" DataContext="{StaticResource MainPivotViewModel}">
<phone:PivotItem Header="{Binding Name}">
<!--<Grid/>-->
</phone:PivotItem>
</phone:Pivot>
</Grid>
</phone:PhoneApplicationPage>
创建 MainPivotViewModel 时,我将 Pivots 可观察集合设置为存储在我的 MainViewModel 中的相同可观察集合,其中包含登录时返回的所有数据。如您所见,我将其分配给属性而不是内部变量,以确保它将触发 INotifyPropertyChanged(嗯...,我认为)
public class MainPivotViewModel : BaseViewModel
{
private ObservableCollection<Pivot> _pivots = null;
public MainPivotViewModel()
{
Pivots = App.MainViewModel.Pivots;
}
public ObservableCollection<Pivot> 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<T>(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); }
}
}
您可能会注意到这是从 BaseModel 继承的。这与 BaseViewModel 中的代码完全相同,但我想将两者分开。我不确定我的 Pivot 课程是否需要这样做,但我正在尝试不同的场景并暂时保留它。
我不知道我做错了什么,但无论我尝试什么,我都无法将“名称”属性显示为标题的文本。我很确定 MainPivotViewModel 在被分配为本地资源时已被初始化,因为它正确地调用了我的构造函数,然后它正在初始化我的可观察集合,但仅此而已。
但它完全没有显示!
我注意到的另一件事是,当我在 BaseViewModel 类的 OnPropertyChanged 方法中的“Set”中放置断点时,eventHandler 始终为空,无论我认为不应该是什么情况,但我不能看看我做错了什么。
我有很多关于 stackoverflow 和其他文章的文章,但我只是看不出我做错了什么?有人有什么想法吗?
谢谢。
【问题讨论】:
-
您是否将页面的
DataContext设置在任何地方? -
嗨,是的,它是在上面的 xaml 中设置的。它只是不可见,但如果您滚动,您会看到它已设置。
-
你有一个
Pivots 的 ObservableCollection。这些是你自己的课吗?如果有,它们长什么样? -
嗨,马特,我刚刚在原始帖子中添加了课程。
-
当您使用 ObservableCollection 时,如果 (_pivots != value) this.SetProperty(ref this._pivots, value) 更改了集合和所有内容,则需要更改集合的内容而不是集合本身与上一个集合的绑定丢失。
标签: c# silverlight mvvm windows-phone-8 inotifypropertychanged