Wie ein Benutzer auswählt, 1 von zwei (oder mehr) Feldern auf einem einzelnen Etikett in Xamarin anzuzeigen

Nov 19 2020

Ich versuche, ein einzelnes Label zu verwenden, um eines der beiden Datenfelder abwechselnd in Xamarin Forms anzuzeigen. Nur Label 1 Zeigt das Bindungsfeld (Contact_Name) an, während das zweite Label, für das ich eine Variable "DisplayField" verwenden möchte, weder 'Contact_Address' noch 'Contact_eMail' anzeigt. Die Frage wurde bereits gestellt und ein anderer Benutzer hat versucht zu helfen, aber es hat nicht funktioniert!

Modellklasse

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

XAML-Seite

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

Code dahinter

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

Modellklasse anzeigen

 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));
  }
 }

Antworten

JuniorJiang-MSFT Nov 20 2020 at 02:30

Sie können die IsVisibleEigenschaft verwenden, um dies zu erreichen, ohne nur ein Etikett binden zu müssen.

Binden Contact_Addressund daher Contact_eMailmit zwei Etiketten in StackLayout wie folgt:

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

Fügen Sie dann in Kontakte zwei sichtbare Eigenschaften hinzu:

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));
    }

}

Jetzt auf der Inhaltsseite können Sie die sichtbare Eigenschaft ändern, wenn Sie auf die Schaltfläche klicken:

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

Hier ist der Effekt: