Frage

Ich habe einige Probleme mit dem EventToCommand nicht verhalten, als ich mit CaptureMouse erwartet.

Ich habe eine ResizeGrip, dass ich mehrere EventToCommand ist definiert haben auf:

<ResizeGrip Name="ResizeGrip" HorizontalAlignment="Right" VerticalAlignment="Bottom" Cursor="SizeNWSE">
<i:Interaction.Triggers>
  <i:EventTrigger EventName="MouseLeftButtonDown">
   <cmd:EventToCommand Command="{Binding ResizeStartCommand}" PassEventArgsToCommand="True" />
  </i:EventTrigger>
  <i:EventTrigger EventName="MouseLeftButtonUp">
   <cmd:EventToCommand Command="{Binding ResizeStopCommand}" PassEventArgsToCommand="True" />
  </i:EventTrigger>
  <i:EventTrigger EventName="MouseMove">
   <cmd:EventToCommand Command="{Binding ResizeCommand}" PassEventArgsToCommand="True" />
  </i:EventTrigger>
 </i:Interaction.Triggers>
 </ResizeGrip>

Die Handhabungsfunktionen im Konstruktor der Klasse festgelegt sind:

ResizeStartCommand = new RelayCommand<MouseButtonEventArgs>(
    (e) => OnRequestResizeStart(e));
ResizeStopCommand = new RelayCommand<MouseButtonEventArgs>(
    (e) => OnRequestResizeStop(e));
ResizeCommand = new RelayCommand<MouseEventArgs>(
    (e) => OnRequestResize(e),
    param => CanResize);

Und schließlich ich alle meine Logik, um die Größe:

void OnRequestResizeStart(MouseButtonEventArgs e)
{
    bool r = Mouse.Capture((UIElement)e.Source);
    Console.WriteLine("mouse down: " + r.ToString());
}
void OnRequestResizeStop(MouseButtonEventArgs e)
{
    ((UIElement)e.Source).ReleaseMouseCapture();
    _canResize = false;
}
void OnRequestResize(MouseEventArgs e)
{
    Console.WriteLine("mouse move");
}
bool CanResize
{ get { return _canResize; } }

Die OnRequestResizeStart & OnRequestResizeStop Befehle arbeiten gut, und die OnRequestResize funktioniert ... aber nur, wenn ich tatsächlich über die ResizeGrip. Es ist nicht ersichtlich, dass die CaptureMouse nicht tatsächlich alle die Mausereignisse an den ResizeGrip senden.

Ist dies eine Einschränkung des EventToCommand, oder tut etwas besonderes Bedürfnis zu kommen?

Vielen Dank für jede Hilfe!

War es hilfreich?

Lösung

Warum verwenden Sie Befehle für diese anstelle von Standard-Event-Handler? Dies ist eindeutig UI-Logik, die in Code-behind gehört, kein Ansichtsmodell.

**** UPDATE **

Im Fall, dass Sie dies in einer Control verwenden können Sie die Control-Code als Code-behind zu behandeln. Um die Verbindungen der Ereignisse tun können Sie das TemplatePart Muster verwenden und auf das speziell benannte Element in OnApplyTemplate verbinden. Zur Erleichterung der Größe Bereitstellung (oder was auch immer Ihre VM Bedürfnisse) können Sie einen DP fügen Sie den entsprechenden Wert zu speichern und zu binden, um eine VM-Eigenschaft auf, dass. Dies ermöglicht auch tun Zweiweg verbindlich, wenn Sie so etwas wie setzte eine Anfangsgröße von der VM tun müssen.

// this doesn't enforce the name but suggests it
[TemplatePart(Name = "PART_Resizer", Type = typeof(ResizeGrip))]
public class MyContainer : ContentControl
{
    private ResizeGrip _grip;

    public static readonly DependencyProperty ContainerDimensionsProperty = DependencyProperty.Register(
        "ContainerDimensions",
        typeof(Size),
        typeof(MyContainer),
        new UIPropertyMetadata(Size.Empty, OnContainerDimensionsChanged));

    private static void OnContainerDimensionsChanged(DependencyObject dObj, DependencyPropertyChangedEventArgs e)
    {
        MyContainer myContainer = dObj as MyContainer;
        if (myContainer != null)
        {
            Size newValue = (Size)e.NewValue;
            if (newValue != Size.Empty)
            {
                myContainer.Width = newValue.Width;
                myContainer.Height = newValue.Height;
            }
        }
    }

    public Size ContainerDimensions
    {
        get { return (Size)GetValue(ContainerDimensionsProperty); }
        set { SetValue(ContainerDimensionsProperty, value); }
    }

    static MyContainer()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyContainer), new FrameworkPropertyMetadata(typeof(MyContainer)));
    }

    public override void OnApplyTemplate()
    {
        _grip = Template.FindName("PART_Resizer", this) as ResizeGrip;
        if (_grip != null)
        {
            _grip.MouseLeftButtonDown += Grip_MouseLeftButtonDown;
            // other handlers
        }

        SizeChanged += MyContainer_SizeChanged;
        base.OnApplyTemplate();
    }

    void MyContainer_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        // update your DP
    }
    ...
}

Um davon Gebrauch zu machen Sie brauchen, um sicher haben Sie ein Element in der Vorlage mit der richtigen Art und Namen das Attribut entsprechen.

<local:MyContainer ContainerDimensions="{Binding Path=SavedSize}">
    <local:MyContainer.Template>
        <ControlTemplate TargetType="{x:Type local:MyContainer}">
            <Grid>
                <Border Background="{TemplateBinding Background}">
                    <ContentPresenter/>
                </Border>
                <ResizeGrip x:Name="PART_Resizer" HorizontalAlignment="Right" VerticalAlignment="Bottom"
                            Width="20" Height="20"/>
            </Grid>
        </ControlTemplate>
    </local:MyContainer.Template>
</local:MyContainer>

Sie können nun diese Vorlage überall hinstellen, da es nicht hat erklärt, keine Event-Handler und so ist unabhängig von einer Code-Behind-Datei. Sie jetzt alle Ihre UI-Logik in einem UI-spezifische Klasse gekapselt haben, aber immer noch Zugriff auf Daten benötigen Sie in Ihrer VM durch Bindung.

Wenn man darüber nachdenkt, ist dies die Art und Weise Sie in der Regel interact mit integrierten Bedienelementen. Wenn Sie einen Expander verwenden würden Sie keine Klicks der ToggleButton in die VM übergeben wollen und versuchen, die Kontrolle von dort zu erweitern, aber Sie vielleicht wissen wollen, ob der Expander geöffnet oder geschlossen ist, so gibt es eine IsExpanded Eigenschaft, dass Sie binden können und speichern und laden als Daten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top