Caliburn Micro disable buttons which have no Property? - c#

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

Related

How to make command not disable button when clicked

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!

How to manipulate a control without any pattern implemented?

I'm trying to implement the automation test via UIAutomation for our project. But lots of the controls are not standrad, and proper patterns are also not implemented for that controls. How should I to manipulate the controls via UIAutomation framework in this case?
For example, a button in our product is implemented via a Pane, and the invoked pattern is not implemented as well. How should I click the button? (To avoid installing VS on the test machine, I don't want to use Mouse.Click() in Microsoft.VisiualStudio.TestTools.UITesting namespace) Is there a way to do that only using UIAutomation framework or something else embedded in .net framework? Thanks in advance! (If the proper pattern is implemented, Below code will work. And as a new user, I cannot post the screenshot for your reference, sorry!)
object temp = null;
if (btnTest.TryGetCurrentPattern(InvokePattern.Pattern, out temp))
{
InvokePattern btnTestPattern = temp as InvokePattern;
btnTestPattern.Invoke();
}
The only way to interact when Control Patterns are not implemented is to go clicking around stuff.
I would suggest try following to avoid maximum errors.
Before sending the click, make sure the parent of button(pane or window is set to foreground)
Instead of sending the click to corner of the AutomationElement, try sending it in midpoint, of the element,
Also, try hovering over the element first, the wait like 200ms, and then send click, So that you are sure to see execution.[Trust me, this helps debugging a lot and avoids many issues.]
The best thing would be, if those guys who implement the system would implement server-side UIA provider to their UI Elements!
But often that's not possible..., I used the following workaround (at least for clicking/toggling):
AutomationElement yourAE = ...// some code to find the right AutomationElement (AE)
clickablePoint = yourAE.GetClickablePoint();
also BoundingRectangleProperty could be of help
If you receive that clickable point you can use
System.Windows.Forms.Cursor.Position = new System.Drawing.Point((int)clickablePoint.X, (int)clickablePoint.Y);
to move to the location, and than click it via InputSimulator or some win32 (user32.dll) commands.
(note: of course you can also use InputSimulator or win32 to move the mouse - but I had some problems with the InputSimulator when it came to several screens with different locations or resolutions - so Cursor.Position was the easiest approach, which is also very reliable)

How do I dynamically evaluate an event?

Please forgive me if this should be phrased differently in a programming context - I have no idea what to search for other than exactly what I used to title my question.
Context - I am attempting to build a word search game involving a 4x4 grid of random letters. I'm currently using a Label_Click event to change the background color of the label containing a given letter. In the future there will be many other actions than just this (evaluating whether an array of clicks forms a legitimate word, for instance), but I'm fundamentally stuck with this problem:
// pseudo-code
if (lblA1_wasClicked || lblB1_wasClicked || ... lblD4_wasClicked)
{
whichever_wasClicked... //perform actions
}
Perhaps I need to learn about creating an event handler for this situation? I have never created a custom event handler, I just know what they are in theory. I am kind of stuck and at this point it's tough to know what to search for to keep learning. I know only enough to be dangerous, so please go easy on me if the answer is as straight-forward as my question feels. :)
If you are in the ui, you can go to the properties of each label and set their Click handler to the same method. so if you have a method with a signature like this.
public void label_Click(object sender, EventArgs e)
{
}
Then assign that to each label and then use that to process each one. This is a naive example, and there are much better methods that use established patterns for creating windows forms applications. Check out this question or search for MVP pattern windows forms to get more info on it!

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.

.Net C# Design View errors

I have subclassed a Treeview and on instantiation it loads a new ImageList (and the associated Images).
Whenever I switch to the designer view, it's also trying to run this code, however the images aren't in the designer's path, so it crashes. I ended up putting in a hack to see if the current directory is "Visual Studio", then do nothing... but that's so ugly.
I find this happening for other things. If a control is trying to use objects during load/initalization that are only available while the program is running, then the Design View cannot bring up the control.
But is there a way to get around this?
I guess what I'm hoping for is having a try/catch for the Designer (only) with the ability to ignore a few errors I know will be happening (like FileNotFoundException, etc.).
Thanks
Everything that inherits from System.Windows.Forms.Control has a DesignMode property that returns a boolean indicating if you are in design mode or not. You could use this to determine when to/when not to load external resources.
Usually it is better to move the loading of these resources to an override of OnLoad as they are rarely required directly at construction. This fixes the issue you are seeing and means that only trees which get displayed at least once will perform these additional resource loading steps.
Otherwise, you can just exclude these steps during design time by checking the DesignMode property and acting accordingly.
This is a fine pattern to use if you're making a control library with a sample of images when shown in the designer or hook ins to other designer features but as a pattern for development I'm not sure it's very effective.
I would suggest shifting your "business logic" (in this case your loading of certain images into a treeview) outside of the bounds of your treeview control. In your case I would place the logic within the Load event of the form that the control is inside:
public void Load(object sender, EventArgs e)
{
string path = "c:\somePath\toAwesome\Images";
myFunkyTreeView.AddImages(path);
}
For larger apps I personally think you want to shift the logic even out of the forms themselves, but this is debatable measure as it requires additional plumbing as a trade-off for the flexibility this provides.
Thanks for pointing me in the right directioon guys.
I had tried registering to the OnLoad event, but that event is triggered when the Design View comes up, so that didn't quite work for me (am I doing something wrong?).
Anyway, I looked a bit more into the DesignMode property. It can only work for Controls, and sometimes your object may not even be a control.
So here's the answer I prefer:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) {
// design-time stuff
} else {
// run-time stuff
}
Found it here.

Categories