【问题标题】:Custom content view with Label-Entry duplicates Xamarin forms带有标签条目的自定义内容视图重复 Xamarin 表单
【发布时间】:2018-11-22 16:21:17
【问题描述】:

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

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

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

只是姓氏的编辑

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

自定义内容视图

<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

【问题讨论】:

    标签: xamarin.forms custom-controls


    【解决方案1】:

    奇怪,但我更改了一行代码,现在可以正常工作了。

    在类变量上将private static Entry newEntry= new Entry();改为 private static Entry newEntry;

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

    newEntry = new Entry { Text = Detail };

    我不确定为什么它采用相同的引用,即使它为每个 LabelledEntrywithIcon 提供了新条目

    【讨论】:

      【解决方案2】:

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

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

      请注意,我有意在 entry 元素内将 ... 作为占位符写为您可能希望在其中进行的所有自定义(字体大小等...)。

      现在添加两个 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 项,尤其是随之而来的错误和错误。

      【讨论】:

      • 谢谢!但是,这会在第二个Labeldetail 的位置创建空白空间,请记住我们只是将其设为Visible="false",但它占用的空间,因此必须删除以获得良好的用户界面。
      • 尝试将“IsEnabled”属性也绑定到 ShowLabel/ShowEntry。如果之后它仍然占用空间,请将 StackLayout 替换为将其行定义设置为自动高度的网格。
      • 我不认为 IsEnabled =false 会删除它,会尝试。我找到了解决方案,将newEntry 转换为non- static 很简单
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-13
      • 1970-01-01
      • 2016-04-06
      • 1970-01-01
      • 2020-11-03
      • 1970-01-01
      相关资源
      最近更新 更多