|
|
Thanks
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
|
|
|
|
|
hi everyone,
Can anybody give me a solution for focusing on an element in a view from ViewModel by binding?????
|
|
|
|
|
You might want to look at the solution provided by Anvaka here[^].
|
|
|
|
|
It is a good post. The only thing for the OP to be aware of though is that focus in WPF is a tricksy thing. Sometimes what you think you are focusing on isn't what ends up focused.
|
|
|
|
|
Good link!
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
|
|
|
|
|
I thought of writing one myself for the OP, then found this sample. There wasn't a lot I could have done to improve on it, so I thought I'd leave it alone.
|
|
|
|
|
My current project has problems in the login dialogue, focusing on the first text box when it opens - I shall be busy tomorrow morning implementing this to see if it works - again good find - and timing was excellent.
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
|
|
|
|
|
Hmm... was kind of envisioning something along the lines of a bindable version of FocusManager.FocusedElement / ElementName binding, but that would mean the VM would be tightly coupled to view control names . Not too big on having to put an attached property on x controls that I might want to set focus to (and having x public bool properties to boot). Not too sure the VM should be the one deciding focus anyways. Seems like a job for the view. I'm thinking 99% of cases can be handled in XAML with triggers .
|
|
|
|
|
Do you mean "event" as in raising a real event? If so, the VM raising events to the V is kinda backwards and not really much different then just exposing public properties in the VM that the V binds to.
On the drive in to work, I thought about this more... I'm now thinking something along the lines of following the .NET control model. I think using the built in VisualStateManager could possibly work. I haven't tried it, so it may be dependent on something , if so, something very similiar to it. This way, you can handle a bunch of different states (in the XAML) with a single object.
Kinda all the same... 50 public bools vs. 50 events vs. a visual state manager. I'd definitely go with some design that can do multiple things off of one property / event / whatever.
|
|
|
|
|
Wait, I kind of read your response as "I'm going to raise Event1" to signal that something should happen in the view. How are you going to tell the view through Event1 to set focus to 1 of 50 controls? Aren't you going to need one event for every state? What I mean is, are you defining a custom eventargs that contains which control to set focus to? The OP poster wanted to set focus from the VM to any one of those 50 controls.
Where I was headed with the VSM is that they already have a method for "switching" in the XAML based on the state. No code behind.
I think we are both trying to say the same thing in different ways LOL, that you should be able to do different things through a single property, DP, whatever.
|
|
|
|
|
Gotcha.
OP sounded like he wanted to randomly set focus to random controls at random times. Otherwise, why would you need a bindable solution?
'50' as in the sense of multiple controls. If I have a dialog with 3 edit boxes, I thought OP wanted to be able to set focus to any of the 3 edit boxes.
If you wanted to do that, you'd either need a custom eventargs to pass a param, or some other object like VSM.
If you are trying to accomplish something like "hey! you were a douche and you put 24 in an edit box that only allows 50 -> 100, so I'm going to focus the edit box for you!" then I wouldn't use any of these solutions and would do it with validation templates.
|
|
|
|
|
this solution is for frameworkelements but i want to focus on a gridviewcolumn....
is there any solution?????
|
|
|
|
|
gridviewcolumn? as in the standard WPF ListView's GridViewColumn? The GridViewColumnHeader is actually the FrameworkElement, but thats not a focusable control anyways.
|
|
|
|
|
not listview's,i mean gridview's GridViewColumn...
|
|
|
|
|
Would anyone like to chime in on the Comments and Discussions section over here?
WPF Dialog Service via Binding[^]
I'm the author and I strongly disagree with the "vote of 2".
|
|
|
|
|
As I already told you, your technique does not allow for testing the VM. When you hit a block of code in the VM that triggers your MessageBoxHelper.Message property, you display a blocking modal message box that requires somebody sitting at the keyboard to dismiss it. You provide no means to prevent that from happening during testing. Using the ServiceLocator pattern, that functionality is provided. The whole point of the service is to allow for testability. In your application, you register the real IDialogService or whatever, but during automated tests, you register a stubbed out IDummyDialogService. This allows you to substitute a non blocking service.
|
|
|
|
|
How does my technique not allow for testing the VM? While running unit testing there would be no actual blocking model dialog box displayed. As I already told you, my approach is better precisely because no stub is required.
|
|
|
|
|
How do you know when unit testing is going on? I see absolutely nothing in the code that prevents the dialog box from being shown.
|
|
|
|
|
The view doesn't exist during unit testing.
|
|
|
|
|
Adrian Alexander wrote:
The view doesn't exist during unit testing.
Correct. So guess what happens during testing? *Nothing*. In your sample code, you set Message to your DialogPM object and the message box gets shown by the view that is bound to it. During testing, there is no view, so nothing happens. None of the code in the lamdas is tested.
Anyways, just a personal opinion, but the more I look at this, the more I don't like it. Seems like a lot more work then the service locator:
1) you have to add the MessageBoxHelper to your view xaml
2) you have to add a bindable / public DialogPM property to your VM
3) you can't use the lambdas inline because they are untestable as mentioned above and you would need to break them out into seperate methods and test them separately (not very cool if you only need a one or two line code block!)
I don't see how this is any easier or better then:
MessageBoxButtons result = ViewModelBase.GetService<IDialogService>().ShowMessageBox(...);
switch (result)
{
}
???
modified 30-Jan-12 12:57pm.
|
|
|
|
|
As you just pointed out, making the lamdas into methods would then mean you can directly call them for testing, so I don't see any problem there. In fact, those "lambdas" are ICommands like any other in the VM. In any case, the technique I suggest could easily be adjusted to work with a switch statement if you like doing it that way.
I prefer using binding (which everyone uses in the WPF apps anyway) and you're determined to use a service locator (which I don't see any need to introduce into my code). We've come a long way from your original claim that my approach is a "clear violation of MVVM". It is just a matter of personal taste as you said.
|
|
|
|
|
Adrian Alexander wrote: As you just pointed out, making the lamdas into methods would then mean you can
directly call them for testing, so I don't see any problem there.
Why would I want to break a single line of code into a separate method? So your "time saver" technique now requires a ton more work? Every single response I get from the message box, I would need to put into a separate method to test it? I suppose you could just have one method which takes the MessageBoxResult and have all your lambdas call it with the appropriate value. Seems silly though. 3 lambdas + 1 method.
Adrian Alexander wrote: In fact, those "lambdas" are ICommands like any other in the VM.
Yes, VMs expose ICommands, but not every bit of functionality in the VM is broken out into a separate ICommand. Thats absurd. ICommands are only created when you need to invoke some operation from the UI.
Using your technique, I would need to create 3 separate methods or 3 separate ICommands (if my message box happens to display Ok, Cancel & Retry for example). If I do go ahead and create ICommands, oh boy... now I need 3 separate ICommand fields and the code to new up those ICommands, etc. So much work!!!
Now imagine if my VM displays messages boxes in 15 places and each message box has 2 or 3 buttons. Now I need 30 to 45 separate methods just to handle message box responses!!! OH MY LORD.
Adrian Alexander wrote: In any case, the technique I suggest could easily be adjusted to work with a
switch statement if you like doing it that way.
A better design then what you have now, but still lacking testability. You would again need to break out all the case statements into separate methods. ServiceLocator has no such requirement.
Adrian Alexander wrote: I prefer using binding (which everyone uses in the WPF apps anyway) and you're
determined to use a service locator (which I don't see any need to introduce
into my code).
You don't seem to have a clear understanding of the difference between the two.
Actually, I don't even use ServiceLocator in my new apps anymore. I use DI. If you took a survey on CP, you'll find almost everybody uses MEF and/or DI to pass around services.
Look, I'm not against coming up with new things... but you have yet to show how your VM remains testable without breaking out every message box case handling code into a separate method and without adding a lot of work for the developer.
ServiceLocator, DI and MEF have already solved all these problems.
|
|
|
|
|
SledgeHammer01 wrote: ICommands are only created when you need to invoke some operation from the UI.
That's exactly correct, and that's what's happening in this case. Just as you bind an ICommand to Button.Command, using my approach you associate an ICommand with a button on the message box.
I wish you the best of luck.
|
|
|
|
|