2012-01-04 8 views
0

FINAL NOTE Final solution found in another postがどのようにウィンドウ

にネストされたコントロールのMVVMでWPFのイベントを処理するために、最終的な解決策は、中-事実、他のソリューションが提供する上記のリンク通りでした。何を試しても、 "Element Name"コンポーネントを介したバインディングは機能しませんでした。私は...データグリッドまでの「相対」の階層に基づいて行くためにWPF/MVVM環境では、あまりにも複雑ではない

<Button Name="btnPrintReport" 
    Command="{Binding DataContext.MyPrintCommand, 
      RelativeSource={RelativeSource FindAncestor, 
          AncestorType={x:Type DataGrid}}}" 
    CommandParameter="{Binding}" 
    Height="16" Width="16" HorizontalAlignment="Center" > 
    <Image Source="MyButtonImage.png" IsHitTestVisible="True"/> 
</Button> 

ホープ何かを持っていました。ここにシナリオがあります。

私はウィンドウ(.xaml)と対応するビューモデル(.cs)を持っています。フォームはすべてのデータバインディングで問題なく表示されます。 (注:これは商用の「フレームワーク」では行われません)

ビューウィンドウにあるコントロールの1つは、事前定義されたすべての列、見出し、およびコンテンツが表示されたDataGridのカスタムユーザーコントロールですビューが表示されます。これは、コントロールがメインウィンドウの.xamlファイルに直接定義されていなくても、ユーザーコントロールとしてフォーム上にドロップされたとしても問題ありません(独自の明白な.csコードビハインドがあります)。メインウィンドウのビューモデルを指して「のDataContext」、そして私が探しているものを、データグリッド今

<DataGrid AutoGenerateColumns="False" 
    Name="dataMyStuff" 
    ItemsSource="{Binding Path=MyTablePropertyOnViewModel, 
     NotifyOnSourceUpdated=True, 
     NotifyOnTargetUpdated=True}" ... /> 

を持つユーザーコントロールで

。このデータグリッドでは、最初の列にイメージがある列があります。このイメージをクリックすると、この行に示されているレコード固有のレポートを印刷したいと思います(これは私が使用するPK値を持っています)。では、データの場所であるView Modelイベントハンドラと、レポートへの呼び出しを準備するために必要な他のメソッドがあるため、画像「KeyUp」イベントにどのように伝える必要がありますか。グリッドのビュー部分は、ユーザへの美的表示のためのものであり、したがってこのコントロールに直接「機能性」はない。

- EDIT - 答え

からの進捗ごとに、私はジョシュとレイチェルからのコメントあたりの私のデータグリッドは、しかし、何かがまだかなり右ではないように調整しました[...]ボタンをして見て"Command"インスタンスを使用して、私はこれを、ビューモデル上の "ICommand"インタフェースオブジェクトのインスタンスにアタッチする必要があると解釈しました。だから、私はインスタンスを作成しました。コマンドハンドラは、Add、Edit、Save、Cancel、Exitなどの一般的なものにも使用されているので、コマンドハンドラが動作することはわかっています。わかりやすくするために、私はAlways Executeとして作成したので、コントロールの "CanExecute"部分を処理するメソッドはありません。私はボタンの "コマンド"を、私がまだ何も考えていないほぼすべての反復に設定しましたが、ここでは私が行っていることが更新されています。私のViewModelクラスで

<UserControl> 
    <Data grid columns/template, etc to the button> 
     <DataTemplate> 
     <Button Name="btnPrintReport" 
      Command="{Binding DataContext.MyPrintCommand}" > 
      <Image Source="myPrintImage.png"/> 
     </Button> 
     </DataTemplate> 
    </Data grid columns, etc> 
</UserControl> 

(myICommandButtonHandlerはICommandのから継承)私が見ているものを今

private myICommandButtonHandler myPrintCommand; 
public myICommandButtonHandler MyPrintCommand 
{ 
    get { if (myPrintCommand == null) 
      myPrintCommand = new myICommandButtonHandler(myPrint); 
     return myPrintCommand; 
     } 
} 

private void myPrint() 
{ 
    MessageBox.Show("Doing the print job..."); 
} 

