Triggering data validation in WPF - wpf

I have a problem in WPF with validation.
I have a user control which has few textboxes, which are binding to datamodel.
The validation is implemented with IDataErrorInfo.
I want the validation to be triggered only when the user press the button "Submit data", so I used UpdateSourceTrigger="Explicit" with the binding of all those text boxes.
Everything working fine, and the validation only triggered when the user push the button, where I update the datasources.
But that user control can be hidden or shown, and when I changed the visibility from display/ to hidden and then back to display, the validation is triggered.
Is there a way to control the validation on that stage?

This is the code that I am using
The binding to the textbox
<TextBox
AutomationProperties.AutomationId="StreetNameTextBoxId"
Height="20" Margin="0,0,5,0" FontSize="12" Name="_streetNameText"
AcceptsReturn="False" AcceptsTab="False" Focusable="True"
Text="{Binding ElementName=_this, Path=SearchParameters.EnteredAddress, UpdateSourceTrigger=Explicit}">
The code that is executing the validation and search (which is associated to click of a button called "Search")
private void ExecuteSearch() {
_streetNameText.UpdateDataSource();
if (ViewModel.CustomerSpecification.IsValid())
PerformActionInBackground(delegate{PerformSearch();});
}

Related

Explicit Binding UpdateSource() Doesn't Work Until Mouse Hovers Over TextBox

So I'm calling the UpdateSource() method on Text property of TextBox in code behind. The ErrorTemplate should come up, but it doesn't until I move my mouse over the TextBox.
Or maybe it does but doesn't get repainted? Any ideas how to fix this to update GUI instantly?
EDIT:
It is PropertyChanged. The problem is not with updating source. The problem is that when source updates, it causes validation and the ErrorTemplate should come up, but it doesn't until I move my mouse over validated TextBox.
EDIT:
Appearently it does update when I move my mouse over some other GUI elements as well (like radio button), which doesn't have anything to do with validation. This is definitely an issue of repainting or binding validation error check trigger. How can I trigger that in code behind?
Binding to Text property of 'TextBox' control is quite specific. UpdateSourceTrigger is set to "LostFocus" by default. It is for improving performance. Try to change it to PropertyChanged.
You may be able to get Validation_Error to fire.
<TextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" x:Name="fieldValue" BorderBrush="SteelBlue" BorderThickness="2" TextWrapping="Wrap"
Text="{Binding Path=DF.FieldValue, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, UpdateSourceTrigger=Explicit}"
Validation.Error="Validataion_Error"
LostFocus="fieldValue_LostFocus" KeyUp="fieldValue_KeyUp"/>
private void Validataion_Error(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
{
MessageBox.Show(e.Error.ErrorContent.ToString(), "Fatal Update Error");
}
}
It may be that since that event is on the TextBox is only fires when the TextBox has focus. You may need to throw a custom event and handle it at the Page/Window.

Saving in a WPF data entry form

I have a WPF MVVM app that contains a data entry form with several text boxes. I noticed that when the user is in a textbox and makes a change that the Context object does not know a change was made until the user tabs out of that text box. Once the user tabs out of the textbox, everything works fine. But I would like to know a change was made without the user having to tab off the textbox.
Is this possible?
The way my form works is that the Save and Cancel buttons bind to ICommands. These commands have a "CanSave" and "CanCancel" method that checks to see if the EntityState changed in anyway but allowing the buttons to enable. This works great but the user has to tab off the textbox to make things work.
How can I make this work without the user tabbing off a changed textbox?
Set the binding direction (Mode) of the TextBox to be TwoWay instead of the default and set the UpdateSourceTrigger to be PropertyChanged instead of default... like so:
<TextBox x:Name="txtPersonLastname" Text="{Binding Person.LastName, Mode=TwoWay, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />
(I have some additional attributes for validation in this excerpt.)
The key difference is the PropertyChanged which will update your backing property in the ViewModel. When the user types anything into the TextBox, that PropertyChanged event will fire, and in turn should trigger your CanSave, Save routines.
In Blend, it should look like this:
You have to chnage the Update Source Trigger Property to refelct the chages in your ViewModel
For Example
<TextBox Text={Binding Path=MyProperty,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}></TextBox>
Dont forget that My Property should fire Property Changed from ViweModel

Embedded ComboBox in Button, but Button steals click event when activating drop down

