Reputation: 488
I've used a few other MVVMLight bindings on my project and they have worked without problems but now I can't seem to get past this one.
After inflating the Fragment on its OnCreateView I save a bunch of controls that I want to bind to: some are LinearLayouts (who I want to hide based on the VM's property) and some are TextViews which I want to bind strings to.
On my search for a solution for this problem I stumbled upon someone that said that the View might not be inflated as the OnCreateView ends so my reference to that control could be wrong/null/not right. Therefore I moved my setBinding expressions to the OnActivityCreated method to at least "give it a little more time". Also, as per someone suggested, my views are all public properties in the Fragment.
pluginCodeLayoutBinding = this.SetBinding(
() => ViewModel.CreateMode,
() => pluginCodeLayout.Visibility,
BindingMode.OneWay).ConvertSourceToTarget(Converters.BoolToVisibilityReverseConverter);
pluginCodeBinding = this.SetBinding(
() => ViewModel.Script,
() => pluginCode.Text,
BindingMode.OneWay);
These bindings give out the following exceptions:
System.InvalidOperationException: Property not found: Visibility System.InvalidOperationException: Property not found: Text
But when the execution breaks on the exception I'm able to inspect pluginCodeLayout and see that it has the Visibility property with it's default value.
Any help would be appreciated.
Thanks in advance!
Upvotes: 2
Views: 1618
Reputation: 138
The reason the original binding didn't work is that pluginCode is a field not a property. If you look at the Flowers example for Mvvm Light all the controls have properties like this.
private TextView _pluginCode;
public TextView PluginCode
{
get
{
return _pluginCode ?? (_pluginCode = View.FindViewById<TextView>(Resource.Id.plugin_code)); }
}
}
If you do that then you can use bindings like the example uses
this.SetBinding(() => ViewModel.Script, () => PluginCode.Text);
If you don't want to have a property then you can do this
var pluginCode = View.FindViewById<TextView>(Resource.Id.plugin_code);
this.SetBinding(() => ViewModel.Script, pluginCode, () => pluginCode.Text);
Upvotes: 4
Reputation: 471
My team previously faced something similar and there's two things you can change in order for it to work:
SetBinding
directly in your previously fetched UI element (EditText or similar)ViewModelLocator
already in place, which can be accessed from your App.cs)We didn't have the time to dig deeper for a proper explanation (the implementation wasn't correct anw), that being said, the previous points translate to something similar to this in code:
var pluginCode = view.FindViewById<EditText>(Resource.Id.PluginCode);
pluginCode.SetBinding(
() => App.Locator.MyViewModel.SomeStringProperty,
() => pluginCode.Text,
BindingMode.TwoWay);
Don't forget to remove the bindings when you don't need them any more.
Upvotes: 2