、。すべてのコントロールなどのステップスルー初期化中。メニュー項目をクリックすると、私のウィンドウが表示されます。最初に、View Modelコントローラのインスタンスを作成します。その後、ウィンドウを呼び出し、View Modelコントローラをパラメータとして渡すので、ウィンドウの「DataContext」としてウィンドウレベルですぐに設定されます。その後、メインウィンドウは「InitializeComponents」コールに入り、問題のデータグリッドを含むこの別のクラスを含む、埋め込まれた他のすべてのコントロールを構築し始めます。このコントロールのコンストラクタ(データグリッドを持つ)にはまだデータコンテキストが設定されていませんが、コントロールの残りの部分はまだ初期化されていません。なぜなら、 "バインディング"が明らかに "データグリッドのコマンドボタンへのバインドをしようとすると失敗しているように見えます。しかし、実行時に、実際のデータはグリッドで更新されるため、多くのことが動作していることがわかります。

したがって、データグリッドの "ItemsSource"プロパティはビューモデルの "DataView"プロパティに設定されていますが、 "ボタン"のバインディングには "MyPrintCommand"ハンドラが表示されません。思考はヒットを得るだろう..そしてそのアクションはただメッセージボックスを表示することです(今のところ)。

+0

コマンドに物事のカップルを、現在のDataRowのDataContextの(データオブジェクト)を渡します。 1. DataContextをUserContorlにバインドする方法のコードを示します。 2.あなたのボタン上のバインディングは 'Binding DataContext.MyPrintCommand'のように見えます。おそらく 'Binding MyPrintCommand'または' Binding ElementName = SomeControl、DataContext.MyPrintCommand'のいずれかでなければなりません。 –

答えて

2

通常、私はAttachedCommand Behaviorを使用して、ViewModelコマンドにイベントをバインドすることができます。私はKeyUpイベントが発射されることはありません飽きないだろうので、画像がキーボードフォーカスを持つことができるとは思わないので、たとえば、あなたが

<Image ... 
     local:CommandBehavior.Event="KeyUp" 
     local:CommandBehavior.Command="{Binding DataContext.PrintCommand, ElementName=dataMyStuff}" 
     local:CommandBehavior.CommandParameter="{Binding }"/> 

を使用することができます私は、keyUpイベントとは異なるイベントを使用することをお勧めしますと思います。

もっと良い方法は、ボタンを使用してテンプレートを上書きしてイメージにすることです。これはClick機能を維持し、あなたがCommandCommandParameter性質も

<Button Command="{Binding DataContext.PrintCommand, ElementName=dataMyStuff}" 
     CommandParameter="{Binding }"> 
    <Button.Template> 
     <Image ... /> 
    </Button.Template> 
</Button> 

にアクセスできるようになります、CommandParameter="{Binding }"は単に

+0

私はあなたの答えの文脈で私の質問を更新しましたが、まだまだ...私が提供した余分なものはさらに助けてくれますか? – DRapp

+0

@DRappコマンドバインディングの 'ElementName'に注意してください。各行のデフォルトの 'DataContext'は、' PrintCommand'を持たない行のデータオブジェクトになります。バインディングで 'ElementName'を使用してバインディングにDataGridを探し、' dataMyStuff'という名前のDataGridに行き、 'DataGrid.DataContext.PrintCommand'にバインドするようにしました。同じオブジェクトに 'PrintCommand'と' MyTablePropertyOnViewModel'が含まれていれば動作します – Rachel

+0

しかし、私のデータグリッドはprintコマンド(ICommand)ハンドラを持っていません。 VIEW MODELはそうしています...私はそれが欠けていると思いますが、Element Nameコンポーネントも見直します。 – DRapp

1

データテンプレートを、画像をコンテンツとして持つボタンに変更します。ボタンのcommandおよびcommandparameterプロパティを使用して、印刷メソッドを呼び出します。あなたのviewmodelであなたのprintコマンドを宣言し、バインドすることができます。パラメータは、データグリッド内の選択された行にすることができます。

+0

非常に有望ですが、私はボーダーとすべての実際の "ボタン"の外観を使用することを避けようとしていましたが、それはショットを与えるでしょう。 – DRapp

+1

イメージのみのボタンをテンプレート化します。ボタンのように振る舞いますが、あたかもボタンの中にネストされていないかのようにイメージを表示します。 –

関連する問題