Jak użytkownik wybiera wyświetlanie 1 z dwóch (lub więcej) pól na jednej etykiecie w oprogramowaniu Xamarin

Nov 19 2020

Próbuję użyć jednej etykiety, aby wyświetlić na przemian jedno z dwóch pól danych w Xamarin Forms. Tylko etykieta 1 Wyświetlanie pola powiązania (nazwa_kontaktu), podczas gdy druga etykieta, której próbuję użyć zmiennej „DisplayField”, nie wyświetla ani „Contact_Address”, ani „Contact_eMail”. Pytanie wysłane wcześniej i inny użytkownik próbował pomóc, ale to nie zadziałało!

Klasa modelu

public class Contacts
{
  [PrimaryKey][Autoincrement]
  public int Contact_ID { get; set; }
  public string Contact_Name { get; set; }
  public string Contact_Address { get; set; }
  public string Contact_eMail { get; set; }
}

Strona XAML

  <StackLayout>
    <Button Text="Display Address" FontSize="Large" HorizontalOptions="Center" VerticalOptions="Fill" Clicked="Display_Address" />
    <Button Text="Display Email" FontSize="Large" HorizontalOptions="Center" VerticalOptions="Fill" Clicked="Display_eMail" />
    <Entry HorizontalOptions="FillAndExpand" Text="{Binding DisplayField}" />
    <ListView x:Name="listView" HasUnevenRows="True" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell >
                    <StackLayout Orientation="Vertical" VerticalOptions="CenterAndExpand" >
                        <Frame >
                            <StackLayout Orientation="Vertical" VerticalOptions="Center">
                                <Label Text="{Binding Contact_Name}" FontSize="Medium" LineBreakMode="WordWrap" />
                                <Label Text="{Binding DisplayField}" LineBreakMode="WordWrap" />
                            </StackLayout>
                        </Frame>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

Kod za

 public partial class FieldSwap : ContentPage
 {
readonly FieldViewModel _fieldViewModel;
readonly SQLiteAsyncConnection _connection = DependencyService.Get<ISQLite>().GetConnection();
public ObservableCollection<Contacts> CList { get; set; }
public static string DisplayField { get; private set; }

public static int caseSwitch { get; private set; }

public FieldSwap()
{
    InitializeComponent();
    _fieldViewModel = new FieldViewModel();
    _fieldViewModel.Field = "Contact_Address";
    
    this.BindingContext = _fieldViewModel;
}

   public static void SelectField()
   {
    

       switch (caseSwitch)
       {
         case 1:
            DisplayField = "Contact_Address";
            break;

        case 2:
            DisplayField = "Contact_eMail";
            break;

        default:
            DisplayField = ("Contact_Address");
            break;
      }
   }

   private void Display_Address(object sender, EventArgs e)
   {
    caseSwitch = 1;
    SelectField();
    ReadData();
   }

   private void Display_eMail(object sender, EventArgs e)
   {
    caseSwitch = 2;
    SelectField();
    ReadData();
   }

   public void ReadData()
   {
     var list = _connection.Table<Contacts>().ToListAsync().Result;
     CList = new ObservableCollection<Contacts>(list);
     listView.ItemsSource = CList;
   }
}

Wyświetl klasę modelu

 public class FieldViewModel : INotifyPropertyChanged
 {
 public event PropertyChangedEventHandler PropertyChanged;

 String _field;

 public string Field
 {
    set
    {
        if (!value.Equals(_field, StringComparison.Ordinal))
        {
            _field = value;
            OnPropertyChanged("DisplayField");
        }
    }
    get
    {
        return _field;
    }
  }
  void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    PropertyChanged?.Invoke(this, new 
    PropertyChangedEventArgs(propertyName));
  }
 }

Odpowiedzi

JuniorJiang-MSFT Nov 20 2020 at 02:30

IsVisibleAby to osiągnąć, można użyć właściwości, a nie wiązać tylko jednej etykiety.

W związku z tym wiązanie Contact_Addressi Contact_eMaildwie etykiety w StackLayout w następujący sposób:

<StackLayout Orientation="Vertical" VerticalOptions="Center">
     <Label Text="{Binding Contact_Name}" FontSize="Medium" LineBreakMode="WordWrap" />
     <Label Text="{Binding Contact_Address}" IsVisible="{Binding AddressVisible}" LineBreakMode="WordWrap" />
     <Label Text="{Binding Contact_eMail}" IsVisible="{Binding EMailVisible}" LineBreakMode="WordWrap" />
</StackLayout>

Następnie w Kontaktach dodaj dwie widoczne właściwości:

public class Contacts: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    ...

    private bool addressVisible;
    public bool AddressVisible
    {
        set
        {
            if (addressVisible != value)
            {
                addressVisible = value;
                OnPropertyChanged("AddressVisible");
            }
        }
        get
        {
            return addressVisible;
        }
    }

    private bool eMailVisible;
    public bool EMailVisible
    {
        set
        {
            if (eMailVisible != value)
            {
                eMailVisible = value;
                OnPropertyChanged("EMailVisible");
            }
        }
        get
        {
            return eMailVisible;
        }
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

}

Teraz na Contentpage możesz modyfikować widoczną właściwość po kliknięciu przycisku:

private void Display_Address(object sender, EventArgs e)
{
    foreach(var item in CList )
    {
        item.AddressVisible = true;
        item.EMailVisible = false;
    }
}

private void Display_eMail(object sender, EventArgs e)
{
    foreach (var item in CList )
    {
        item.AddressVisible = false;
        item.EMailVisible = true;
    }
}

Oto efekt: