Есть ли событие, которое срабатывает, когда элемент становится неактивным - PullRequest
0 голосов
/ 03 мая 2019

У меня есть приложение WPF-MVVM, которое связывается с ПЛК.Пока кнопка нажата на переменную bool в plc, она должна остаться true, и если она была освобождена, потеряла фокус или стала неактивной, переменная должна снова стать false.

У меня есть кнопки, реализованные с событиями.(Между тем, есть события PreviewTouchUp и PreviewTouchDown, потому что есть мультитач-экраны.)

<UserControl x:Class="..."
    ...
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    ... >
    ...
    <Button>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
                <i:InvokeCommandAction Command="{Binding CmdSetFlag}" CommandParameter="PlcVariable" />
            </i:EventTrigger>
            <i:EventTrigger EventName="PreviewMouseLeftButtonUp">
                <i:InvokeCommandAction Command="{Binding CmdResetFlag}" CommandParameter="PlcVariable" />
            </i:EventTrigger>
            <!-- followed by touch events -->
        </i:Interaction.Triggers>
    </Button>
    ...
</UserControl>

В моей ViewModel есть команды CmdSetFlag и CmdResetFlag:

public MyViewModel : INotifyPropertyChanged
{

    public MyViewModel(string pageName)
    {
        CmdResetFlag = new ActionCommand((p) => MyPlc.WriteVar(p.ToString(), false));
        CmdSetFlag = new ActionCommand((p) => MyPlc.WriteVar(p.ToString(), true));
    }

    /// <summary>
    ///   Sets a bool on the plc to false.
    /// </summary>
    public ICommand CmdResetFlag { get; private set; }

    /// <summary>
    ///   Sets a bool on the plc to true.
    /// </summary>
    public ICommand CmdSetFlag { get; private set; }
}

Таким образом, если мышь или касание отключаются, происходит событие и команды, вызываемые с именем переменной plc в качестве параметра.

Затем существует клиентский класс plc, который пишет в сам plc:

/// <summary>
///   MyPlc is a static wrapper class.
///   It sends write and read commands to the actual plc implementation.
/// </summary>
public class MyPlc
{
    static MyPlc()
    {
        MyActualPlc = new ...Plc();
    }

    /// <summary>
    ///   The actual plc interface in use. There may any type of plc.
    /// </summary>
    private IPlc MyActualPlc { get; set; }

    /// <summary>
    ///   Write a variable to the plc.
    /// </summary>
    /// <param name="varName">The name of the variable.</param>
    /// <param name="value">The value to write.</param>
    public void WriteVar(string varName, object value)
    {
        int myHandle = PlcClient.CreateVariableHandle(varName);
        PlcClient.WriteAny(myHandle, value);
        PlcClient.DeleteVariableHandle(myHandle);
    }
}

Если мышь или сенсор отпущены, переменная снова становится ложной.Таким образом, значение в plc остается истинным до тех пор, пока кнопка не будет отпущена.

Это прекрасно работает, пока не произойдет прерывание, подобное окну, которое открывается при событии.Тогда не срабатывает ни событие PreviewMouseUp, ни PreviewTouchUp.

Я также безуспешно пытался LostFocus.

Есть ли событие, которое можно использовать вместо PreviewMouseUp или PreviewTouchUp?

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Может быть это является решением.

Проблема решена для меня с помощью событий IsEnabledChangedIsVisibleChanged), добавленных через поведение.

Возможно, это работает только потому, что кнопки открываются при открытии окна, которое вызывает прерывание, которое я описал в своем вопросе.

<UserControl x:Class="..."
    ...
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ext="clr-namespace:NamespaceOfMyBehavior"
    ... >
    ...
        <Button...>
            <!-- The triggers looks like above -->
            <i:Interaction.Triggers>...</i:Interaction.Triggers>  
            <i:Interaction.Behaviors>
                <ext:PlcButtonBehavior PlcVar="PlcVar"/>
            </i:Interaction.Behaviors>
        </Button>
        ...
</UserControl>

Класс поведения выглядит как

public class PlcButtonBehavior : Behavior<Button>
{
    public static readonly DependencyProperty InvalidValueProperty =
        DependencyProperty.Register(
            "InvalidValue", typeof(string), typeof(PlcButtonBehavior),
            new PropertyMetadata(string.Empty, (d, e) =>
                (PlcButtonBehavior)d).Update()));

    public string PlcVar
    {
        get { return (string)GetValue(InvalidValueProperty); }
        set { SetValue(InvalidValueProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.IsEnabledChanged += AssociatedObject_IsEnabledChanged;
        AssociatedObject.IsVisibleChanged += IsVisibleChanged_IsVisibleChanged;
        Update();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.IsEnabledChanged -= AssociatedObject_IsEnabledChanged;
        AssociatedObject.IsVisibleChanged -= IsVisibleChanged_IsVisibleChanged;
        base.OnDetaching();
    }

    private void AssociatedObject_IsEnabledChanged(
        object sender, DependencyPropertyChangedEventArgs e)
    {
        Update();
    }

    private void IsVisibleChanged_IsVisibleChanged(
        object sender, DependencyPropertyChangedEventArgs e)
    {
        Update();
    }

    private void Update()
    {
        if (AssociatedObject is Button button
            && button.IsVisible
            && button.IsEnabled
            && AssociatedObject.IsPressed)
        {
            Plc.SetFlag(PlcVar);           
        }
        else
        {
            Plc.ResetFlag(PlcVar);             
        }
    }
}

Чтобы установить события из поведения в качестве триггера, оно не работает.

0 голосов
/ 03 мая 2019

«Это работает нормально, пока не произойдет прерывание, подобное окну, открывающемуся на событии», я не уверен, правильно ли я понимаю, что ваши события не работают, когда ваш элемент управления (или приложение) потерял фокус? Возможно, вы ищете что-то вроде Application.Deactivation Event - Происходит, когда приложение перестает быть приложением переднего плана.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...