문제

좋아, 나는 LayoutTransform 및 ScaleTransform을 사용하여 UI 요소의 그리드를 확대하는 방법을 알아 냈습니다. 내가 이해하지 못하는 것은 Ctrl+Mousewheelup 에 응답하기 위해 내 견해를 얻는 방법과 코드를 MVVM 패턴에 맞추는 방법입니다.

저의 첫 번째 아이디어는 Zoomfactor를 속성으로 저장하고 명령에 결합하여 조정하는 것이 었습니다.

나는 다음과 같은 것을보고 있었다.

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

그러나 나는 두 가지 문제를 본다 :

1) 나는 휠이 위 또는 아래로 이동했는지 여부를 알 수있는 방법이 없다고 생각하거나 얼마를 결정하는지 알 수 없다고 생각합니다. 나는 mousewheeleventargs.delta를 보았지만 그것을 얻는 방법을 모른다.

2) 뷰 모델에서 명령에 바인딩하는 것은 엄격하게보기에 옳지 않은 것처럼 보이지 않습니다.

줌은 엄격하게 UI보기 전용이므로 실제 코드가 코드-비만에 들어가야한다고 생각합니다.

당신은 이것을 어떻게 구현하겠습니까?

추신, 나는 mvvm에 cinch를 사용하여 .net wpf 4.0을 사용하고 있습니다.

도움이 되었습니까?

해결책

VM에서 일반 줌 명령을 구현하는 것이 좋습니다. 명령은 새로운 줌 레벨로 매개 변수화 될 수 있거나 (아마도 더 간단하게) 구현할 수 있습니다. 증가 zoomcommand 그리고 감소 ZoomCommand. 그런 다음 마우스 휠 이벤트의 이벤트 인수를 처리 한 후에 View의 코드를 사용하여 이러한 명령을 호출하십시오. 델타가 양수이면 부정적인 확대가 확대되면 축소하십시오.

몇 줄의 코드를 사용 하여이 문제를 해결하는 데 아무런 해가 없습니다. MVVM의 주요 아이디어는 UI에 의존하지 않는 객체 (테스트 가능성 향상)에서 거의 전체 시야 상태를 추적하고 수정할 수 있다는 것입니다. 결과적으로, 줌의 결과 인 새 뷰포트의 계산은 Code 뒤에 있지 않은 VM에서 수행해야합니다.

뒤에있는 코드에 존재하는 작은 테스트 가능성의 간격은 무시되거나 자동 UI 테스트로 덮을 수 있습니다. 그러나 자동 UI 테스트는 매우 비쌀 수 있습니다.

다른 팁

진짜 Anwser는 자신의 마우스 하단을 작성하는 것입니다.

<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,
    }

}

뒤에 코드를 사용하지 않으려면 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>

ViewModel :

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

나는 이것이 누군가를 돕기를 바랍니다. 나는 질문이 일종의 오래된 것임을 압니다 ...

나는 당신이 시도하는 것이 관점과 매우 관련이 있다고 생각하기 때문에 코드에 코드를 넣는 데 아무런 해를 끼치 지 않습니다 (적어도 내 의견으로는). 더 많은 뷰 모델 기반.

onprevewmousewheel 이벤트에 등록 할 수 있고, 사용자가 컨트롤 키를 누르고 있는지 확인하고 줌 요소를 변경하여 원하는 확대 / 축소 효과를 얻으려면 줌 계수를 변경해야합니다.

나는 두 가지 답변에 동의하며,이 경우에 코드를 사용하는 것이 유일한 방법이므로, 좋은 관행을 깨뜨리는 지 여부에 대해 생각할 필요조차 없습니다.

사실, Mouseeventargs (그리고 델타)를 붙잡는 유일한 방법은 코드 뒤에 있으므로, 필요한 것을 잡고 (그 논리가 필요하지 않음) Olli가 제안한대로보기 모델에 전달하십시오.

플립 측면에서는보기 또는 OS와 관련된 컨벤션을 무지하게 유지하기 위해보다 일반적인 델타 (예 : 뷰 모델로의 단계로 전달하기 전에 120으로 나누기)를 사용하고 싶을 수도 있습니다. 이렇게하면보기 모델에서 코드를 최대한 재사용 할 수 있습니다.

전체 문제를 피하기 위해 옵션이 하나 더 있습니다. XAML에서 ContentPresenter를 사용하고 컨텐츠를 뷰 모델 객체에 바인딩하도록합니다. -뷰 모델 내에서 Mousewheel 이벤트를 처리하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top