10

OK、LayoutTransform と ScaleTransform を使用して、UI 要素のグリッドをズームする方法を理解しました。私が理解していないのは、View を CTRL+MouseWheelUp\Down に応答させる方法と、コードを MVVM パターンに適合させる方法です。

私の最初のアイデアは、ZoomFactor をプロパティとして保存し、それを調整するコマンドにバインドすることでした。

私は次のようなものを見ていました:

<UserControl.InputBindings>
 <MouseBinding Command="{Binding ZoomGrid}" Gesture="Control+WheelClick"/>
</UserControl.InputBindings>

しかし、2つの問題があります:

1) ホイールが上に移動したか下に移動したかを判断する方法はないと思います。MouseWheelEventArgs.Delta を見たことがありますが、取得方法がわかりません。

2) ビューモデルのコマンドへのバインドは、厳密にはビューのものであるため、正しくないようです。

ズームは厳密には UI View のみなので、実際のコードはコード ビハインドに入れる必要があると考えています。

皆さんはこれをどのように実装しますか?

ps、MVVMにCinchを使用して.net\wpf 4.0を使用しています。

4

6 に答える 6

13

本当の解決策は、独自の MouseGesture を作成することです。これは簡単です。

<MouseBinding Gesture="{x:Static me:MouseWheelGesture.CtrlDown}"  
              Command="me:MainVM.SendBackwardCommand" />

public class MouseWheelGesture : MouseGesture
{
    public static MouseWheelGesture CtrlDown
        => new MouseWheelGesture(ModifierKeys.Control) { Direction = WheelDirection.Down};

    public MouseWheelGesture(): base(MouseAction.WheelClick)
    {
    }

    public MouseWheelGesture(ModifierKeys modifiers) : base(MouseAction.WheelClick, modifiers)
    {
    }

    public WheelDirection Direction { get; set; }

    public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
    {
        if (!base.Matches(targetElement, inputEventArgs)) return false;
        if (!(inputEventArgs is MouseWheelEventArgs args)) return false;
        switch (Direction)
        {
            case WheelDirection.None:
                return args.Delta == 0;
            case WheelDirection.Up:
               return args.Delta > 0;
            case WheelDirection.Down:
                return args.Delta < 0;
            default:
                return false;
        }
    }

    public enum WheelDirection
    {
      None,
      Up,
      Down,
    }
}
于 2011-09-23T10:16:58.053 に答える
2

コード ビハインドを使用したくない場合は、mvvm light の EventToCommand 機能を使用できます。

意見:

 <...
     xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
     ...> 
<i:Interaction.Triggers>
         <i:EventTrigger EventName="PreviewMouseWheel">
             <cmd:EventToCommand Command="{Binding
     Path=DataContext.ZoomCommand,
     ElementName=Root, Mode=OneWay}"
         PassEventArgsToCommand="True"   />
         </i:EventTrigger> </i:Interaction.Triggers>

ビューモデル:

ZoomCommand = new RelayCommand<RoutedEventArgs>(Zoom);
...
public void Zoom(RoutedEventArgs e)
{
    var originalEventArgs = e as MouseWheelEventArgs;
    // originalEventArgs.Delta contains the relevant value
}

これが誰かに役立つことを願っています。私は質問がちょっと古いことを知っています...

于 2011-06-25T20:38:58.323 に答える
0

私は両方の答えに同意します。この場合、コードビハインドを使用することが唯一の方法であると付け加えるだけなので、それがグッドプラクティスに違反するかどうかを考える必要はありません。

事実は、MouseEventArgs(したがってDelta)を取得する唯一の方法はコードビハインドにあるため、そこで必要なものを取得し(そのためのロジックは必要ありません)、olliが提案したようにビューモデルに渡します。

反対に、ビューまたはOSに関連する規則を無視するために、より一般的なデルタを使用することもできます(たとえば、ビューモデルにステップとして渡す前に120で除算します)。これにより、ビューモデルでコードを最大限に再利用できます。

于 2010-03-19T13:43:06.853 に答える
0

あなたがやろうとしていることはビューに非常に関連していると思うので、コードを後ろに置いても害はありません(少なくとも私の意見では)が、これを処理するエレガントな方法があると確信していますより多くのビューモデルベース。

OnPrevewMouseWheelイベントに登録し、ユーザーがCtrlキーを押したかどうかを確認し、それに応じてズーム率を変更して、探しているズーム効果を得ることができるはずです。

于 2010-02-16T08:40:37.323 に答える
0

問題全体を回避するには、もう 1 つのオプションがあります。-xaml で ContentPresenter を使用し、そのコンテンツをビューモデル オブジェクトにバインドします。-ビューモデル内でマウスホイール イベントを処理します。

于 2013-12-19T13:35:15.043 に答える