I think it is all bout manually trigerring validation for data template.
For example I have my checklistbox (it is from Xceed wpf extended toolkit, but it doesnt matter. It can be a simple listbox for the sake of example):
<xctk:CheckListBox Name="myCheckListBox" ItemsSource="{Binding Fields}" SelectedValue="{Binding SelectedValue}" Margin="10,10,10,72">
<xctk:CheckListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Width="250" Text="{Binding Field.Symbol}"/>
<Label Content="Value:" Visibility="{Binding SelectedValueVisibility}"/>
<TextBox Name="myTextBox" Width="100" Visibility="{Binding SelectedValueAppVisibility}"
Validation.ErrorTemplate="{StaticResource validationErrorTemplate}" >
<TextBox.Text>
<Binding Path="TextValue" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<my:EmptyTextValidator></my:EmptyTextValidator>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
</DataTemplate>
</xctk:CheckListBox.ItemTemplate>
</xctk:CheckListBox>
I have my EmptyTextValidator class similiar to:
https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-binding-validation
For clarification: "Value: {TextBox}" appears only when an item is checked.
The problem is the same as if it was a simple Listbox and all the textboxes would be visible from the beginning.
What is needed:
Show validation errors on Button_click.
The problem:
Validation works only after you enter something.
When user loads my control and instantly clicks "OK", validation errors are not displayed.
To trigger validation manually I need a "static" textbox:
textBox1.GetBindingExpression(TextBox.TextProperty).UpdateSource();
I am unable to do it with a texbox in template.
This is also the reason why I am unable to do it throught e.g IDataErrorInfo.
You could implement the INotifyDataErrorInfo interface in the class where the TextValue property is defined and raise the ErrorsChanged event whenever you want to invalidate the TextBox. Please refer to the following TechNet article for a sample implementation: https://social.technet.microsoft.com/wiki/contents/articles/19490.wpf-4-5-validating-data-in-using-the-inotifydataerrorinfo-interface.aspx.
So in your Button click event handler, or in your command, you could iterate through the items in your Fields collection and call a method or something of each of these objects that performs the validation and raises the ErrorsChanged. This should cause the Validation.Error template of the invalid TextBox elements in the ListView to be displayed as expected.
Related
What I am trying to do is create a ComboBox where at the top there is a textbox that I can type into to filter the items within the ComboBox. Here is a an example of what I mean:
I need to do this using an MVVM approach. I am not sure how to go about this or how to overwrite the style to do so. I have looked on google for several solutions but none of them are quite exactly what I need. I am pretty sure once I have the style created I can figure out the filtering portion within my view model.
Any help would be appreciated.
Use IsTextSearchEnabled from the ComboBox control like this:
<ComboBox IsTextSearchEnabled="True" IsTextSearchCaseSensitive="True or False depending on your scenario" />
In my projects, when I do something like this, I add a TextBox as the first item in the dropdown content template, with a presenter following it of the items that need to be data-bound.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Path=FilteredText"} Mode="TwoWay"/>
<ListBox ItemSource="{Binding Path=ItemsForBinding}" Mode="TwoWay" NotifyOnSourceUpdated="True" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And in your view-model, make sure that NotifyOnProperyChanged is enabled for the FilteredText property when it is updated, it will trigger the "removal" of the bound-items, I usually use ObservableCollection, but I know ListCollectionView has capabilities to filter and notifies the UI when the collection changes. You can even find a 3rd party text AutoCompleteBox ( I use Telerik,) and it would allow you to prepopulate the terms in the "textbox" that you want the user to be able to filter.
We are currently writing a GUI application using WPF and .Net4.5.
One of our pages contains a TabControl with custom UserControls as TabItems. These UserControls just contain a list of editable TextBoxes. The Textboxes have a custom ValidationRule that validates the text based on a regular expression. The issue is that these editable text boxes are bound to Properties that get loaded at startup with default values from a text file/database.
I need validation to occur before a text box has focus, or before it is edited, to ensure that the values that were entered in the text file/database were entered correctly. Currently, when I select a tab item the text boxes are not displaying the red validation error box, even though it seems validation is running correctly. Only after I click an item with a Validation error do I see the associated red box.
I am using UpdateSourceTrigger="PropertyChanged" and I can debug and see that the validation code is running at the correct time, but still the red boxes will not display. I even added code to re-fire the 'Property changed' events on the bound properties whenever the TabItem gains focus - but this still does not help. Here is an example of one of the TextBoxes that is not showing the validation:
<TextBox x:Name="TextBox1" Margin="10,5,5,5" Width="150" MaxLength="5" Style="{StaticResource ServiceEntryTextBox}">
<TextBox.Text>
<Binding Path="TexBox1BoundProperty" Converter="{StaticResource DoubleConverter}" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<validation:StringRegexFormatValidation RegexPattern="^[0-9]{0,1}.{0,1}[0-9]{1,3}$" ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Is there another piece I am missing?
Can you try placing your TextBox inside an AdornerDecorator? I need to dig out the source for this but I have seen issues before where controls inside a Tab control do not render the validation correctly.
e.g.
<AdornerDecorator>
<TextBox x:Name="TextBox1" Margin="10,5,5,5" Width="150" MaxLength="5" Style="{StaticResource ServiceEntryTextBox}">
<TextBox.Text>
<Binding Path="TexBox1BoundProperty" Converter="{StaticResource DoubleConverter}" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<validation:StringRegexFormatValidation RegexPattern="^[0-9]{0,1}.{0,1}[0-9]{1,3}$" ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</AdornerDecorator>
Further help for debugging
I have also seen issues when binding directly to a DependencyProperty. The issue I saw was I was raising INotifyPropertyChanged in order to trigger the validation to be processed (which worked fine in .NET 4.0) however since .NET 4.5 you cannot use INotifyPropertyChanged for triggering validation on a DependencyProperty.
I have a textbox with the following binding :
<TextBox Binding={Path=MyStr, Mode=TwoWay}>
My problem is that the binding only fires when the textbox loses focus and not for each char the user enters.
The textbox also has an OnTextInput function that fires properly but how do I activate the binding in the code behind?
*I'd rather doing it in a pure mvvm way (not use the window's code behind if possible)
Any answer will be accepted mvvm or not.
Here:
<TextBox Text="{Binding Path=MyStr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
now your bound property will be changed on each character.
U can use the updatesource trigger and set it to property changed
<Binding Source="{StaticResource myDataSource}" Path="Name"
UpdateSourceTrigger="PropertyChanged"/>
The moment it is changed it will sent it's updated value back to your DataContext
on msdn:
http://msdn.microsoft.com/en-us/library/system.windows.data.updatesourcetrigger.aspx
There is a UpdateSourceTrigger Called PropertyChanged, if you use that as your update trigger when you change the text of the textbox it will fire and in your binding property setter you can perform what ever action you need to happen as text changes.
<TextBox Text="{Binding Path=Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
I have a custom component, ExportCommandButton, that has two attached properties. This component is designed to be attached to a button. When clicked, the component would initiate the export method of the grid (Telerik RadGridView). The problem I have is how can I pass the grid to the component via one of the attached properties? I've tried element to element binding, but the GridView set property never fires. How do you bind to a control and not a property of the control?
<Button IsEnabled="{Binding Loaded}"
cmd:ExportCommandButton.GridView="{Binding ElementName=MyGrid}"
cmd:ExportCommandButton.Converter="{StaticResource MyConverter}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="/Assets/xls.png" />
<TextBlock VerticalAlignment="Center" Text="Export" Margin="5,0,0,0" />
</StackPanel>
</Button.Content>
</Button>
Your syntax seems right. The CLR property setter is not called because the binding directly updates the dependency property, without passing by the property which is here for convenience. Use the propertyChangedCallback parameter of your attached property metadata to listen for changes.
I am working with the the WPF Toolkit DataGrid and currently have a problem with committing data back to the source.
My grid is bound to a CLR object list and I have a converter with both the convert and convert back methods implemented.
The two way binding works fine if the user hits Enter in the cells but if they deselect or tab out of the cells the data that was typed is lost.
I have put a break on the CellEditEnding event and both events for Tab and Enter seem identical, but when it gets to the ConvertBack method on my converter the value is empty.
Any help would be much appreciated.
Try changing the UpdateSourceTrigger parameter of your control's Binding to PropertyChanged instead of the default LostFocus.
Eg
<TextBox
Width="75"
VerticalAlignment="Top"
Margin="10"
Text="{Binding
Source={StaticResource data},
Path=Age,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
ValidatesOnExceptions=True}"
Style="{StaticResource textBoxInError}" />