【问题标题】:Xamarin.Forms: Communication between partial view's VM and Parent's VMXamarin.Forms:部分视图的 VM 和父 VM 之间的通信
【发布时间】:2020-08-28 01:47:57
【问题描述】:

我已经使用自己的 ViewModel 实现了一个局部视图,因此我可以在不同的 ContentPage (s) 中使用它。但是,此部分视图还必须具有一些将绑定到父虚拟机的属性。 (这应该没有任何第三方库的干预,例如 Prism)

这是一个示例:

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:

我知道 Token 属于嵌入式 VM,因此我写了 Token2 来解释它是 PV 的不同属性,应该能够从 Parent 的视图或从 parent 的 VM(绑定)设置

<ContentPage x:Class="....ParentPage">
   <partials:OtpVerificator x:Name="otpVerifier"
                                                 Grid.Row="2"
                                                 HorizontalOptions="CenterAndExpand"
                                                 ActionType="LoginConfirmation"
                                                 Token2="123658">
                        </partials:OtpVerificator>

</ContentPage>

【问题讨论】:

    标签: c# xaml xamarin mvvm xamarin.forms


    【解决方案1】:

    尝试给你的 parentView 一个名称并像这样绑定:

    Token2="{Binding BindingContext.token2 , Source={x:Reference parentView}}"
    

    示例如下:

    <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>
    

    【讨论】:

    • +1,谢谢你的通行证,请问还有什么比这更含蓄的吗?我想要像 Native Views 一样显示的局部视图,以某种方式显示嵌入式 VM 没有任何痕迹?
    • “以某种方式显示嵌入式 VM 没有任何痕迹”是什么意思?
    • 我的意思是像普通绑定方式:Token2="{Binding token}" 也设置 BindingContext 不应该影响嵌入式 VM //这里显式 vm(即不同于嵌入并仅影响 token2 道具
    • 对不起,我不明白。普通绑定不会影响嵌入式 VM。
    • 我希望它显示像这样
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多