Issue
I have implemented a partial-view with its own ViewModel so I can use it in different ContentPage
(s). However, this partial view must also have some properties that will be bound to the parent's VM. (and this should be without intervention of any third party libs such as Prism)
here is a sample:
PrtialView
PrtialView.xaml:
<StackLayout x:Class="....OtpVerificator" ...>
<Entry x:Name="Otp1Entry"></Entry>
<Entry x:Name="Otp2Entry"></Entry>
<Entry x:Name="Otp3Entry"></Entry>
<Entry x:Name="Otp4Entry"></Entry>
<Entry x:Name="Otp5Entry"></Entry>
<Entry x:Name="Otp6Entry"></Entry>
</StackLayout>
PrtialView.xaml.cs:
public partial class OtpVerificator : StackLayout
{
//.....
// For example I want also set this property from the parent's view or vVM
public static readonly BindableProperty TokenProperty = BindableProperty.Create(nameof(Token), typeof(string), typeof(OtpVerificator), default(string), Xamarin.Forms.BindingMode.TwoWay);
public string Token
{
get
{
return (string)GetValue(TokenProperty);
}
set
{
SetValue(TokenProperty, value);
}
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == TokenProperty.PropertyName)
{
if (Token != EntriesFullText)
{
for (int i = 0; i < Token.Length; i++)
otpEntries[i].Text = Token.Substring(i, 1);
}
}
//......
}
// .......
private string EntriesFullText
{
get => string.Join(string.Empty, otpEntries
.Where(e => !string.IsNullOrEmpty(e.Text))
.Select(e => e.Text[0]));
}
private void OtpEntry_Changed(object sender, TextChangedEventArgs e)
{
if (Token != EntriesFullText)
Token = EntriesFullText;
var oldVal = e.OldTextValue ?? string.Empty;
var newVal = e.NewTextValue ?? string.Empty;
var entry = sender as BorderlessEntry; // .. and check for null
var index = otpEntries.IndexOf(entry); // what if IndexOf returns -1?
// allow for a single val
if (!string.IsNullOrEmpty(entry.Text) && !string.IsNullOrEmpty(oldVal))
entry.Text = newVal.All(nw => nw.ToString() == oldVal) ? oldVal : entry.Text.Replace(oldVal, string.Empty);
if (string.IsNullOrEmpty(entry.Text))
return;
var nextIndex = index + 1;
if (nextIndex >= otpEntries.Length)
entry.Unfocus();
else
{
var next = otpEntries.ElementAt(nextIndex);
next?.Focus();
}
}
}
ParentView.xaml:
I know that Token
belongs to the embedded VM, Hence I wrote Token2 to explain that it is different property of the PV that should be able to set from the Parent's view or from parent's VM (binding)
<ContentPage x:Class="....ParentPage">
<partials:OtpVerificator x:Name="otpVerifier"
Grid.Row="2"
HorizontalOptions="CenterAndExpand"
ActionType="LoginConfirmation"
Token2="123658">
</partials:OtpVerificator>
</ContentPage>
Solution
Try to give your parentView a name and bind like this :
Token2="{Binding BindingContext.token2 , Source={x:Reference parentView}}"
Here is the example:
<ContentPage x:Class="....ParentPage" x:Name="parentView">
<partials:OtpVerificator x:Name="otpVerifier"
Grid.Row="2"
HorizontalOptions="CenterAndExpand"
ActionType="LoginConfirmation"
Token2="{Binding BindingContext.token2 , Source={x:Reference parentView}}">
</partials:OtpVerificator>
</ContentPage>
Answered By - nevermore
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.