<Setter Property="IsChecked">
<Setter.Value>
<MultiBinding>
<!-- Get value for property -->
<Binding Path="IsPressed" RelativeSource="{RelativeSource Self}" Mode="OneWay"/>
<!-- Set value to ViewModel's property -->
<Binding Path="Shift" Mode="OneWayToSource"/>
</MultiBinding>
</Setter.Value>
</Setter>
I need to use 2 bindings for property: one to get value for property and one to set value to ViewModel's property.
How I can realize this scenario?
You can create a couple of attached properties. One will be the target of your binding, and second will contain binding for your proxy. Example:
Then in ProxySource OnChange implementation you will get TextBox as UIElement, there you can read value from ProxySource and write it to ProxyTarget.
This is not a very clean aproach, but it should work.
If you can't get it working, I can write a complete sample later.
Ok, I've implemented everything, here's complete source:
public class ViewModel : ViewModelBase
{
string sourceText;
public string SourceText
{
get { return sourceText; }
set
{
if (sourceText == value) return;
sourceText = value;
System.Diagnostics.Debug.WriteLine("SourceText:" + value);
RaisePropertyChanged("SourceText");
}
}
string targetText;
public string TargetText
{
get { return targetText; }
set
{
if (targetText == value) return;
targetText = value;
System.Diagnostics.Debug.WriteLine("TargetText:" + value);
RaisePropertyChanged("TargetText");
}
}
}
public static class AttachedPropertiesHost
{
public static object GetProxySource(DependencyObject obj)
{
return obj.GetValue(ProxySourceProperty);
}
public static void SetProxySource(DependencyObject obj, object value)
{
obj.SetValue(ProxySourceProperty, value);
}
public static readonly DependencyProperty ProxySourceProperty =
DependencyProperty.RegisterAttached(
"ProxySource", typeof(object), typeof(AttachedPropertiesHost),
new UIPropertyMetadata(null, ProxySourcePropertyPropertyChanged)
);
private static void ProxySourcePropertyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
dependencyObject.Dispatcher.BeginInvoke(
new { Dp = dependencyObject, NewValue = e.NewValue },
args => SetProxyTarget(args.Dp, args.NewValue)
);
}
public static object GetProxyTarget(DependencyObject obj)
{
return obj.GetValue(ProxyTargetProperty);
}
public static void SetProxyTarget(DependencyObject obj, object value)
{
obj.SetValue(ProxyTargetProperty, value);
}
public static readonly DependencyProperty ProxyTargetProperty =
DependencyProperty.RegisterAttached("ProxyTarget", typeof(object), typeof(AttachedPropertiesHost));
}
<TextBox Text="{Binding SourceText, UpdateSourceTrigger=PropertyChanged}"
WpfDataGridLayout:AttachedPropertiesHost.ProxySource="{Binding RelativeSource={RelativeSource Self}, Path=Text, UpdateSourceTrigger=PropertyChanged}"
WpfDataGridLayout:AttachedPropertiesHost.ProxyTarget="{Binding TargetText, Mode=OneWayToSource}"
/>
And the output from console while editing textbox:
SourceText:f
TargetText:f
SourceText:fh
TargetText:fh
SourceText:fhh
TargetText:fhh
Please dont design your solution around IsPressed, thats actually what some call a flash data which means it changes back to a default value (false) sooner. Also contextually Binding will have dedicated target, source and mode. In MultiBinding acheiving one way IsPressed (from a Source) and other way saving back to another Target is not supported. For two way update to occur, all bindings have to be TowWay.
Although a Hack to this could be using MultiConverter having a Target itself as one of the values.
<MultiBinding Converter="MyMultiBindingConverter">
<!-- Get value for property -->
<Binding Path="IsPressed"
RelativeSource="{RelativeSource Self}" Mode="OneWay"/>
<!-- Set value to ViewModel's property -->
<Binding BindsDirectlyToSource="True"/>
</MultiBinding>
MyMultiBindingConverter.Convert()
{
var myViewModel = values[1] as MyViewModel;
var isPressed = bool.Parse(values[0].ToString());
if (isPressed)
{
myViewModel.Shift = !myViewModel.Shift;
}
}
But this is strongly NOT recommended.
Related
I am working on custom control.
I have three dependency property as mentioned below.
Now depending on the control height, width and a range provided by the user, I have to calculate a value and
display it in the custom control.
I am trying to use a multibinding where I can bind all these three values and my multivalue converter will do some calculation on this
and returns me the appropriate value.
The problem is I do not know to bind this value in the styles as multivalue converter binding.
Dependency Properties:
public static readonly DependencyProperty ControlHeightProperty =
DependencyProperty.Register("ControlHeight", typeof(double), typeof
(TestControl), new PropertyMetadata(150D));
public double ControlHeight
{
get { return (double)GetValue(ControlHeightProperty); }
set { SetValue(ControlHeightProperty, value); }
}
public static readonly DependencyProperty ControlWidthProperty =
DependencyProperty.Register("ControlWidth", typeof (double), typeof
(TestControl), new PropertyMetadata(default(double)));
public double ControlWidth
{
get { return (double) GetValue(ControlWidthProperty); }
set { SetValue(ControlWidthProperty, value); }
}
public static readonly DependencyProperty RangeProperty =
DependencyProperty.Register("Range", typeof (double), typeof
(TestControl), new PropertyMetadata(default(double)));
public double Range
{
get { return (double) GetValue(RangeProperty); }
set { SetValue(RangeProperty, value); }
}
Style (I have not written the binding): If the properties are available in the same style than I can do it
using ElementName binding. But in this case atlease may be for height and width it is possible. But Range is a direct dependency property
which I have to bind in my style (I mean there is no way I can do an ElementName binding)
<TextBlock Grid.Row="1">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource
CalculateConverter}">
<Binding Path=""></Binding>
<Binding Path=""></Binding>
<Binding Path=""></Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Can someone help me?
Thanks & Regards,
You can do it using RelativeSource.
<Binding Path="Range" RelativeSource="{RelativeSource AncestorType=UserControl, Mode=FindAncestor}"></Binding>
I am unable to set a property of type TimeSpan from xaml on my dependency object and am looking for if there's a way to get this to work.
Xaml: <local:MyDependencyObject Time="00:00:05"/>
Time is a dependency property of type TimeSpan.
Please tell me how can I set a dependency property of type (TimeSpan) in xaml.
TotalMinutes is a Double, but the D format specifier is only supported for integral types such as Int32. A format string such as {}{0:D1} h {1:D1} min ({2} min) should work.
OR
Try This way :
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0:D2}:{1:D2}">
<Binding Path="MyTime.Hours" />
<Binding Path="MyTime.Minutes" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
I Did it from code Behind.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
MessageBox.Show(IsSpinning.ToString());
}
public static readonly DependencyProperty IsSpinningProperty =
DependencyProperty.Register(
"IsSpinning", typeof(TimeSpan),
typeof(TimeSpan), null
);
public TimeSpan IsSpinning
{
get { return (TimeSpan)GetValue(IsSpinningProperty); }
set { SetValue(IsSpinningProperty, value); }
}
}
I'm using the Delay binding tag of .Net 4.5 but I want to change the textbox's background color while the changes are not "committed". How can I set an IsDirty property to true while the delay is happening?
I tried using the TextChanged event to set an IsDirty flag and then remove the flag when the bound property got set. The problem is that the TextChanged fires whenever the bound property changes and not just when the user modifies the text.
I got it "working" in a very clunky and fragile way by monitoring the TextChanged event and the bound property. Needless to say this is very prone to bugs so I would like a cleaner solution. Is there any way to know that the textbox has been changed but not committed yet (by the Delay)?
I had a look through the source code and the BindingExpressionBase itself is aware of this through a property called NeedsUpdate. But this property is internal so you would have to use reflection to get it.
However, you won't be able to monitor this property in any easy way. So the way I see it, you would need to use both of the events TextChanged and SourceUpdated to know when NeedsUpdate might have changed.
Update
I created an attached behavior that does this, it can be used to monitor pending updates on any DependencyProperty. Note that NotifyOnSourceUpdated must be set to true.
Uploaded a small sample project here: PendingUpdateExample.zip
Example
<TextBox Text="{Binding ElementName=textBoxSource,
Path=Text,
NotifyOnSourceUpdated=True,
UpdateSourceTrigger=PropertyChanged,
Delay=1000}"
ab:UpdatePendingBehavior.MonitorPendingUpdates="{x:Static TextBox.TextProperty}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="ab:UpdatePendingBehavior.HasPendingUpdates"
Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
UpdatePendingBehavior
public class UpdatePendingBehavior
{
#region MonitorPendingUpdates
public static DependencyProperty MonitorPendingUpdatesProperty =
DependencyProperty.RegisterAttached("MonitorPendingUpdates",
typeof(DependencyProperty),
typeof(UpdatePendingBehavior),
new UIPropertyMetadata(null, MonitorPendingUpdatesChanged));
public static DependencyProperty GetMonitorPendingUpdates(FrameworkElement obj)
{
return (DependencyProperty)obj.GetValue(MonitorPendingUpdatesProperty);
}
public static void SetMonitorPendingUpdates(FrameworkElement obj, DependencyProperty value)
{
obj.SetValue(MonitorPendingUpdatesProperty, value);
}
public static void MonitorPendingUpdatesChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
DependencyProperty property = e.NewValue as DependencyProperty;
if (property != null)
{
FrameworkElement element = target as FrameworkElement;
element.SourceUpdated += elementProperty_SourceUpdated;
if (element.IsLoaded == true)
{
SubscribeToChanges(element, property);
}
element.Loaded += delegate { SubscribeToChanges(element, property); };
element.Unloaded += delegate { UnsubscribeToChanges(element, property); };
}
}
private static void SubscribeToChanges(FrameworkElement element, DependencyProperty property)
{
DependencyPropertyDescriptor propertyDescriptor =
DependencyPropertyDescriptor.FromProperty(property, element.GetType());
propertyDescriptor.AddValueChanged(element, elementProperty_TargetUpdated);
}
private static void UnsubscribeToChanges(FrameworkElement element, DependencyProperty property)
{
DependencyPropertyDescriptor propertyDescriptor =
DependencyPropertyDescriptor.FromProperty(property, element.GetType());
propertyDescriptor.RemoveValueChanged(element, elementProperty_TargetUpdated);
}
private static void elementProperty_TargetUpdated(object sender, EventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
UpdatePendingChanges(element);
}
private static void elementProperty_SourceUpdated(object sender, DataTransferEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (e.Property == GetMonitorPendingUpdates(element))
{
UpdatePendingChanges(element);
}
}
private static void UpdatePendingChanges(FrameworkElement element)
{
BindingExpressionBase beb = BindingOperations.GetBindingExpressionBase(element, GetMonitorPendingUpdates(element));
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
PropertyInfo needsUpdateProperty = beb.GetType().GetProperty("NeedsUpdate", bindingFlags);
SetHasPendingUpdates(element, (bool)needsUpdateProperty.GetValue(beb));
}
#endregion // MonitorPendingUpdates
#region HasPendingUpdates
public static DependencyProperty HasPendingUpdatesProperty =
DependencyProperty.RegisterAttached("HasPendingUpdates",
typeof(bool),
typeof(UpdatePendingBehavior),
new UIPropertyMetadata(false));
public static bool GetHasPendingUpdates(FrameworkElement obj)
{
return (bool)obj.GetValue(HasPendingUpdatesProperty);
}
public static void SetHasPendingUpdates(FrameworkElement obj, bool value)
{
obj.SetValue(HasPendingUpdatesProperty, value);
}
#endregion // HasPendingUpdates
}
Another way could be to use a MultiBinding that binds both to the source and the target and compares their values in a converter. Then you could change the Background in the Style. This assumes that you don't convert the value. Example with two TextBoxes
<TextBox Text="{Binding ElementName=textBoxSource,
Path=Text,
UpdateSourceTrigger=PropertyChanged,
Delay=2000}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Value="False">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource IsTextEqualConverter}">
<Binding RelativeSource="{RelativeSource Self}"
Path="Text"/>
<Binding ElementName="textBoxSource" Path="Text"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBox Name="textBoxSource"/>
IsTextEqualConverter
public class IsTextEqualConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values[0].ToString() == values[1].ToString();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
You could try some other event like PreviewTextInput or one of the key related ones. (You probably need the tunneling versions as bubbling events are probably handled internally)
I'm not sure about the Delay binding. However, in .Net 4.0 I'd use a BindingGroup. BindingGroup has a CanRestoreValues property which will report exactly what you want: If the UpdateSourceTrigger is Explicit (which is default if there is a BindingGroup), CanRestoreValues will be true from the time one bound control value has been changed until BindingGroup.CommitEdit is called and the values are forwarded to the bound object. However, CanRestoreValues will be true as soon as any control that shares the BindingGroup has a pending value, so if you want feedback for each separate property you will have to use one BindingGroup per control, which makes calling CommitEdit a little bit less convenient.
Suppose you have a class inheriting from ValidationRule:
public class MyValidationRule : ValidationRule
{
public string ValidationType { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo) {}
}
In XAML you are validating like this:
<ComboBox.SelectedItem>
<Binding Path="MyPath" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
<Binding.ValidationRules>
<qmvalidation:MyValidationRule ValidationType="notnull"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
Which works and everything is ok.
But suppose now, you want to have ValidationType="{Binding MyBinding}" where MyBinding comes from DataContext.
For this purpose I would need to make MyValidationRule as a DependencyObject and add a Dependency Property.
I've tried to write a class that is DependencyObject, and bind it. There are 2 problems though.. the ValidationRule DOES NOT have the DataContext from the Combobox / Item.
Do you have any ideas, on how to solve that?
Since ValidationRule does not inherit from DependencyObject you cannot create a DependecyProperty in your custom validation class.
However as explained in this link you can have a normal property in your validation class which is of a type that inherits from DependecyObject and create a DependencyProperty in that class.
For example here is a custom ValidationRule class that support bindable property:
[ContentProperty("ComparisonValue")]
public class GreaterThanValidationRule : ValidationRule
{
public ComparisonValue ComparisonValue { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
string s = value?.ToString();
int number;
if (!Int32.TryParse(s, out number))
{
return new ValidationResult(false, "Not a valid entry");
}
if (number <= ComparisonValue.Value)
{
return new ValidationResult(false, $"Number should be greater than {ComparisonValue}");
}
return ValidationResult.ValidResult;
}
}
ComparisonValue is a simple class that inherits from DependencyObject and has a DependencyProperty:
public class ComparisonValue : DependencyObject
{
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
nameof(Value),
typeof(int),
typeof(ComparisonValue),
new PropertyMetadata(default(int));
This solves the original problem but unfortunately brings two more problems:
The binding does not work correctly since the ValidationRules is not part of visual tree and therefore cannot get the bound property correctly. For example this naive approach will not work:
<TextBox Name="TextBoxToValidate">
<TextBox.Text>
<Binding Path="ViewModelProperty" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<numbers:GreaterThanValidationRule>
<numbers:ComparisonValue Value="{Binding Text, ElementName=TextBoxToValidate}"/>
</numbers:GreaterThanValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Instead a proxy object should be used as explained in this answer:
<TextBox Name="TextBoxToValidate">
<TextBox.Resources>
<bindingExtensions:BindingProxy x:Key="TargetProxy" Data="{Binding Path=Text, ElementName=TextBoxToValidate}"/>
</TextBox.Resources>
<TextBox.Text>
<Binding Path="ViewModelProperty" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<numbers:GreaterThanValidationRule>
<numbers:ComparisonValue Value="{Binding Data, Source={StaticResource TargetProxy}}"/>
</numbers:GreaterThanValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
BindingProxy is a simple class:
public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object Data
{
get { return GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty = DependencyProperty.Register(nameof(Data), typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}
If the property in custom ValidationRule is bound to another object's property, the validation logic for the original property will not fire when that other object's property changes.
To solve this problem we should update the binding when the ValidationRule's bound property is updated. First we should bind that property to our ComparisonValue class. Then, we can update the source of the binding when the Value property changes:
public class ComparisonValue : DependencyObject
{
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
nameof(Value),
typeof(int),
typeof(ComparisonValue),
new PropertyMetadata(default(int), OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ComparisonValue comparisonValue = (ComparisonValue) d;
BindingExpressionBase bindingExpressionBase = BindingOperations.GetBindingExpressionBase(comparisonValue, BindingToTriggerProperty);
bindingExpressionBase?.UpdateSource();
}
public object BindingToTrigger
{
get { return GetValue(BindingToTriggerProperty); }
set { SetValue(BindingToTriggerProperty, value); }
}
public static readonly DependencyProperty BindingToTriggerProperty = DependencyProperty.Register(
nameof(BindingToTrigger),
typeof(object),
typeof(ComparisonValue),
new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
}
The same proxy problem in the first case also exists here. Therefore we should create another proxy object:
<ItemsControl Name="SomeCollection" ItemsSource="{Binding ViewModelCollectionSource}"/>
<TextBox Name="TextBoxToValidate">
<TextBox.Resources>
<bindingExtensions:BindingProxy x:Key="TargetProxy" Data="{Binding Path=Items.Count, ElementName=SomeCollection}"/>
<bindingExtensions:BindingProxy x:Key="SourceProxy" Data="{Binding Path=Text, ElementName=TextBoxToValidate, Mode=TwoWay}"/>
</TextBox.Resources>
<TextBox.Text>
<Binding Path="ViewModelProperty" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<numbers:GreaterThanValidationRule>
<numbers:ComparisonValue Value="{Binding Data, Source={StaticResource TargetProxy}}" BindingToTrigger="{Binding Data, Source={StaticResource SourceProxy}}"/>
</numbers:GreaterThanValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
In this case the Text property of TextBoxToValidate is validated against the Items.Count property of SomeCollection. When the number of items in the list changes, the validation for the Text property will be triggered.
I want to set the UpdateSourceTrigger to an event of a control:
<TextBox Text="{Binding Field, UpdateSourceMode=btnOK.Click}">
<Button Name="btnOK">
<Button.Triggers>
<Trigger>
<!-- Update source -->
</Trigger>
</Button.Triggers>
</Button>
I thought about two ways:
Set UpdateSourceMode or some other stuff in the binding.
Set an EventTrigger that updates source on button click.
Possible, or I have to do it with code?
You'll have to use code. Specifically:
Set UpdateSourceTrigger=Explicit on the TextBox.
Call UpdateSource when the user clicks the Button.
However, you can put the code in the code behind or in an attached behavior.
I know it's been a while, but I came across the same issue and want to share my solution. Hope it will be helpful for somebody.
public class UpdateSourceBehavior : Behavior<System.Windows.Interactivity.TriggerBase>
{
internal const string TargetElementPropertyLabel = "TargetElement";
static UpdateSourceBehavior()
{
TargetElementProperty = DependencyProperty.Register
(
TargetElementPropertyLabel,
typeof(FrameworkElement),
typeof(UpdateSourceBehavior),
new PropertyMetadata(null)
);
}
public static readonly DependencyProperty TargetElementProperty;
[Bindable(true)]
public FrameworkElement TargetElement
{
get { return (FrameworkElement)base.GetValue(TargetElementProperty); }
set { base.SetValue(TargetElementProperty, value); }
}
public PropertyPath TargetProperty { get; set; }
protected override void OnAttached()
{
base.OnAttached();
this.InitializeMembers();
base.AssociatedObject.PreviewInvoke += this.AssociatedObject_PreviewInvoke;
}
protected override void OnDetaching()
{
base.AssociatedObject.PreviewInvoke -= this.AssociatedObject_PreviewInvoke;
base.OnDetaching();
}
private void AssociatedObject_PreviewInvoke(object sender, PreviewInvokeEventArgs e)
{
this.m_bindingExpression.UpdateSource();
}
private void InitializeMembers()
{
if (this.TargetElement != null)
{
var targetType = this.TargetElement.GetType();
var fieldInfo = targetType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.FirstOrDefault(fi => fi.Name == this.TargetProperty.Path + "Property");
if (fieldInfo != null)
this.m_bindingExpression = this.TargetElement.GetBindingExpression((DependencyProperty)fieldInfo.GetValue(null));
else
throw new ArgumentException(string.Format("{0} doesn't contain a DependencyProperty named {1}.", targetType, this.TargetProperty.Path));
}
else
throw new InvalidOperationException("TargetElement must be assigned to in order to resolve the TargetProperty.");
}
private BindingExpression m_bindingExpression;
}
Here is my solution:
XAML:
<StackPanel>
<i:Interaction.Triggers>
<i:EventTrigger SourceName="submit" EventName="Click">
<behaviours:TextBoxUpdateSourceAction TargetName="searchBox"></behaviours:TextBoxUpdateSourceAction>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBox x:Name="searchBox">
<TextBox.Text>
<Binding Path="SomeProperty" UpdateSourceTrigger="Explicit" NotifyOnValidationError="True">
<Binding.ValidationRules>
<DataErrorValidationRule ValidatesOnTargetUpdated="False"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button x:Name="submit"></Button>
</StackPanel>
Behaviour definition (inherited from TargetedTriggerAction):
public class TextBoxUpdateSourceAction : TargetedTriggerAction<TextBox>
{
protected override void Invoke(object parameter)
{
BindingExpression be = Target.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
}
}
Please note that it's important to attach TextBoxUpdateSourceAction to parent container (StackPanel in example code).