具有 Label-Entry 个重复的 Xamarin 表单的自定义内容视图

Custom content view with Label-Entry duplicates Xamarin forms

我有自定义内容视图,其中 Label 作为标题,另一个 Label 作为详细信息,编辑 Icon ;当单击图标时,详细信息标签将转换为 Entry 以进行更改,并且更改会转移到绑定。

我已将这些自定义视图中的多个绑定到相同 object 的不同属性并尝试编辑每个视图并移动到下一个,问题是它似乎重复了各个视图

我也放了 x:Name 但它仍然复制相同的值到上面的视图..

只是姓氏的编辑

现在,如果我移至第 3 个视图并对其进行编辑,它会将新值复制到所有之前编辑过的值。 - 在这种情况下,对于姓氏,考虑到它在页面中使用的视图不同,并且在调试时它只点击一次该方法,这很奇怪。

自定义内容视图:

<StackLayout Orientation="Horizontal"
                     VerticalOptions="Start"
                     Padding="25,10,25,10">
            <StackLayout x:Name="stackLayoutDetail"
                         HorizontalOptions="FillAndExpand">
                <Label x:Name="title"
                       Text="{Binding Title}" />
                <Label x:Name="detail"
                       Text="{Binding Detail}"
                       FontSize="Large"
                       FontAttributes="Bold" />
            </StackLayout>
            <Image x:Name="editIcon"
                   Source="edit_icon.png"
                   WidthRequest="25"
                   HeightRequest="25"
                   IsVisible="{Binding EditIconVisible}">
                <Image.GestureRecognizers>
                    <TapGestureRecognizer Tapped="EditIcon_Clicked" />
                </Image.GestureRecognizers>
            </Image>
        </StackLayout>

后面的代码:

private static Entry newEntry = new Entry();

public static readonly BindableProperty DetailProperty = BindableProperty.Create(propertyName: nameof(Detail),
                                                                                            returnType: typeof(string),
                                                                                            declaringType: typeof(LabelledEntrywithIcon),
                                                                                            defaultValue: default(string));


        public string Detail
        {
            get
            {
                return (string)GetValue(DetailProperty);

            }
            set => SetValue(DetailProperty, value);
        }

private void EditIcon_Clicked(object sender, System.EventArgs e)
        {
            detailLabel = (Label)stackLayoutDetail.Children[1];
            stackLayoutDetail.Children.RemoveAt(1);
            newEntry.Text = Detail;
            stackLayoutDetail.Children.Add(newEntry);
            editIcon.IsVisible = false;
            newEntry.Completed += NewEntry_Completed;

        }


        private void NewEntry_Completed(object sender, System.EventArgs e)
        {
            try
            {
                var _newText = newEntry.Text;
                detailLabel.Text = _newText;
                stackLayoutDetail.Children.RemoveAt(1);
                stackLayoutDetail.Children.Add(detailLabel);
                Detail = _newText;
                editIcon.IsVisible = true;
            }
            catch (System.Exception ex)
            {

                Debug.WriteLine(ex.Message);
            }
        }

页数

<local:LabelledEntrywithIcon x:Name="firstName"
                                     Title="First Name"
                                     Detail="{Binding Fella.FirstName}" />
        <local:LabelledEntrywithIcon  x:Name="lastname"
                                      Title="Last Name"
                                     Detail="{Binding Fella.LastName}" />
        <local:LabelledEntrywithIcon  x:Name="gender"
                                      Title="Gender"
                                     Detail="{Binding Fella.Gender}" />

后面的代码:

ViewModel=new MainViewModel();
BindingContext = ViewModel;

要测试的完整代码位于 Github 回购:https://github.com/pmahend1/CustomViewDuplicationIssue

奇怪,但我更改了一行代码,现在可以按预期工作了。

在 class 变量上 private static Entry newEntry= new Entry(); 更改为 private static Entry newEntry;

EditIcon_Clicked方法中而不是newEntry.Text = Detail;使用

newEntry = new Entry { Text = Detail };

我不确定为什么它采用相同的引用,即使每个 LabelledEntrywithIcon

都有新条目

您可以通过以下方式简化问题,而不是创建新条目并查找和删除标签并添加新条目:

<StackLayout Orientation="Horizontal"
                 VerticalOptions="Start"
                 Padding="25,10,25,10">
        <StackLayout x:Name="stackLayoutDetail"
                     HorizontalOptions="FillAndExpand">
            <Label x:Name="title"
                   Text="{Binding Title}" />
            <Label x:Name="detail"
                   Text="{Binding Detail}"
                   IsVisible="{Binding ShowLabel}"
                   FontSize="Large"
                   FontAttributes="Bold" />
             <Entry ... IsVisible="{Binding ShowEntry}" ... />
        </StackLayout>
        <Image x:Name="editIcon"
               Source="edit_icon.png"
               WidthRequest="25"
               HeightRequest="25"
               IsVisible="{Binding ShowLabel}">
            <Image.GestureRecognizers>
                <TapGestureRecognizer Tapped="EditIcon_Clicked" />
            </Image.GestureRecognizers>
        </Image>
    </StackLayout>

请注意,我有意在条目元素内写了 ... 作为占位符,用于您可能希望在此处执行的所有自定义设置(字体大小等)。

现在您添加两个 BindablyProperties(类型 bool)ShowEntry 和 ShowLabel,其中 ShowLabel 默认为 true,ShowEntry 默认为 false。 现在您所要做的就是调整您的 EditIcon_Clicked 事件:

    private void EditIcon_Clicked(object sender, System.EventArgs e)
    {
        ShowLabel = false;
        ShowEntry = true;
        newEntry.Text = Detail;
        newEntry.Completed += NewEntry_Completed;

    }

并使NewEntry_Completed适应

    private void NewEntry_Completed(object sender, System.EventArgs e)
    {
        try
        {
            var _newText = newEntry.Text;
            detailLabel.Text = _newText;
            ShowLabel = true;
            ShowEntry = false;
            Detail = _newText;
        }
        catch (System.Exception ex)
        {

            Debug.WriteLine(ex.Message);
        }
    }

基本上这与您的解决方案相同,但是您不必在代码隐藏中推送 UI 项目,尤其是随之而来的错误和错误。