How do I pass changes from source in a TwoWay binding?
I have created a custom TextBox control (but not derived from TextBox) that contains a Dependency Property "Text".
I have added an instance of this and bound it to a property on my view model using a TwoWay binding.
From within my custom TextBox control, how do I update the Text property in such a way that the change is propagated to the property on the view model?
If I set the "Text" property on my custom control, that replaces the binding leaving the property on the view model as null.
I would have thought this would be simple but I can't see how to do it (the standard TextBox control must do it!)
Cheers
Edit:
Custom Control:
public class SampleCustomControl : CustomControl
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
Dependenc开发者_如何学CyProperty.Register("Text", typeof(string), typeof(SampleCustomControl), new PropertyMetadata(null));
public void Update()
{
// This replaces my binding, I want it to pass the new value
// through to the "SomeProperty" two way binding.
Text = "some value";
}
}
Usage:
<Controls:SampleCustomControl Text="{Binding SomeProperty, Mode=TwoWay}" />
You need to add a Property Changed callback in the metadata of your dependency property.
This callback will be fired when the Text property changes (from either side). You can use the value passed in from this to update your custom UI that you've built to display the text.
Update: Responding to your comment about what this is about. Since your example code is too vague to test, here is what I used to test your problem.
public class TestControl : ContentControl
{
private TextBlock _tb;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_tb = new TextBlock();
_tb.Text = Text;
this.Content = _tb;
_tb.MouseLeftButtonDown += new MouseButtonEventHandler(_tb_MouseLeftButtonDown);
}
void _tb_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Update();
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(TestControl), new PropertyMetadata(string.Empty, OnTextChanged));
public void Update()
{
// This replaces my binding, I want it to pass the new value
// through to the "SomeProperty" two way binding.
Text = "some value";
}
public static void OnTextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
((TestControl)sender).UpdateText((string)e.NewValue);
}
protected void UpdateText(string text)
{
if (_tb != null) _tb.Text = text;
}
}
I then bound the Text property on my control to the view model using a two way binding. When I click the text in the view both the view and the viewmodel get updated with the new text "some value". If I update the value in the viewmodel (and raise the property changed event) the value gets updated in the view and the control so the binding is still valid.
There must be some other missing pieces in your example.
As long as your binding property is set to TwoWay and you have exposed the getter and the setter, than the text you enter in the TextBox is sent to the ViewModel. I believe the actual send occurs when you lose focus of that control however, i believe.
精彩评论