WPF command not executable - wpf

I have a button on a toolbar that has its command set to "MyControl.Print" (for example).
In the control the command is added to the command bindings including both the Execute and CanExecute.
The control is within a window with other controls docked appropriately.
I am finding that for the Print button to be enabled I have to "select" MyControl first which does not provide a good user experience and indeed causes various "bugs" being raised and lots of confusion.
Is there a way that I can ensure that the button is enabled whether or not the control has been "selected"?

Since the CanExecute doesn't fire, I think you might be looking at the major downside to RoutedCommands - the way they tunnel and bubble can leave a highly composed interface unable to have commands arrive anywhere useful. For this reason we ended up moving to DelegateCommands from (I think) the Microsoft CAG. Not any of the other stuff, just the commands. Works a lot better, and isn't tied in to the interface so tightly.
Oh, the other response raises a good point. I assumed you meant that to ever print, your MyControl needed to have keyboard focus. Is it only the first time and after that it works?
I recommend http://msdn.microsoft.com/en-us/library/ff921126(PandP.20).aspx as a pretty good starting point. You don't have to worry too much about the IActiveAware up front, since you're hoping for this command to be available all the time (or at least let its availablity be determined by CanExecute).

CommandManager.InvalidateRequerySuggested will force the command manager to re-call all of your CanExecute methods and should disable the button. Perhaps call that onload?

Related

Send call open event from the event ItemChanged of a DataWindow

I try to send for the Open event of the window from the event ItemChanged a DataWindow using the: SUPER :: EVENT OPEN () in addition to the open event contains "script ancestor" I also need to run; itself need to restart the window from the event ItemChanged of a DataWindow.
I hope your help.
Thanks in advance.
Regards,
A few things jump out from your question.
SUPER::EVENT OPEN() will try to call the Open event of the DataWindow if called from the ItemChanged, not the Window.
I'm not 100% sure of this, but I'm pretty sure I've run into problems trying to call the ancestor of one script from a completely different script. I can't point to documentation; I'll have to just chalk it up to experienced suspicion.
It's not entirely clear what you're after, but if you want to call the Open of the window (and I'll suggest otherwise below), and if the window's Open script either extends the ancestor script or explicitly calls the ancestor script (as above), explicitly calling the ancestor script is unnecessary, and strikes me as potentially undesirable. Just call the Open script of the window you're writing.
This will depend entirely on your code, but of the dozens of systems I've had to maintain, I'd never assume that running the Open event of a Window would "restart" the window. Most systems I've worked on, that would just create an unexpected mix of previous and new states. Additionally, even if I coded this from scratch to work perfectly in this way, I'd assume that the next guy that came along to maintain my code (after I won the lottery and retired to a small South Pacific island) would code in a way that made perfect sense to him based on other systems he worked on, but would screw up my assumptions. If I needed to "restart" the window, I would either:
close the window and post an Open() (the function, not the event) of the window again
create a ue_ResetWindow event, hopefully coding so that the Open could use it as well, that made it obvious that anything added to the window needed to be maintained in this script as well
(Of the two, the latter would be far better user experience and coding, IMHO.)
Good luck,
Terry.

Avoid second click in silverlight button MVVM

I've seen I have a problem with several users that use to double-click in buttons.
I have several buttons bound to commands that launch many actions.
For example there are two windows that communicate between them through a mediator so when I click "close the other window", the bound command sends a "CloseTheOtherWindowMessage". The problem is that when a user makes double click it tries to close the window a second time and, as expected, it crashes.
I've tried to set the window BusyIndicator as IsBusy when I press the button but my finger is quicker than MVVM and it still let me double-click before it starts showing the BusyIndicator.
I've found many examples of how to only admit double click in MVVM using interaction.Behaviors but I want just the opposite. Is there any example or other good and general solution for this problem?
Why is it "as expected" when it crashes? A crash should never be "as expected".
Your finger shouldn't be "quicker than MVVM". The Dispatcher thread always acts deterministically and sequentially. Do you use a multi-threaded approach?
In the command's Execute method or handler, raise its CanExecuteChanged event, and the binding engine will immediately call CanExecute(...). Make it so that this method will return false the second time. Maybe use a timer, or, better yet, you can logically determine by your view model state alone that the action is not possible right now (i.e. because IsOtherStuffAvailable is currently false).

WPF performance problem with CommandManager

We've created a new, quite complex, WPF application from the ground up and have run into a performance problem as the number of commands registered with the CommandManager increase. We're using simple lightweight commands in our MVVM implementation, however the third party controls we're using (Infragistics) do not, and call CommandManager.RegisterClassCommandBinding liberally to add RoutedCommands. The performance problem manifests itself as a perceived sluggishness in the UI when responding to user input, for example tabbing between controls is slow, text input is 'jerky' and popup animation is 'clunky'. When the app is first fired up the UI is snappy. As more screens containing Infragistics grids are opened the performance deteriorates.
Internally, the CommandManager has a private field named _requerySuggestedHandlers, which is a List< WeakReference>. I've used reflection to get a reference to this collection, and I've noticed that when I call .Clear(), the responsiveness of the UI improves back to its initial state. Obviously I don't want to go round clearing collections that I know little about, especially using reflection (!) but I did it to see if it would cure the performance problems, and voila it did.
Normally, this situation would clean itself up after a certain amount of time passes. However, the collection of WeakReferences (_requerySuggestedHandlers) will only get trimmed once a garbage collection is initiated, which is non-deterministic. Because of this, when we close down windows containing grids (Infragistics XamDataGrid), the CanExecute property for 'dead' grid commands continue to be evaluated unnecessarily, long after the window is closed. This also means that if we close down a number of windows, the performance is still sluggish until a garbage collect is initiated. I understand that this can happen on allocation, and I've seen that myself because if I open a further window this causes the initial memory (from the disposed Windows) to be collected and performance returns to normal.
So, given the above, here are my questions:
How, and from where, does CommandManager.InvalidateRequerySuggested() get called? I haven't found any documentation on MSDN that explains this in any great detail. I hooked up to the CommandManager.RequerySuggested event and it looks like it's being called whenever controls lose focus.
Is is possible to suppress CommandManager.InvalidateRequerySuggested() being called in response to user input?
Has anyone else run into this issue, and if so, how have you avoided it?
Thanks!
This sounds like one of the rare cases where deterministically calling GC.Collect() is the right thing to do. The ordinary argument against it is that the garbage collector is smarter than you are. But when you're dealing with WeakReference objects, you enter territory where you may know something that the garbage collector doesn't. Kicking off garbage collection is certainly better than clearing _requerySuggestedHandlers - among other things, it won't do anything to the WeakReference objects that point to controls that are still alive.
I'd choose this over trying to figure out how to suppress RequerySuggested, since that would screw up the behavior of those commands that you still care about.

contextsensitive RoutedUICommand.CanExecute, Execute

I have a single RoutedUICommand that can be accessed through various places in the UI. Such as global Keyboardshortcut, Menu, ContextMenu or Button. The code that is to be executed in the RoutedUICommand.CanExecute and RoutedUICommand.Execute methods depends on what UI element was used. How can I achieve this differentiation. I was thinking that I could use the (Can)ExecutedRoutedEventArgs.Source or OrigianlSource but the source is always the same. It is the main Root window. How is this usually achieved? What could I possibly be doing wrong?
If you need different code to run depending on the UI that invoked the command you are probably doing something wrong.
If you have something like a just doing something from a keystroke or opening a dialog asking for more information from a menu you should break this apart into two commands (like MS Office "Print" and "Quick Print" commands).
If you truly have to do different things from each UI element you are not getting any advantage from using commands and should think about using old fashioned event handlers, at least then the element specific code is tied to the element and not stored in a central all encompassing "Execute" code .
And if you choose to ignore my advice above, take a look at the CommandParameter property, you can set a different value fro the parameter for each UI element, at least with it you can keep an illusion of the UI/Logic separation commands are designed to provide.
Normally you could have different CommandBinding implementations for different 'Targets' - having different behavior for each 'Source' is unusual.
Could you give an example of what you are trying to do?

So what am I missing with this here WPF?

Background: I have a little video playing app with a UI inspired by the venerable Sasami2k, just updated to use VMR9 (i.e. Direct3D9 with DirectShow) and be less unstable. Currently, it's a C++ app using raw Win32, through necessity: none of the various toolkits are worth a damn. WPF, in particular, was not possible, due to its airspace restrictions.
OK, so, now that D3DImage exists it might be viable to mix and match D3D/VMR9/DirectShow and WPF. Given past frustrations with Win32's inextensibility, this seems like a good thing.
But y'know, I'm falling at the first hurdle here.
With Win32 I have created (very easily) a borderless window that's resizable, resizes proportionately, snaps to the screen edges, and takes up the whole screen (including taskbar area) when maximized. It's a video app, so these are all pretty desirable properties.
OK, so, how to do the same with WPF?
In Win32, I use:
WM_GETMINMAXINFO to control the maximize behaviour
WM_NCHITTEST to control the resize borders
WM_MOVING to control the snap-to-screen-edges
WM_SIZING to control the resize aspect ratio
However, looking at WPF it seems that the various events arrive too late, unless I'm misunderstanding the documentation?
For example, I don't know when I'm mid-move, as LocationChanged says it fires only once the window has moved (which is too late).
Similarly, it appears that StateChanged only fires once the window has been restored/maximized (when I need the information prior to the maximize, to tell the system the correct maximize size).
And I seem to be completely overlooking where the system tells me about resizes. Likewise the hit testing.
So, uh, am I missing something here, or do I have no choice but to drop back to hooking the wndproc of this thing anyway? Can I do what I want without hooking the WndProc?
If I have to use the WndProc I might as well stick with my existing codebase; I want to have simpler, cleaner UI code, and moving away from the WndProc is fundamental to this.
If I do have to hook the WndProc, I have to wonder--why? Win32 has got the sizing/sized, moving/moved, poschanging/poschanged window messages, and they're all useful. Why wouldn't WPF replicate the same set of events? It seems like an unnecessary gap in functionality.
Plus, it means that WPF is tied to a specific USER32-dependent implementation. This means that MS can't (in Windows 7 or 8, say) invert the display layer to make WPF "native" and emulate HWNDs and WndProcs for legacy apps--even though this is precisely what MS should be doing.
OK, to answer my own question, I was missing Adorners (never came back in any of the searches I did, so it doesn't seem that they're as widely known as they perhaps should be).
They seem rather more complex than the WndProc overrides, unfortunately, but I think it should be possible to manhandle them into doing what I want.
And I seem to be completely overlooking where the system tells me about resizes. Likewise the hit testing.
For the resizing you're indeed missing the SizeChanged event.
AFAIK there is sadly no OnSizeChanging, OnLocationChanging and OnStateChanging event on a Window in .NET
I saw that one, but as far as I can tell it only fires after the size has changed, whereas I need the event to fire during the resize. Unless I'm misreading the docs and it
actually fires continuously?
It does not fire continuously but you can probably use the ResizeBegin and ResizeEnd events and be able to do that.
Aren't they WinForms events?
Hmm, you're right.
In code you can set the WindowStyle property to "None" and WindowsState to "Maximized"
Im not sure what the Xaml would look like.
Can you perhaps override the ArrangeOverride and/or MeasureOverride to make up for those missing resize events? Measure is the first pass, and occurs when a layout needs to adjust for a new size, so it's kind of like a size changing event.

Resources