Click here to Skip to main content
15,902,198 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am trying to implement a Button in a WPF project, which sets a variable to 1 by clicking and back by releasing the button. Since I found no way to bind to MouseDown and MouseUp directly. I am trying to go with MVVM Light Toolkit, but it is not working. Does anyone know to handle this? VS2013 WPF4.5

My DLLs from MvvmLightLibs.4.2.30.0:
C#
GalaSoft.MvvmLight.Extras.WPF45
GalaSoft.MvvmLight.WPF45
System.Windows.Interactivity


My XAML:
HTML
<UserControl x:Class="PMWA.View.OperatorView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF45">
    <Grid>
                <Button  x:Name="MoveUp"
                         Content="Up"
                         Margin="5">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseDown">
                            <cmd:EventToCommand Command="{Binding MoveUpCommand}"/>
                        </i:EventTrigger>
                        <i:EventTrigger EventName="MouseUp">
                            <cmd:EventToCommand Command="{Binding StopMoveCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
                <Button x:Name="MoveDown"
                        Content="Down"
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseDown">
                            <cmd:EventToCommand Command="{Binding MoveDownCommand}" />
                        </i:EventTrigger>
                        <i:EventTrigger EventName="MouseUp">
                            <cmd:EventToCommand Command="{Binding StopMoveCommand}" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
                <Button  x:Name="Apply"
                         Content="Apply"
                         Command="{Binding ApplyDistanceCommand}"
                <TextBox x:Name="Distance"
                         Text="{Binding CurrentDistance}"
    </Grid>
</UserControl>


Hier is my ViewModel:
C#
private ICommand moveUpCommand;
public ICommand MoveUpCommand
{
    get
    {
        if (moveUpCommand == null)
        {
            moveUpCommand = new RelayCommand(p => ExecuteMoveUpCommand());
        }
        return moveUpCommand;
    }
}
private void ExecuteMoveUpCommand()
{
    Trace.WriteLine("Move Up");
    SetPort1(1);
}

And the binding is set up in MainWindow.xaml.cs like this:
C#
private void SetupBindings()
{
    var operatorModel = new Model.Operator();
    operatorView.DataContext = new OperatorViewModel(operatorModel, measurementWeightListViewModel);
}

