WP8とMVVMは初めてです。ユーザーがログインすると、さまざまなデータを要求するwp8アプリを作成しました。ピボットヘッダーを動的に作成することができず、バインディングで何かを行っているためかどうかわかりません。 INotifyPropertyChanged、両方または他の何か!!
これが私がこれまでにしたことです:
App.csで定義されたグローバルMainViewModelがあり、ログイン時に返されたすべてのデータが保存されます。
ログインが成功し、データがMainViewModelにロードされたら、これをピボットコントロールを含むテストページにリダイレクトし、ピボットアイテムを動的に作成しようとしています。
これは私のテストページのxaml、つまりMainPivotPage.xamlであり、MainPivotViewModelはローカルリソースとして定義され、ピボットコントロールのデータコンテキストとして設定されているため初期化されます。これを正しく行っているかどうかはわかりませんが、監視可能なコレクションPivotsに格納されているオブジェクトであるPivotItemのヘッダーに「Name」プロパティを割り当てています。プロパティNameは、PivotIdとNameを含むPivotというクラスにある2つのプロパティの1つです。
<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);
}
}
}
基本クラスに含まれ、INotifyPropertyChangedイベントを生成するために使用されるSetProperty関数を使用します。これにより、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));
}
}
}
私のピボットクラスは次のようになります。
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とまったく同じコードですが、2つを別々に保ちたいと思いました。これが私のピボットクラスで必要かどうかはわかりませんが、別のシナリオを試していて、今のところそのままにしておきました。
何が間違っているのかわかりませんが、何を試しても、「Name」プロパティをヘッダーのテキストとして表示することはできません。MainPivotViewModelは、ローカルリソースとして割り当てられたときに初期化されると確信しています。これは、コンストラクターを正しく呼び出して、監視可能なコレクションを初期化するためですが、それだけです。
しかし、それはまったく何も表示しません!
私が気付いたもう1つのことは、BaseViewModelクラスのOnPropertyChangedメソッドの「Set」にブレークポイントを設定すると、どのような場合でも、eventHandlerは常にnullになりますが、何が起こっているのかわかりません。私は間違っています。
私はstackoverflowやその他に関する記事をたくさん持っていますが、何が間違っているのかわかりませんか?誰かアイデアがありますか?
ありがとう。