I have a TextBox
style that formats a number if the box is unfocused, but leaves the number unformatted whlie it\'s being edited.
This is the style I wa
Is there a way I can make this style generic, such as only changing the StringFormat property of the binding in the DataTrigger?
Inherit Style
and new XAML would become this:
<TextBox>
<TextBox.Style>
<local:FlyingStyle Binding="{Binding ElementName=This, Path=SomeValue}" StringFormat="F2" />
</TextBox.Style>
</TextBox>
Here's the class...
public class FlyingStyle : Style
{
public FlyingStyle()
: base(typeof(TextBox))
{ }
string _stringFormat;
public string StringFormat
{
get { return _stringFormat; }
set
{
_stringFormat = value;
CheckInitialize();
}
}
Binding _binding;
public Binding Binding
{
get { return _binding; }
set
{
_binding = value;
CheckInitialize();
}
}
void CheckInitialize()
{
if (StringFormat == null || Binding == null) { return; }// need both
Setters.Add(CreateSetter(Binding, StringFormat));
var trigger = new Trigger
{
Property = UIElement.IsKeyboardFocusWithinProperty,
Value = true,
};
trigger.Setters.Add(CreateSetter(Binding));
Triggers.Add(trigger);
}
/// <summary>Creates the common <see cref="Setter"/>.</summary>
static Setter CreateSetter(Binding binding, string stringFormat = null)
{
// must create a copy, because same binding ref but diff StringFormats
var bindingCopy = new Binding
{
// these could be copies as well
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
ValidatesOnDataErrors = true,
Mode = BindingMode.TwoWay,
Path = binding.Path,
AsyncState = binding.AsyncState,
BindingGroupName = binding.BindingGroupName,
BindsDirectlyToSource = binding.BindsDirectlyToSource,
Converter = binding.Converter,
ConverterCulture = binding.ConverterCulture,
ConverterParameter = binding.ConverterParameter,
ElementName = binding.ElementName,
FallbackValue = binding.FallbackValue,
IsAsync = binding.IsAsync,
NotifyOnSourceUpdated = binding.NotifyOnSourceUpdated,
NotifyOnTargetUpdated = binding.NotifyOnTargetUpdated,
NotifyOnValidationError = binding.NotifyOnValidationError,
//StringFormat = set below...
TargetNullValue = binding.TargetNullValue,
UpdateSourceExceptionFilter = binding.UpdateSourceExceptionFilter,
ValidatesOnExceptions = binding.ValidatesOnExceptions,
XPath = binding.XPath,
//ValidationRules = binding.ValidationRules
};
// mutex ElementName, so modify if needed
// Source = binding.Source,
// RelativeSource = binding.RelativeSource,
if (stringFormat != null)
{
bindingCopy.StringFormat = stringFormat;
}
return new Setter(TextBox.TextProperty, bindingCopy);
}
}
Note that my test was
SomeValue
INPC propertyMy attempt to solve this ended up with a custom control plus a multi-binding, both of which where suggested above.
This allowed me to use markup like this:
< CustomTextBox Value="{Binding Value"} Format="N2" />
I tried to post my code but I keep getting an error about "code that is not properly formatted as code".
I'm wondering if you could maybe have an attached property on the edits to hold the formatted value (just bound to the real edit value with a Stringformat applied), then in your out of focus trigger you could set the edit value to this property.
This would result in a circular binding though when the edit doesn't have focus, dunno how WPF reacts in such situations.
The only option I see there would be to create an attached property for the StringFormat and use a multiBinding.
Not quite what you wanted, but close enough, I guess...
you have more info on this (kind of duplicate) question on S.O.:
Modifying the Parameters of a TextBox's Text Binding through the use of a Style
Sadly this is (to my knowledge) not possible. One possible workaround would be programmatically creating such a style on the fly, that could be encapsulated in a MarkupExtension
which takes the path as constructor parameter.