2016-11-23 9 views
1

私は基本的にthis personと同じ質問をしますが、新しいx:Bindのコンテキストで質問しています。私は、テンプレート内で動作しないことがとてもx:DataTemplate内のイベントにViewModelメソッドをバインドします

ItemsSource="{x:Bind ViewModel.pageList, Mode=OneWay}" 

ようのViewModelに私は明示的にそれを行うに何かをバインドする必要があるとき

のviewmodels' DataContextのは、だから、そう

<Page.DataContext> 
    <vm:ChapterPageViewModel x:Name="ViewModel" /> 
</Page.DataContext> 

のように定義されて

<FlipView ItemsSource="{x:Bind ViewModel.pageList, Mode=OneWay}"> 
    <FlipView.ItemTemplate> 
     <DataTemplate x:DataType="models:Image"> 
      <ScrollViewer SizeChanged="{x:Bind ViewModel.PageResized}"> <-- this here is the culprit 
       <Image Source="{x:Bind url}"/> 
      </ScrollViewer> 
     </DataTemplate> 
    </FlipView.ItemTemplate> 
</FlipView> 

ドキュメントを読むと、Pathは、基本的にページにコンテキストをリセットする必要がありますが、これは(x:Bind Path=ViewModel.PageResizeEventも動作しませんでした。私はまだObject reference not set to an instance of an objectを取得していますが、それはメソッド(しかしヌル)が表示されないことを意味するはずです。

Imageクラス:

public class Image { 
    public int page { get; set; } 
    public string url { get; set; } 
    public int width { get; set; } 
    public int heigth { get; set; } 
} 

そしてChapterPageViewModel

private List<Image> _pageList; 
public List<Image> pageList { 
    get { return _pageList; } 
    set { Set(ref _pageList, value); } 
} 

public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, 
    IDictionary<string, object> suspensionState) 
{ 
    Initialize(); 

    await Task.CompletedTask; 
} 

private async void Initialize() 
{ 
    pageList = await ComicChapterGet.GetAsync(_chapterId); 
} 

public void PageResized(object sender, SizeChangedEventArgs e) 
{ 
    //resizing logic happens here 
} 
+0

これらのモデルは:画像クラスはViewModelプロパティを持っていますか?そうでない場合、 'FlipView.ItemsSource'にバインドした同じViewModelを参照しようとしている場合、DataTemplateのDataContextがモデルになっているので、そのようにアクセスすることはできません:Imageオブジェクト。 –

+0

です。私が 'SizeChanged =" {x:Bind ViewModel.PageResized} "を取り除くと、コードが動作します。しかし、ScrollViewのサイズでイメージのサイズを調整できる必要があります。これは、テンプレート内からViewModelプロパティにアクセスする必要があります。 – rancor1223

+0

Imageクラスのコードを追加してもよろしいですか? –

答えて

2

に我々はここで二つの問題があります。直接イベントハンドラデリゲートにイベントをバインドしようとしている

まず、

単純に、動作しません。
MVVMパターンでイベントを処理する方法の1つは、EventTrigger and ICommand.
です。これには、ICommandを実装するクラスが必要です。 This postあなたがそれを行う方法がわからない場合に役立ちます。私はDelegateCommandと呼ぶでしょう。ここで

は、私は2つのステップでそれをリファクタリングする方法をです:

1)VMにコマンドを追加します。

public class ChapterPageViewModel 
{ 
    public ChapterPageViewModel() 
    { 
     this.PageResizedCommand = new DelegateCommand(OnPageResized); 
    } 

    public DelegateCommand PageResizedCommand { get; } 

    private void OnPageResized() 
    { } 
} 

2)EventTriggerとInvokeCommandActionとSizeChangedイベントにコマンドをバインド。

