5

MVVM パターンを初めて使用しようとしています。だから私はItemsControlビューモデルオブジェクトでいっぱいになり、DataTemplate's;を使って表示されました。オブジェクトはとオブジェクトで表されるDataTemplate「ノード」と「エッジ」であり、ノードとエッジを移動するためにクリックとドラッグを検出できるようにしたいと考えています。ThumbPolylineItemsControl

2 つの質問:

  • Polylineマウス イベント ハンドラをとにアタッチThumbして、小さなビューモデルで処理するにはどうすればよいですか? Thumb.DragDelta(ハンドラーをItemsControlおよびにアタッチすることはできe.OriginalSourceますThumbが、対応するビューモデル オブジェクトを取得するにはどうすればよいでしょうか?)
  • ItemsControlにマウス イベント ハンドラーをアタッチして、空白スペースでのマウスのクリックとドラッグを検出するにはどうすればよいですか? (答えは下にあります)

注: View のイベントを直接処理している場合、適切な ViewModel と見なされない可能性があることはわかっています。しかし、重要な点は、マウス イベントを処理する必要があり、それらをアタッチする方法がわからないということです。

4

6 に答える 6

6

DataTemplate 内のオブジェクトによって発生したイベントを処理する方法を見つけました。

(1) イベント ハンドラーを ItemsControl にアタッチします。

<ItemsControl x:Name="_itemsControl" 
              Thumb.DragStarted="Node_DragStarted"
              Thumb.DragDelta="Node_DragDelta"
              Thumb.DragCompleted="Node_DragCompleted"
              MouseDoubleClick="OnMouseDoubleClick"
              .../>

(2) イベントが適用される項目を見つけるには、OriginalSource を FrameworkElement として扱い、その DataContext を取得します。

void Node_DragStarted(object sender, DragStartedEventArgs e)
{
    var os = (FrameworkElement)e.OriginalSource;
    var vm = os.DataContext as ItemViewModel;
    if (vm != null)
        // do something with the item ViewModel
}
于 2009-05-15T21:55:39.260 に答える
3

ViewModelはGUIから切断する必要があるため、コントロールやマウスクリックについては何も認識しません。

2つのオプション:

  • Thomasの提案に従って、ViewModelでコマンドを呼び出します
  • サムの位置をViewModelのプロパティにバインドすると、コントロールがWPF内を移動すると、ViewModelの位置の値が更新されます。
于 2009-05-16T02:04:18.943 に答える
2

2番目の質問の答えがわかりました。スクロールをサポートする ItemsControl が必要で、デフォルトの StackPanel ではなく Grid に項目を配置する必要がありました。両方の要件を満たすために、ControlTemplate を使用しました。

<!--In the resources...-->
<ControlTemplate x:Key="GraphTemplate" TargetType="ItemsControl">
    <ScrollViewer Name="ScrollViewer"
                  Padding="{TemplateBinding Padding}"
                  HorizontalScrollBarVisibility="Auto">
        ...
            <Grid Name="Panel" IsItemsHost="True"
                  Background="{TemplateBinding ItemsControl.Background}"/>
        ...
    </ScrollViewer>
</ControlTemplate>
<!--Later...-->
<ItemsControl x:Name="_itemsControl" 
              ItemsSource="{Binding Items}"
              Template="{StaticResource GraphTemplate}"
              Background="LightYellow"/>

意味のあるマウス座標 (つまり、スクロール可能な空間の座標) を持つマウス イベントを取得するには、奇妙な呪文を使ってグリッドへの参照を取得する必要がありました。

Grid grid = (Grid)_itemsControl.Template.FindName("Panel", _itemsControl);

次に、イベント ハンドラーをグリッドにアタッチし、マウス イベント ハンドラー内で、次を使用してグリッドに関するマウス座標を取得します。

Point p = e.GetPosition((IInputElement)sender);

サーフェス全体でマウス イベントを取得するには、コントロール (実際にはグリッド) に背景が必要なので、上で Background="LightYellow" を設定します。これは、ControlTemplate のバインディングを介してグリッドに伝達されます。

于 2009-05-15T19:51:32.023 に答える
1

Bea Stollnitzには、「データバインドされたItemsControls間でアイテムをドラッグアンドドロップするにはどうすればよいですか?」というタイトルのドラッグアンドドロップの例があります。リンクを投稿しますが、StackOverflowでは許可されません。

ドラッグの処理中にUIフィードバックを分割し、最終的にドロップされたときに実行されるアクションを分割することをお勧めします。

ただし、上記のトーマスとキャメロンには同意します。イベント処理とデータバインディングの混合/マッチングを制限する必要があります。イベント処理ルートを使用する場合は、オブジェクトに「モデルの表示」という用語を使用することを避けたくない場合があります。これは、一般にデータバインディングの代替手段を意味するためです。

于 2009-05-20T16:43:58.530 に答える
1

コードビハインドなしでそれを行う方法があります...

添付の動作パターンを使用して、イベントをコマンドにマップできます。Marlon Grech の実装はこちらを参照してください。

次のように、InputBindings を ViewModel コマンドにバインドするために私が作成したマークアップ拡張機能を使用することもできます。

<UserControl.InputBindings>
    <MouseBinding Gesture="LeftClick" Command="{input:CommandBinding SomeCommand}"/>
</UserControl.InputBindings>

ただし、それがあなたの特定のニーズに合っているかどうかはわかりません...

于 2009-05-15T23:04:41.713 に答える
0

私ははるかにエレガントな方法を使用しています。Prism 2 とデータ テンプレートを使用します。だから私がやったことはこれです:

<ItemsControl x:Name="SearchImagesList" ItemTemplate="{StaticResource SearchResultsAlbum}"   

ItemTemplate で、ボタンを作成しました。

<DataTemplate x:Key="SearchResultsAlbum">                        
    <Button CommandParameter="{Binding}"                 
            Command="{Binding Source={x:Static PhotoBookPRMainModule:ServiceProvider.DesignEditorViewManager}, Path=NavigationCommands.NavigateSearchResultAction}">
于 2010-11-02T16:11:48.190 に答える