I have a WPF user control which needs to validate some fields. It is bound to a class implementing IDataErrorInfo.
When I set the user control as the content of my ContentPresenter in another, already open, window, I can see validation occurring, and error messages being returned, however, I don't get any validation adorner - e.g. the default red outline.
If I enter the field and leave it (triggering re-validation) the validation adorner appears.
Also, if I show the user control in it's own window it shows the validation adorner immediately.
(I'm using Caliburn IResults to do this underneath, e.g. Show.Dialog<VM>(); but I suspect this isn't related)
Can anyone offer any suggestion why the validation adorners aren't appearing immediately. (I had guessed animation on my ContentPresenter ContentChanged, however, I have removed this and still experience the problem.
thanks,
Chris
This is a known bug that exists in .NET 3.5. You may be able to implement a workaround, however if it is feasible, I would recommend upgrading to .NET 4 as this will take care of your issue with validation.
Related
Is there a way to make an entire WPF Window inert after a button click?
The window is invoked via Window.ShowDialog() and after use, the window is no longer needed for interaction but I leave it open to remind the user of the inputs in TextBox's, ListBox's, and give visual feedback via OxyPlot and so on. I leave it to the user to close the window manually.
One solution is to disable all buttons but that's tedious and it still leaves TextBox's functioning. That's not optimal because for anything to be functioning creates the wrong impression that the Window remains for anything other than looking at. It would be better for every control to be non-functioning by a single setting.
I did it by putting a name on the WPF window code behind and then setting .IsEnabled false upon the appropriate button click. All buttons, combo boxes, text boxes, and even OxyPlot became inert at that point and most parts were greyed out.
Consider creating a dedicated boolean dependency property in your code-behind or viewmodel and binding IsEnabled of every TextBox to the property.
UPDATE:
Let me be more specific about what I'm after... I have error borders around my controls using the error template. Those show up all the time since they use the INotifyData interface. But additionally, I want to display bubbles next to controls in an error state when the user mouses over the Save button.
I have pretty much every component of this solution working: I have popups that I can make appear on my controls through the code behind. I have validating viewmodels using the validation framework to give me the borders. And my Save buttons disable themselves as necessary through "CanSave". I also know how to wire up an event handler to listen for mouse enter on the save button.
But now I need to somehow find all the controls in error so I can trigger their bubbles... I can find all the properties in error via the dictionary of properties to error messages in my INotifyDataErrorInfo implementation.... But how to find the DependencyObjects in the visual tree for each property?
I found this WPF. Find control that binds to specific property, but it seems pretty heavy handed.
The .NET validation framework somehow does this, right? Validator.TryValidateObject must search through all the properties with ValidationAttributes, then finds their Dependency objects so it can activate the ErrorTemplate on them... If could access the dependency objects, I could activate their error templates as necessary. How does it do it? Through the bindings? Or is there a better way?
Am I missing something obvious here?
I've created a textbox style to contain a validation.errortemplate for use in a UserControl class. If the UserControl is loaded in the normal, non-MAF way, I can see the validation rule kicking in and getting visual feedback (thick red border, a circular bang to the right of the textbox, and an error message-in-a-tooltip) -- everything works the way I expect it to.
However... if I load that same UserControl in as an AddIn, I lose the visuals. (I do see the error tooltip behaving correctly, so I know my validation rule is firing; I just don't see the border and bang symbol.
My AddIn, by the way, is based on MSDN's example for an 'addin-which-provides-a-usercontrol.'
I know a few of the limitations of an AddIn (e.g., video won't play in an AddIn UserControl); is this another limitation, or am I screwing up?
Thanks in advance!
[Update -- I removed the error template from my UserControl.Resources -- as I suspected, in the non-MAF version, this causes the validation failure to result in the 'standard,' thin red border around the textbox. However, no such red border shows up in the MAF version. Ergo, the TextBox.Style seems to have been ruled out as the culprit.]
Got it working by enclosing the fields I want to validate within an AdornerDecorator tag... go figure :-)
I have UserControl which is hoseted in ElementHost.
It contains DataGrid
When user presses enter or double clicks the row new window is shown (modalless), and when that window is closed window with ElementHost is activated back. The problem is that DataGrid loses focus.
Snoop showed me that visual tree has the following structure:
AdornerDecorator -> AvalonAdapter -> My UserControl.
Snoop shows that after activation AdornerDecorator has properties
IsFocusable = false
IsFocused = false
IsKeyboardFocused = true
IsKeyboardFocusWithin = true
What is an absolute nonsense to me.
When user hits Tab or arrow keys the first enabled UserControl's element receives focus.
I've read this post and I'm not happy with it:
Focus works differently for WPF and Windows Forms, and there were some
rough edges around here that we were unable to fix. If you have focus
inside a WindowsFormsHost and either minimize/restore the form or show
a modal dialog, the focus inside the WindowsFormsHost may be lost –
the WindowsFormsHost still has focus, but the control inside it may
not.
Now what? Relax and be happy?
And the very disapointing is inability to reproduce the problem in other applications.
Can anyone explain what are the reasons of such a strange behavior?
May be offer some workaround.
It is a known bug: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7d41218e-c2bb-4957-b0b4-aa24efc4d8c2/
So far the official word from Microsoft is the issue I've described
above is an acknowledged bug but will not be fixed for .NET 3.5. Also
this issue won't be fixed in the next version the .NET Framework (.NET
4.0).
(by kainhart)
But unfortunately the reference to connect is dead.
To workaround this bug I had to add IsVmFocused property to my ViewModel and also create my FocusHelper.IsFocused attached property which listens for element's IsFocused property change and bound VM's property.
You can see the xaml in this (task related) SO question: What is a Cached acessor in the context of DataBinding?
I have some simple code for popping up a "dialog"-like thing over part of my application window. The idea is, the user must dismiss the dialog before continuing to work with that part of the page.
This works by hovering a large semi-transparent rectangle over the part of the page that is supposed to be disabled - which does a nice enough job of blocking clicks to the region. You see this sort of thing a lot in WPF and Web apps, I think.
The problem I have is, the user can still reach all those juicy blocked controls by tabbing to them using the keyboard. "No problem", I hear you say, "just set the IsEnabled on the panel to false, thereby blocking keyboard access".
Unfortunately, disabling the controls:
Doesn't look very nice
Tends to have unintended consequences with custom styles and bindings further down the tree
So, is there a better way to disable a part of the page, without setting the "IsEnabled" property, such that it doesn't change the visual appearance of any of the controls?
Thanks,
Mark
Can you put your "dialog" XAML in a popup window? Then, call ShowDialog() on the window to make it a modal window? If you don't want your popup to look like a standard window, you could always syle it to remove borders, etc.
I solved this by subscribing to the PreviewGotKeyboardFocus event, from the parent element in the tree, and then handling the event such that focus never gets passed to the children.
Also, I had to explicitly remove focus from the "disabled" controls as well, of course.