c# - 使用 Observable Collection MVVM 绑定(bind) Pivot 控件(windows phone 8)

标签 c# silverlight mvvm windows-phone-8 inotifypropertychanged

我是 WP8 和 MVVM 的新手。我创建了 wp8 应用程序,该应用程序在用户登录后请求各种数据。我只是无法动态创建我的枢轴 header ,我不知道是不是因为我在绑定(bind)中做了一些事情, INotifyPropertyChanged,两者兼而有之!

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

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

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

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

<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 始终为 null,无论我认为不应该是这种情况,但我不能看看我做错了什么。

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

谢谢。

最佳答案

问题已解决!!!

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

我猜是陡峭而痛苦的学习曲线!无论如何,我在找到一篇关于 stackoverflow 的文章后找到了解决方案,该文章基本上向我表明我编写 xaml 的方式是不合适的。

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

这是帖子:Databound pivot is not loading the first PivotItem in Windows Phone 8

关于c# - 使用 Observable Collection MVVM 绑定(bind) Pivot 控件(windows phone 8),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15651419/

相关文章:

android - 如何在非 FragmentActivity 上使用 ViewModelProviders.of() 获取 ViewModel?

c# - Encoding.UTF8.GetString 和 Encoding.UTF8.GetBytes 不是彼此相反的原因是什么?

c# - 如何从我的程序启动一个进程并让它由 visual studio 控制?

c# - C# 中的 FILETIME 舍入以适应 FAT 舍入

c# - 过滤 ICollectionView<object> 时性能下降

c# - 如何在 WPF 中创建一个带有绑定(bind)的验证文本框,在无效输入后切换回最后一个有效值?

c# - LibGit2Sharp 日志远程

C# Silverlight - 具有双向绑定(bind)的组合框?

Silverlight ClientHttp WebRequest 超时

silverlight - MVVM触发事件返回查看