In XAML, I have a TextBox with x:Name of MyTextBox
.
<TextBox x:Name="MyTextBox">Some text</TextBox>
For speed reasons, I want to call the method .AppendText
, e.g. In C# code behind, I would call MyTextBox.AppendText("...")
However, this is not very MVVM like. If I want to make a call to a function on a control using binding to my ViewModel, what is an elegant way to achieve this?
I'm using MVVM Light.
Update
I would use the answer from @XAML Lover if I wanted a simple, quick solution. This answer uses a Blend Behavior which is less C# coding.
I would use the answer from @Chris Eelmaa if I wanted write a reusable Dependency Property which I could apply to any TextBox in the future. This example is based on a Dependency Property which, while slightly more complex, is very powerful and reusable once it is written. As it plugs into the native type, there is also slightly less XAML to use it.
Basically when you call a method from a control, it is obvious that you are doing some UI related logic. And that should not sit in ViewModel. But in some exceptional case, I would suggest to create a behavior. Create a Behavior and define a DependencyProperty of type Action<string> since AppendText should take string as a parameter.
In the OnAttached method, I have assigned the extension method that I have created on TextBlock to the DP of Behavior. Now we can attach this behavior to a TextBlock in View.
Consider we have a property in ViewModel with same signature. And that property is the source of this binding. Then we can invoke that Action anytime, which will automatically invoke our extension method on TextBlock. Here I am invoking the method on a button click. Remember in this case, our Behavior acts like an Adapter between View and ViewModel.
Seems like a reasonable request to me.
AppendText
is definitely very fast, as it deals with pointers. Pretty much every answer in MVVM world be either subclassing, or attached properties.You can create new interface, call it
ITextBuffer
:This will be used throughout the viewmodels. All you have to do now, is write an attached property that takes advance of such interface, when you do bindings.
Something like this:
The idea here is to wrap
StringBuilder
into an interface (as it raises no events by default :) which can then be exploited by an attached property &TextBox
actual implementation.In your viewmodel, you'd probably want something like this:
and in the view: