I'm looking for a reason why my code isn't doing its job:
In XAML I use:
<TextBox Text="{Binding Path=Txt_8, Converter={StaticResource DefKonverter}, ConverterParameter='UserAlias'}"/>
In C# there are an IValueConverter which giving me a default value when the ConverterParameter='UserAlias'. For ex. the string 'Jettero'. This works well for that point I see in my TextBox the text 'Jettero'.
I saving my record to database, but in the record Txt_8 still NULL ! (Other fields are saved well)
Looks like the Binding not updating the record field behind the TextBox.
=========== Update start
CONCLUSION: This is not working because the Binding working in one direction. The Converter good for showing special things what makes your user experince better but not to save it.
=========== Update end
A similar issue backward happens also, In XAML:
<TextBox Text="{Binding Path=Date_1, Converter={StaticResource DefKonverter}, ConverterParameter='\{0:yyyy-MM-dd\}TimeStamp'}"/>
This working as it should in the record behind: when I write in the TextBox the '.' character it 'translates' to the today's date. After I save the record, it contains the date.
But in the TextBox I still see the written '.'.
In this sit the Binding not updating the TextBox over the record.
=========== Update start
CONCLUSION: This is not working well because the Binding working in one direction. The Converter good for change the data in that shape how you wanna store.
What is still not answered: when I convert '.' into the present date, it is not showing that - now I see the reason. BUT in the Converter if I'm using a Modal window to somehow extend the data what I wrote in (finding a full text for a keyword), that extended information SHOWS UP in my TextBox beside to store of it.
=========== Update end
I don't know what I miss... I checked lot of using of the default and IValueConverter solutions, but this simple sit never came up. Can anyone help?
I think you might be expecting behaviour from a value converter for which it wasn't designed. What is happening is:
On rendering the textbox, the binding reads a value, let's say null, from your property Txt_8, passes that to the converter, which gives it the value to render, in your example 'Jettero'. This means that the visual representation of your null is Jettero. This isn't meant to (and won't) consequently replace your null with 'Jettero' because, according to the binding engine, it has successfully loaded the value from the source and returned it to the target.
The ConvertBack method of the value converter is supposed to cater for the scenario where the value is changed on the UI and needs to be converted back for storage.
Moral of the story: don't use a value converter for specifying a "default" value for the binding. If your property needs a default value, assign it that in your constructor or initializer. If you want your property value to change itself as it is assigned a value, implement it there, instead of in the converter.
For instance, you can define a Date property like this instead of using a converter:
// disclaimer: untested pseudo-code
private DateTime? _dateTimeField;
public string SomeDateProperty
{
get { return _dateTimeField.ToString('dd-MM-yyyy'); }
set
{
if (value == '.')
value = DateTime.Today.ToString();
_dateTimeField = DateTime.Parse(value);
}
}
Related
In a MVVM model, my view uses a value converter. This value converter has a property X that influences the converted value. This property X might change
Whenever X changes, all values that were converted using this value converter need to be updated. Of course My ViewModel does not know that my Views use this converter, so It can't notify PropertyChanged. Besides I think it is not neat to let the ViewModel know in what format values are converted.
My value converter does not know for which values it is used. Luckily my XAML and its code behind class do.
So, my view has two converters as resources, and two text blocks that use these resources:
MyView.XAML:
<UserControl.Resources>
<convert:FormattedStringConverter x:Key="SelectedHistoryConverter" />
<vm:TimeFrameConverter x:Key="TimeFrameConverter"/>
</UserControl.Resources>
...
<TextBlock Height="20" Name="HistoryTime"
Text="{vm:CultureInfoBinding Path=SelectedHistoryTime,
Converter= {StaticResource SelectedHistoryConverter},
ConverterParameter='History Time: {0:G}'}"/>
<TextBlock Height="20" Name="Timeframe"
Text="{vm:CultureInfoBinding Path=Timeframe,
Converter= {StaticResource TimeFrameConverter},
ConverterParameter='Time Frame: [{0:G}, {1:G}]'}"/>
Event handler in MyView.XAML.cs
private void OnMyParameterChanged(object sender, EventArgs e)
{
UpdateConverterParameters(); // updates the changed property in the converters
UpdateTargets(); // forces an Update of all Targets that use these converters
}
In UpdateTargets I need to tell the two TextBlocks to update their values, which will use the changed converters.
For this I used the accepted answer in StackOverflow: How to force a WPF binding to refresh?
public void UpdateTargets()
{
BindingExpression historyTimeExpression = HistoryTime.GetBindingExpression(TextBlock.TextProperty);
historyTimeExpression.UpdateTarget();
BindingExpression timeframeExpression = Timeframe.GetBindingExpression(TextBlock.TextProperty);
timeframeExpression .UpdateTarget();
}
This works fine. However this means that whenever I add an element in XAML that uses this binding I'll have to add this element to UpdateTargets.
Is there a way for a class Derived from Binding to know which Targets are bound to it?
Whenever X changes, all values that were converted using this value converter need to be updated.
In this situation, instead of a converter, perhaps have the VM provide the computed values via on demand properties which the controls will subsequently bind to.
So to somewhat borrow from your example I have three properties, two are computed (which do the job of the converter(s)) and one is the existing one which the computed properties utilize.
Computed
public string HistoryTime { get { return SelectedHistoryTime.AddDays(-2).ToShortDate(); } }
public string Timeframe {
get
{
return $"Time Frame: [{SelectedHistoryTime.AddDays(-14)}, {SelectedHistoryTime.AddDays(+14).ToShortDate()}]";
}
}
Existing Notifies All
Then whenever all corresponding properties which HistoryTime and TimeFrame use, in their setters notify a change such as
public DateTime SelectedHistoryTime
{
get { return _SelectedHistoryTime; }
set
{
_SelectedHistoryTime = value;
NotifyChange("SelectedHistoryTime");
// These rely on this property, so they change too
NotifyChange("HistoryTime");
NotifyChange("Timeframe");
}
}
Within the WPF binding system, it is best to allow the system to respond to notifications directly associated with bound values (properties). It is possible to explicitly refresh bindings, as you've found. But that's an error-prone, inefficient way to approach the problem.
As explained here, the best way to do this is to write an IMultiValueConverter instead. This allows for the source properties to be each be bound via INotifyPropertyChanged events, working smoothly with the binding system just like any other properties you might bind. This way, both the main source property and the "property X" will automatically cause the converter to be invoked, updating the target property as needed if either changes.
It is also possible to write a composite property in your view model, as suggested by the other answer. But it's my preference to declare as much of the view-oriented code as possible, rather than putting imperative implementation in the code-behind. This provides the best flexibility, as well as follows the "separation of concerns" philosophy better (i.e. by isolating the "data conversion" aspect in the converter itself, rather than overloading the view model with that logic).
There are numerous examples of how to implement IMultiValueConverter, here on Stack Overflow, on Microsoft's documentation web site, and of course various tutorials on the web. I trust you'll be able to easily apply what you already know about XAML binding syntax, value converters, etc. to implement your current scenario using IMultiValueConverter.
Let's say I have a ViewModel with a data type of float and implements INotifyPropertyChanged interface.
private float Amount;
And then in my UI:
<TextBox Text="{x:Bind Amount, Mode=TwoWay}" />
What happens is that when I'm trying to type the character . (period), the text cursor goes back to the start and just appears right after two presses of period. What could be causing this behavior?
I have tested the code when UpdateSourceTrigger=PropertyChanged as mentioned in the comments. The problem is that PropertyChanged causes the binding to update immediately after each keystroke. Because of this the behavior is quite upredicatable when the input does not contain a valid float. I have seen three different behaviors so far. Once only one digit is entered and period right after that, the binding sometimes converts it to a decimal:
But sometimes this did not happen and the control just let me enter 3. without any change. The behavior is seems really random. The key is that the value that is set to the backing property is then reflected in the UI by virtue of PropertyChanged event and data binding, which causes the text to change and cursor to jump.
Simply said, the problem here is the fact that the property is a float while the input accepts any string. The solution to your problem could be to use a string property for the binding, like AmountText and then in the setter verify that the text is actually a valid float, parse it and manually set the Amount property. This way you would preserve the "immediate" updating of the value as soon as a valid input is entered while you would also avoid the weird behavior you are seeing.
Also check out the WinRTXamlToolkit and its NumericUpDown control, which might be a better solution for your goal as it provides a natural way for the user to enter numeric values.
I know something like this has been asked before, but I just can't get it to work. I have a masked textbox like this:
<xctk:MaskedTextBox IncludeLiteralsInValue="False" Mask="000-00-0000"
TextWrapping="Wrap" Text="{Binding SomeInteger, UpdateSourceTrigger=PropertyChanged}"/>
And, you guessed it, I need to bind it to an int property but I keep getting a parsing exception because it seems to be trying to store the dashes as well. No matter what I do, the masked text box is storing the mask as well, and I can clearly see that by changing my property to string.The problem is, I'm working with someone else's code, and I'm not allowed to change the model of the application, not even the data types. Can someone help me?Thanks in advance
EDIT: I never figured out the way to do this, so I created another intermediate property that stores the string and updates the int as necessary, and bound that to the textbox.
I have a WPF TextBox that has it's text value bound in XAML. This works fine and, as expected, when the associated value is loaded to the field, it is formatted as desired.
My issue is when the user enters the text field to modify the value, I want to strip away the formatting, and display the raw underlying value.
To do this, I tried to set the BindingExpression.ParentBinding.StringFormat property, on the text boxes binding from within a GotFocus event. However, when I tried to set the StringFormat property to an empty string, I got the following exception:
Binding cannot be changed after it has been used.
So, after a control has been bound to a data model object, is there a straight-forward way that I can modify the string format of the TextBox? I'm willing to change how I format the value of the control, but the end desire is to strip the formatting of the data when it is being edited, and re-instating the string formatting once the user exits the field.
I would probably try it differently. It sounds like you are using the same TextBox for the formatted value and editing the raw value. It would be cleaner to use two different TextBoxes for View and Edit, or package it in a UserControl. Also, I would use two properties, e.g. RawText and FormattedText, and the UserControl would have DependencyProperties with bindings to both properties. The UserControl would automatically switch to the Edit TextBox. The question of "how does the automatic switching" work may be a challenge though. You probably need to use the GotFocus of the View TextBox as you mentioned, although it might not be a bad idea to have an actual Edit button that switches it for you.
I understand about switching to WPF. There is quite a bit of adjustment (aka learning) when switching to WPF. I would think of it as designing a form or control that is "fit for purpose". You don't have to create a new UserControl though. You could do something similar to StackOverflow where there is an Edit TextBox and then the View area, that would be equivalent to the Raw and Formatted values. You would control the Visibility of the Edit TextBox through a BoolToVisibilityConverter when you are in edit mode. Create a public bool IsEditing property on your ViewModel and bind that to the <EditTextBox Visibility="{Binding IsEditing, Converter={StaticResource BoolToVisibilityConverter}}" Text="{Binding RawText}" ...etc... /> After working with WPF for a while, you really appreciate data binding and it makes it hard to go back to plain WinForms (at least for me - not to say there aren't challenges though!).
I am developing a WPF application in which i am using a textbox that is bind to an int field of my POCO entity, when i clear the textbox i want my currentobject to be invalid as this is a non nullable field.
But the thing is when i clear my textbox, it convert to string.empty that can ot be set to an int value, so my int field never gets updated and my object remains Valid.
Kindly suggest some logical solution to this.
One approach is to bind to a string value instead (probably added to a view model if you don't want to pollute your model), and then in the setter for the string property, convert the string to an integer to store on your int property.
As i see it, you should not be able to set an 'empty' value to an int control.
Maybe you could use the IntegerUpDown control in the Extended WPF Toolkit which allows you to provide a watermark to show text in place of a NULL Value or set a default value, which could be 0.
It also has button spinners, which can be hidden if needed.
i copied my answer from here. i hope it helps you too.
if your viewmodel has an Property of type int, then your binding just
works if your view got input which is convertable to int. otherwise
your viewmodel will never be informed. there are 2 ways now:
first: you make sure that your view just can take numeric input (with
your numeric textbox) and the viewmodel property can be int.
or second: your viewmodel property type is typeof string and you use
IDataErrorInfo to let the view know when the input is not numeric.
By default WPF should display the ErrorTemplate when a validation error occurs, and this includes validation errors caused by invalid casts, such as trying to store a string field in an int. The default ErrorTemplate for a TextBox is a red border, and for most users this is an indication that something is incorrect and the changes will not get saved.
If you want something more than that, you could try using an IValueConverter in your binding which attempts to cast the value into a int, and will return 0 (or some invalid value) if it fails so your object will get updated with something no matter what the user enters.