I have i third button which works fine but those up and down buttons wont do anything :(
Posted

Hi matlab22,

You've written your code correctly, but you are trying to overdo it. Just change the button code to this one and let me know how it goes.
<Button x:name="MoveUp" content="Up" margin="5" command="{Binding MoveDownCommand}" xmlns:x="#unknown" />


Hope this helps, Cheers

Update 1

So I understood your question incorrectly (partly due to that you haven't posted all the code I needed to understand it at a glance). Sorry for that.

Your approach to the problem is correct, but your understanding of events are not. That's why you haven't been able to make it work. Events occur when something changes, not as long as something is happening. For instance, when you hold down your left mouse button on the button, it fires the 'LeftMouseButtonDown' event but it won't fire it repeatedly, as long as you are holding it. It would fire it repeatedly, if you started clicking your left mouse button. So what you need is something which would trigger on left mouse button down and keep polling it the status of the left mouse button independently of the UI thread (obvious reason: it will block the UI as long as it runs otherwise).

My explanation has got quite long :D Sorry about that, so here goes the code. I created a new MVVMLight4.5 project and removed all the unnecessary code and updated the MainViewModel and MainWindow to achieve this.
public class MainViewModel : ViewModelBase
    {
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            statusData = new StringBuilder();

            worker = new BackgroundWorker {WorkerSupportsCancellation = true};
            worker.DoWork += workerOnDoWork;

            MoveUpCommand = new RelayCommand(moveUpAction);
            StopMoveUpCommand = new RelayCommand(stopMoveUpAction);
        }

        private void workerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
        {
            var counter = 0;
            while (!worker.CancellationPending)
            {
                // This is just a guard condition
                if (counter == 100)
                    break;

                Status = "Going up";
                Thread.Sleep(50);
                counter++;
            }

            Status = "Stopped going up";
        }

        private void stopMoveUpAction()
        {
            worker.CancelAsync();
        }

        private void moveUpAction()
        {
            worker.RunWorkerAsync();
        }

        #region Member(s)

        private readonly BackgroundWorker worker;

        private readonly StringBuilder statusData;
        public string Status
        {
            get { return statusData.ToString(); }
            set
            {
                if (string.IsNullOrWhiteSpace(value))
                    return;

                statusData.AppendLine(value);
                RaisePropertyChanged("Status");
            }
        }

        public RelayCommand MoveUpCommand { get; private set; }
        public RelayCommand StopMoveUpCommand { get; private set; }

        #endregion
    }

And in the MainWindow I changed the XAML to this:
XML
<Grid x:Name="LayoutRoot">
       <Grid.RowDefinitions>
           <RowDefinition Height="Auto" />
           <RowDefinition Height="*" />
       </Grid.RowDefinitions>
       <Button Content="Go up">
           <i:Interaction.Triggers>
               <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
                   <command:EventToCommand Command="{Binding MoveUpCommand}"/>
               </i:EventTrigger>
               <i:EventTrigger EventName="PreviewMouseLeftButtonUp">
                   <command:EventToCommand Command="{Binding StopMoveUpCommand}"/>
               </i:EventTrigger>
           </i:Interaction.Triggers>
       </Button>
       <TextBox Text="{Binding Status}" VerticalScrollBarVisibility="Visible" Grid.Row="1" />
   </Grid>

Hope this helps, cheers
 
Share this answer
 
v3
Comments
matlab22 4-Apr-14 4:01am    
As far as I know this would just give you the click event. I needed the press and release event.
CodeHawkz 5-Apr-14 13:51pm    
Hey, sorry I misunderstood your question. I just understood what you wanted to do and I updated my solution (Update 1). Hope it helps, cheers.
matlab22 7-Apr-14 3:00am    
Thanks for your detailed explanation. Probably I wrote it a little misleading. My only problem was that the binding didn't worked. The down press had to set a flag and the release had to clear this flag. Otherwise there is a RepeatButton Class which constantly fires event while pressing.
I kicked this mvvm light toolkit and went with:

Dll: System.Windows.Interactivity.dll
Namespace: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

HTML
<UserControl x:Class="PMWA.View.OperatorView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <Grid>
        <GroupBox Grid.Column="0"
                  Grid.ColumnSpan="2"
                  Grid.RowSpan="5">
            <GroupBox.Header>Operator</GroupBox.Header>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Button  x:Name="MoveUp"
                         Content="Up"
                         Grid.Column="0"
                         Grid.Row="1"
                         Grid.ColumnSpan="2"
                         HorizontalAlignment="Center"
                         VerticalAlignment="Bottom"
                         Width="75"
                         Margin="5">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="PreviewMouseDown">
                            <i:InvokeCommandAction Command="{Binding MoveUpCommand}"/>
                        </i:EventTrigger>
                        <i:EventTrigger EventName="PreviewMouseUp">
                            <i:InvokeCommandAction Command="{Binding StopMoveCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
                <Button x:Name="MoveDown"
                        Content="Down"
                        Grid.Column="0"
                        Grid.Row="3"
                        Grid.ColumnSpan="2"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Top"
                        Width="75"
                        Margin="5">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="PreviewMouseDown">
                            <i:InvokeCommandAction Command="{Binding MoveDownCommand}" />
                        </i:EventTrigger>
                        <i:EventTrigger EventName="PreviewMouseUp">
                            <i:InvokeCommandAction Command="{Binding StopMoveCommand}" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
                <Button  x:Name="Apply"
                         Content="Apply"
                         Command="{Binding ApplyDistanceCommand}"
                         Grid.Column="1"
                         Grid.Row="2"
                         HorizontalAlignment="Left"
                         VerticalAlignment="Center"
                         Width="75"
                         Margin="5" />
                <TextBox x:Name="Distance"
                         Text="{Binding CurrentDistance}"
                         Grid.Column="0"
                         Grid.Row="2"
                         HorizontalAlignment="Left"
                         VerticalAlignment="Center"
                         IsReadOnly="True"
                         TextAlignment="Right"
                         Width="75"
                         Margin="5" />
            </Grid>
        </GroupBox>
    </Grid>
</UserControl>
 
Share this answer
 
v2
Comments
Nelek 5-Apr-14 16:58pm    
Is this the answer? Or another trial and you are expecting further help?

Please edit the message and clarify it :)
matlab22 7-Apr-14 2:54am    
Sry about this, I'm new here :S Yes this is my working solution.
Nelek 8-Apr-14 4:24am    
No problem. Thanks for clarifying it :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900