0
votes

Problem description: In my Silverlight application (4.0), I have a TextBox control, which background is bound to some source property. I created a behavior for TextBox control. Inside my behavior, I want to take that binding, and "redirect" to other target (lets say, to the behavior itself). In other words, when the source property of background binding is changed, instead of updating property on TextBox control, I want to update some another target property. How to do that? I tried reflection, but it not allowed in SL on private fields...

Thanks in advance.

2

2 Answers

1
votes

You can get the existing Binding using FrameworkElement.GetBindingExpression. Here's a sample:

FrameworkElement yourControl = null; // the code to get the control goes here
BindingExpression bindingExpression =
    yourControl.GetBindingExpression(TextBox.Background);
Binding binding = bindingExpression.ParentBinding; // it's your binding

Then, create a new Binding object, setup its properties (change target if required) and use SetBinding to attach it.

UPDATE

Now about the binding source.

Note that Source property will be non-null only if you set this property explicitly.

Other options for the Binding source include:

  1. specific element: used if Binding.ElementName property is set
  2. templated control: used if Binding.RelativeSource is set to a RelativeSource with Mode=RelativeSourceMode.TemplatedParent
  3. binding target control: used if Binding.RelativeSource is set to a RelativeSource with Mode=RelativeSourceMode.TemplatedParent
  4. DataContext: if neither Source, nor the previous 3 options apply.

If you want to clone a Binding, you should check all these options.

However, if you just need the data item, you'd better use BindingExpression.DataItem property, which should return the actual data item that is the binding source.

0
votes

I'm not sure why you would want to "redirect". Is it still ok if the text in the textbox changes? If you're trying to do binding to another element on the screen, you can use Element binding that would occur after the tb1 textbox loses focus:

<StackPanel>
<TextBox x:Name="tb1" />
<TextBox Text="{Binding ElementName=tb1, Source=Text}" />
</StackPanel>

In a behavior, you can us the TextChanged event and capture it there.

public class TextBoxBehavior : Behavior<TextBox>
{
/// <summary>
/// Called after the Behavior is attached to an AssociatedObject.
/// </summary>
/// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);
}

/// <summary>
/// Called after the Behavior is detached from an AssociatedObject.
/// </summary>
/// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.TextChanged -= new TextChangedEventHandler(AssociatedObject_TextChanged);
}

void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
{
if(!string.IsNullOrEmpty(this.AssociatedObject.Text))
{
 string enteredValue = this.AssociatedObject.Text;
// do what you want with the entered value
}

// if you want to reset it.. this.AssociatedObject.Text = string.Empty;
}
}