I have an application with limited screen space, so I'm trying to conserve some real estate by putting a combo box within a button. Its pretty nifty and it looks exactly like what I wanted it to look like. The problem is, every time I click the down arrow on the combo box, the Button also receives a click event. The drop down menu still works properly, but my button has already fired before I've had a chance to actually select what I wanted.
Here is my WPF code that describes my Button and its contents.
<Button FontSize="14" Height="32" HorizontalAlignment="Left" Click="DisableCopierButton_Click">
<StackPanel Orientation="Horizontal">
<Label Content="Disable Copier:" />
<ComboBox Name="DisableCopierComboBox">
<ComboBoxItem Content="1"/>
<ComboBoxItem Content="2"/>
</ComboBox>
</StackPanel>
</Button>
My question is, when I'm clicking on the ComboBox and only the ComboBox, how do I prevent the click event from passing through the button that is underneath it?
I finally found it. I went with the solution provided by Rachel here, even though it was not selected as the answer.
private void EnableCopierButton_Click(object sender, RoutedEventArgs e)
{
if (!(e.OriginalSource is Button))
{
// combo box was clicked, not the button, so get out of here.
return;
}
}
This seems like a SplitButton, yeah. Don't reinvent the wheel. Plenty of implementations on the web.
I recommend WPF Toolkit Extended's.
Rather than making the combo box be part of the button's Content, you may want to try creating a ContentTemplate for the button that includes a combo box.

AutoCompleteBox with TextChanged event not selecting properly

Hi I'm using an AutoCompleteBox like this
<!-- XAML Code -->
<sdk:AutoCompleteBox Grid.Row="2"
FilterMode="None"
ItemsSource="{Binding Customers}"
SelectedItem="{Binding Path=SelectedCustomer, Mode=TwoWay}"
Text="{Binding CustomerSearchString, Mode=TwoWay}"
ValueMemberBinding="{Binding Path=FullName}"
ValueMemberPath="FullName"
TextChanged="{ext:Invoke MethodName=Search, Source={Binding}}"/>
C# part:
// Search Method in the viewmodel
public void Search()
{
var customerOperation = _context.Load(_context.GetCustomerByNameQuery(CustomerSearchString));
customerOperation.Completed += (s, e) => Customers = new List<Customer>(customerOperation.Entities);
}
In my app to quick-search for customers for an fast and uncomplicated method to search. I get it to display everything correctly in the dropdown, and when I select with the mouse it works perfectly.
But when I press ArrowDown, you see the text come up for a split-second but then it reverts and puts the cursor back in the textbox instead of selecting the first entry down. I tried using the TextInput event, but that one won't fire.
How can I avoid this behaviour?
SOLUTION:
The problem was, that the TextChanged event got fired when the user selected an entry, creating some sort of race condition like behaviour where the Text got reset. The solution was to use the KeyUp event (don't use KeyDown, because the Text property won't be updated yet). This event doesn't get triggered when the user selects something, solving the problem.
Final code (ViewModel unchanged):
<!-- XAML Code -->
<sdk:AutoCompleteBox Grid.Row="2"
FilterMode="None"
ItemsSource="{Binding Customers}"
SelectedItem="{Binding Path=SelectedCustomer, Mode=TwoWay}"
Text="{Binding CustomerSearchString, Mode=TwoWay}"
ValueMemberBinding="{Binding Path=FullName}"
ValueMemberPath="FullName"
KeyUp="{ext:Invoke MethodName=Search, Source={Binding}}"/>
Thanks everyone!
Add a handler like this in code:
KeyEventHandler eventHandler = MyAutoCompleteBox_KeyDown;
MyAutoCompleteBox.AddHandler(KeyDownEvent, eventHandler, true);
I'm not understanding why you are using a TextChanged event...? What is that for? If you take that out, does it work? I use an autocomplete box in my project and I don't need a search method... all I do is just supply a list of objects to the autocompletebox and the it searches that list when the user types. I can select either by mouse or by up/down arrows. The only thing that I can think of is that each time you try to use the up/down arrow the text changes and fires off the search function and closes the selection option drop down...

silverlight validation on textbox inside usercontrol

As the title states, I have a usercontrol with a textbox inside. The purpose of the user control is to add a spell check button and character count below the textbox. But for the most part, I'm using it just like a normal textbox:
<controls:SuperTextBox Text="{Binding Accomplishments, Mode=TwoWay, ValidatesOnNotifyDataErrors=True,NotifyOnValidationError=True}"
Height="200" EnableCharacterCounting="True" EnableSpellChecking="True" AcceptsReturn="True"
TextWrapping="Wrap" />
The problem I'm having is that I no longer get the nice red border when validation fails for the field. What do I need to do to reenable that behavior?
What you need to do here, it's to relay the validation of your UserControl back to the textbox.
I did answer a similar question here.

Resources