Reputation: 171
I feel like I am missing something very obvious. I have a custom control that has a view model with a bunch of fields inside it but the important one for this example is a text value. I can bind to that very easily using the following inside the custom control XAML.
<Label Text="{Binding Text}" />
I want to expose this to anything calling this custom control. Which as far as I am aware requires the use of a bindable property
public static readonly BindableProperty TextProperty = BindableProperty.Create(propertyName: nameof(Text)
, returnType: typeof(string)
, declaringType: typeof(CustomControl));
public string Text
{
get
{
return GetValue(TextProperty).ToString();
}
set
{
SetValue(TextProperty, value);
}
}
Which works. The problem is I don't want to be binding to something in the views code behind when I already have a viewmodel for the view but can see no way of going from a bindable property to a viewmodel field.
I at first tried using the property changed event of the bindable property however this has to be static so it can not access the controls view model/binding context. I tried using the set on the Text field but these do not seem to actually get called. Neither of these worked and it seems inefficient to have a text field in the code behind purely to update a field in the view model
Edit: just to try and explain further, I have a page with a viewmodel
I have a custom control which has xaml bound to a view model
the custom control is used on the page likes so
<ctrl:CustomControl Text="{Binding ControlText}"/>
Currently that will set the Text dependency property and backing field in the custom controls code behind correctly to whatever the Pages viewmodel ControlText is.
Instead I want this to set the Text field on the Custom controls viewmodel and fire the viewmodels property changed event.
so basically it will go PageVM.ControlText --> CustomControlVM.Text
Upvotes: 3
Views: 2478
Reputation: 10958
I make a custom control with bindable property. If you want to perform an action on a BindableProperty change, you need to attach to one of its property change events. You miss the PropertyChanged
event in your code.
MyCustomControl:
<StackLayout>
<Label x:Name="Title" BackgroundColor="Red" TextColor="White" HeightRequest="60" Text="A"/>
<Label BackgroundColor="Green" TextColor="Black" HeightRequest="60" Text="B"></Label>
</StackLayout>
BindableProperty:
private string _text;
public string Text
{
get { return _text; }
set
{
_text = value;
OnPropertyChanged();
}
}
public static readonly BindableProperty TextProperty = BindableProperty.Create(
nameof(Text),
typeof(string),
typeof(MyCustomControl),
string.Empty,
propertyChanged: (bindable, oldValue, newValue) =>
{
var control = bindable as MyCustomControl;
//var changingFrom = oldValue as string;
//var changingTo = newValue as string;
control.Title.Text = newValue.ToString(); //Title is the name of the label which I want to change the Text.
});
ViewModel:
public class ViewModel
{
public string Text { get; set; }
}
My use of custom control: Please do not forget to add the reference of local.
<local1:MyCustomControl Text="{Binding Text}"></local1:MyCustomControl>
Binding:
ViewModel viewModel = new ViewModel();
viewModel.Text = "hello, ";
this.BindingContext = viewModel;
You could download the source file from the MyCustomControl folder on GitHUb for reference. https://github.com/WendyZang/Test.git
Upvotes: 1