How to make command not disable button when clicked - c#

I'm currently developping an application in MVVM.
I'm using for all buttons RelayCommand to perform action. The fact is that, with RelayCommand, the button is disabled when clicked on it, the time that the command is executing.
Because our rendering engine is a little bit heavy, when we open a new window, the button stay disabled for a bit, like a second.
My question is : is there a way to disable this behaviour and let the button enabled, because it changes style ?
Changing disabled style is not an option ...
I haven't see that kind of behavior on the net or in the documentation ?
Thank you
EDIT :
Two differents implementations of my RelayCommand
AnswerCommand = new RelayCommand(p => AnswerMail(p), p => IsMailSelected());
DeleteMailCommand = new RelayCommand(p => Task.Run(() => DeleteMail()), p => IsMailSelected());

I think you should synchronize the access for the block existing in the ICommand instance Execute method and every time you get there, start a new thread. If you want to click on that Button many times, having that lock section there, will put your calls in a queue. If you want to reject the requests received while it's still working you can implement the balking pattern.
https://en.wikipedia.org/wiki/Balking_pattern
This way, your button will stop being disabled when the created thread is starting.
I am not sure if this approach helps you but i think it's a feasible scenario.
One more thing, i've just found this:
Patterns for Asynchronous MVVM Applications: Commands
i haven't used it before but looks nice, i will give it a try tonight. Good luck!

Related

Mvvm light issue, not updating UI / buttonstates correctly

We have a strange issue with MVVM light. Our application has some buttons which perform tasks like starting a socketlisterner via a task:
Task.Run(() => { _serviceMonitor.SocketServer.StartListening(); });
The RelayCommands are setup to use CanExecute options:
public RelayCommand StartSocketServerCommand => _startSocketServerCommand ?? (_startSocketServerCommand = new RelayCommand(ExecuteStartSocketServerCommand, CanStartSocketServerCommand));
For unclear reasons, the UI does not always update the button state (enable/disable) correctly until we just click somewhere on the UI. Then the buttons states are correctly enabled/disabled.
Does this sounds familiar to anyone?

Caliburn Micro disable buttons which have no Property?

At the moment i'm working with Caliburn Micro. But i got to a problem which i don't know how to solve.
The problem is i want to disable Buttons, but every website has only a solution with propertys. the functions of my buttons for example just start a thread to establish a connection over tcp with Netmq. So i don't know how i'll be able to disable them. Searched a lot through google but didn't find anything helpful.
Example of a button function
public void startPubButton()
{
Thread entryThread = new Thread(startPublisher);
entryThread.IsBackground = true;
entryThread.Start();
}
is there maybe a possibility to enable the Buttons only when the thread runs ?
That is the one premise behind CM wiring up by convention all you have to do is provide a CanstartPubButton Boolean property run a code check to see if you can enable or disable button according to the logic with that guard property. Call with NotifyOfPropertyChange(() => CanstartPubButton); in some fashion to do what you want. The logic with in the property (get only needed) is up to you. one other thing I will drop on you is a thread presently in the GitHub discussions on the repository itself. Might help and it might not
https://github.com/Caliburn-Micro/Caliburn.Micro/issues/422

Properly use Background Worker in a WPF application

i'm stuck in using properly the background worker, the app needs to communicate with the database, so it takes a bit longer and the UI freezes for a while, i need to create a function that does the database things and wait until the work is finished, for this time, i want to display a kind of window that inform the user about the app state (Loading, busy, Downloading).
My code
i didn't write any code yet, but here're what i need:
//instructions
InitializeComponent();
//do this in background and wait until it finnishes
GetEntitiesFromDatabase();
entitiesListView.ItemSource = someList; (GetEntitiesFromDatabase will initialize this list)
//....
How can i proceed, i know that this question might be already asked in the forum but i'm desperate by searching for an answer, if this can be done other way please help me, thanks in advance.
If you are going to directly manipulate the UI like that, you need to use Dispatcher.BeginInvoke when you aren't on the UI thread (read, in the BackgroundWorker).
Dispatcher.BeginInvoke(new Action(() =>
{
entitiesListView.ItemSource = someList;
}), null);
You could also bind that items source to your view model (a much better idea) and the framework will marshal the change to the bound property for you.
Basically, either use Dispatcher.BeginInvoke or switch to MVVM (which WPF was meant to use anyways).

Redraw WPF UI when minimized

I have a C# WPF application that is software captured using Open Broadcaster Software. When the application is in the foreground or even hidden by another application, it works just fine. However, if it is actually minimized, it stps updating. This makes sense, because usually, why would you need to redraw it if nobody can see it, but this is not true for this case. Is it possible to somehow force the UI to redraw? It would be possible to call a certain method every time a UI update is needed, because the code where I would need the UI to update/redraw looks something like this (simplified):
private void displaySomething(int something)
{
someRectangle.Fill = new SolidColorBrush(...);
// Redraw UI here
}
EDIT: "Update" might have been a misleading term here. "Redraw" may be better.
So if it works even the form is behind the other form, then do not let user to Minimize the form. Set yourWindow.ResizeMode = ResizeMode.NoResize;

How do you manually refresh a window in WPF?

I'm using the ICommand interface to perform binding on a couple of buttons in my application, the Run and Close button. I'm using a helper method that was mentioned in this question to hook up the ICommand to a delegate as follows:
_someCommand = new DelegateCommand(this.DoSomething, this.CanDoSomething);
private ICommand _someCommand;
public ICommand SomeCommand
{
get { return _someCommand; }
}
private void DoSomething(object state)
{
// do something here
}
private bool CanDoSomething(object state)
{
// return true/false here is enabled/disable button
}
This appears to work just fine as, in my implementation, CanDoSomething returns the value of a property that I have in my application.
If I set the initial value of the property to true, then the button is enabled and false it is disabled.
I have a series of events that are raised from a BackgroundWorker in the application layer back to the ViewModel that change the value of the property to true or false based on the current state of the application.
The current problem I'm having is that the button is not "re-enabling" when I set the value to true after the work has completed. If I click somewhere within the window, it will update. So, therefore, I'm thinking than manually refreshing the window will solve my problem, at least for the interim. This feels a bit gross to do it this way, but I'm kind of at a loss for what else I could try.
If anyone has any suggestions, I'm all ears.
Thanks for the help!
Ian
Edit -
A little bit more information on the application itself. It uses a background worker in the application thread to handle the "work". The application is a simple utility to manage the creating of tables and loading of data into the tables. We use a lot of pre-defined SQL scripts to setup our test environment, so this is a simple utility that allows us to do that sort of thing based on parameters provided by the user in the UI.
Hopefully that helps, because when I re-read my question it read as if I were doing everything in the UI thread, which is not the case. Progress reports are raised back up to the UI thread and everything is updated as expected, except the button..
CommandManager.InvalidateRequerySuggested() may be the answer - it tells all the commands to check whether they are enabled or not.
You have to raise the CanExecuteChanged event:
http://msdn.microsoft.com/en-us/library/system.windows.input.icommand.canexecutechanged.aspx
This may be more useful than the other answer in cases where you know you should re-evaluate a single control, and re-evaluating all the controls would be costly. The other answer is simpler if you don't have a case like that, though.

Categories