Вопрос

У меня есть некоторые проблемы с EventToCommand, не ведем себя так, как я ожидаю, что с Capturemouse.

У меня есть резервуар, который я определил несколько EventToCommand на:

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

Функции обработки устанавливаются в конструкторе класса:

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

И, наконец, я делаю всю свою логику для изменения изменений:

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

Команды OnrequestresizeStart & OnrequestresizeStop работают нормально, и онrequestresize работает ... Но только когда я на самом деле через резюме. Это не отображается, что Capturemouse на самом деле не отправляет все события мыши к резюме.

Это ограничение EventToCommand или что-то особое надо происходить?

Спасибо за любую помощь!

Это было полезно?

Решение

Почему вы используете команды для этого вместо стандартных обработчиков событий? Это явно логика пользовательского интерфейса, которая принадлежит коду-позади, а не просмотрамодель.

****ОБНОВИТЬ**

В случае, если вы используете это в контрольной таблице, вы можете лечить код управления в качестве кода. Для выполнения соединений событий вы можете использовать шаблон шаблона и подключаться к специальному именованному элементу в OnApplyTemplate. Чтобы облегчить предоставление размера (или что-то еще ваша ваша VM). Вы можете добавить DP для хранения соответствующего значения и связывать свойство VM для этого. Это также позволяет делать двусторонние привязки, если вам нужно сделать что-то вроде набора начального размера от VM.

// 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
    }
    ...
}

Чтобы использовать это, вам необходимо убедиться, что у вас есть элемент в вашем шаблоне с правильным типом и именем, чтобы соответствовать атрибуту.

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

Теперь вы можете поставить этот шаблон в любом месте, так как он не объявляет никаких обработчиков событий и так не зависит от кода-за файлом. Теперь у вас есть вся ваша логика пользовательского интерфейса, инкапсулированная в определенном классе UI, но все еще может получить доступ к данным в вашу виртуальную машину, привязывая его.

Если вы думаете об этом, это так, как вы обычно взаимодействуете со встроенным элементом управления. Если вы используете расширитель, вы не захотите пройти клики ToggleButton в вашу виртуальную машину и попробуйте сделать элемент управления оттуда, но вы можете узнать, открыт ли расшифер или закрыт, так что есть свойство ISExpanded может привязать и сохранить и загружать в качестве данных.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top