<Page (...) 
    xmlns:i="using:Microsoft.Xaml.Interactivity" 
    xmlns:core="using:Microsoft.Xaml.Interactions.Core"> 
    (...) 
    <FlipView ItemsSource="{x:Bind ViewModel.pageList, Mode=OneWay}" > 
     <FlipView.ItemTemplate> 
      <DataTemplate x:DataType="models:Image"> 
       <ScrollViewer> 
        <i:Interaction.Behaviors> 
         <core:EventTriggerBehavior EventName="SizeChanged"> 
          <core:InvokeCommandAction 
           Command="{x:Bind ViewModel.PageResizedCommand }" /> 
         </core:EventTriggerBehavior> 
        </i:Interaction.Behaviors> 

        <Image Source="{x:Bind url}"/> 
       </ScrollViewer> 
      </DataTemplate> 
     </FlipView.ItemTemplate> 
    </FlipView> 
</Page> 

"しかし、ガブリエル"、あなたが言う、"動作しませんでした!"

私は知っています!そして、それは理由がXにしようとしている第二の問題、のだ: - 私はそこからいくつかの情報を借りるように、この1が密接に、this questionに関連しているのDataTemplateクラス

に属していないプロパティをバインドします。DataTemplateを(項目テンプレート、コンテンツ テンプレート、またはヘッダテンプレートとして使用するかどうか)の内部DataTemplate and x:Bind

について、パスの値は、の文脈で 解釈されないMSDNから

、ページが、データオブジェクト がテンプレート化されているという状況では、コンパイル時にそのバインディングが検証され(効率的に コードが生成されるように)、DataTemplateはx:DataTypeを使用してデータオブジェクトの型を 宣言する必要があります。

あなたが<ScrollViewer SizeChanged="{x:Bind ViewModel.PageResized}">を行うときに、あなたは実際のDataTemplateのx:DataTypeであるmodels:Imageクラス、上のViewModelというプロパティを探しています。そしてそのようなプロパティはそのクラスには存在しません。

ここには2つのオプションがあります。

ViewModelをImageクラスのプロパティとして追加し、VMに入力します。これだけでは

public class Image { 
    (...) 
    public ChapterPageViewModel ViewModel { get; set; } 
} 

public class ChapterPageViewModel 
{ 
    (...) 
    private async void Initialize() { 
     pageList = await ComicChapterGet.GetAsync(_chapterId); 
     foreach(Image img in pageList) 
      img.ViewModel = this; 
    } 
} 

、その前のコードは、他の何かを変更する必要はありませんで動作するはずです。

これを削除します。x:バインドして、ElementNameを使用してgood'bindingに戻ってください。

<FlipView ItemsSource="{x:Bind ViewModel.pageList, Mode=OneWay}" x:Name="flipView"> 
    <FlipView.ItemTemplate> 
     <DataTemplate x:DataType="models:Image"> 
      <ScrollViewer> 
       <i:Interaction.Behaviors> 
        <core:EventTriggerBehavior EventName="SizeChanged"> 
         <core:InvokeCommandAction 
          Command="{Binding DataContext.PageResizedCommand 
          , ElementName=flipView}" /> 
        </core:EventTriggerBehavior> 
       </i:Interaction.Behaviors> 

       <Image Source="{x:Bind url}"/> 
      </ScrollViewer> 
     </DataTemplate> 
    </FlipView.ItemTemplate> 
</FlipView> 

敗北のこの一種あなたの質問の目的に、それは仕事をし、それは、前の1をやってのけるする方が簡単です。

+0

それはトリックでした。そして、イベントの議論を得るための他の問題を導入しました。しかし、私は、私がちょうど(そしてはるかに簡単に)FlipViewディメンションを読むことができるときに、テンプレートの子供のディメンションを読んで私の人生をもっと難しくしていたことに気がつきました。そして、そのコマンドの例は将来も必ず役に立つでしょう。ありがとう! – rancor1223

+0

@ rancor1223さて、そのイベント引数はMVVMの古い問題です。だから、[これをここに残しておきます](http:// stackoverflow。com/questions/6205472/mvvm-passing-eventargs-as-command-parameter) –

関連する問題