This is my first effort with MVVM. I'm getting an InvalidOperationException and I just hope it is something simple. Here is the full error message
InvalidOperationException: A TwoWay or OneWayToSource binding cannot work on the read-only property 'AddText' of type 'myMVVM_1.ViewModel.DoTextAppend'.
In my test app I have a usercontrol the contains a button and two textboxes. I will enter some text into the first textbox and then click the button. This should display the text content of textbox1 inside of textbox2 with some additional text appended to it. Below is my code behind and the xaml. I placed the model code in a Model folder and the ViewModel code in a ViewModel folder. The app compiles, and if I don't wire the code behind to the xaml -- the app will run, but when I try to wire up the code behind -- I get the invalid markup message and the InvalidOperationException. I hope someone could find the error and suggest how I could fix it. I did notice that if I remove
Text="{Binding AddText}"
from the 2nd textbox in the Usercontrol -- then the app runs, but when I type some text in textbox1 and then click the button -- nothing happens. When I click the button -- the idea is that the text in textbox1 will appear in Textbox2 and some default text appended to it.
Model
using System; namespace myMVVM_1.Model { class appendString { public Func<string, string> _strAppend; public appendString() { _strAppend = appendText; } public string appendText(string inputText) { return inputText + " yyyyyy "; } } }
ViewModel
using System; using System.ComponentModel; using System.Windows.Input; using myMVVM_1.Model; namespace myMVVM_1.ViewModel { public class DoTextAppend : myObservableObject { appendString ap = new appendString(); Func<string, string> appender; private string _addText; public DoTextAppend() { appender = ap.appendText; } private string _someText; public string prpSomeText { get { return _someText; } set { _someText = value; RaisePropertyChangedEvent("xxxxx"); } } public string AddText { get { return _addText; } } public ICommand textAppendCommand { get { return new myDelegateCommand(textAppend); } } private void textAppend() { _addText = appender(prpSomeText); prpSomeText = String.Empty; } } public class myObservableObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChangedEvent(string propName) { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propName)); } } public class myDelegateCommand : ICommand { private Action _action; public myDelegateCommand(Action action) { _action = action; } public void Execute(object parameter) { _action(); } public bool CanExecute(object parameter) { return true; } #pragma warning disable 67 public event EventHandler CanExecuteChanged { add { } remove { } } #pragma warning restore 67 } }
MainWindow xaml
<Window x:Class="myMVVM_1.View.mainView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:uc="clr-namespace:myMVVM_1.View" xmlns:vModel="clr-namespace:myMVVM_1.ViewModel" Title="mainView" Height="350" Width="525"><Window.DataContext><vModel:DoTextAppend/></Window.DataContext><Grid><uc:UserControl1 /></Grid></Window>
UserControl1 xaml
<UserControl x:Class="myMVVM_1.View.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:vucModel="clr-namespace:myMVVM_1.ViewModel" mc:Ignorable="d" d:DesignHeight="350" d:DesignWidth="525" d:DataContext="{d:DesignInstance vucModel:DoTextAppend}"><UserControl.InputBindings><KeyBinding Key="Enter" Command="{Binding textAppendCommand}"/></UserControl.InputBindings><StackPanel><Button Command="{Binding textAppendCommand}" Content="Button" HorizontalAlignment="Left" Height="25" Margin="29,22,0,0" Width="88" /><TextBox Text="{Binding prpSomeText, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Height="20" Margin="29,69,0,0" Width="200"/><TextBox Text="{Binding AddText}" HorizontalAlignment="Left" Height="20" Margin="29,110,0,0" Width="200"/></StackPanel></UserControl>
Thanks in advance for any suggestions
Rich P