data-bindinglabelxamarin.forms.listview

How a user select to display 1 out of two (or more) fields on a single Label in Xamarin


I'm trying to use a single Label to display one of the two data fields alternately in Xamarin Forms. Only Label 1 Displaying the binding field (Contact_Name), while second Label which I am trying to use a variable "DisplayField" is not displaying either 'Contact_Address' or 'Contact_eMail' . Question posted before and Another user tried to help but it didn't work!

Model Class

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 Page

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

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

View Model Class

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

Solution

  • You could use IsVisible property to achieve that, not need to bind only one lable.

    Therefore, binding Contact_Address and Contact_eMail with two lables in StackLayout as follows:

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

    Then in Contacts add two visiable proerty:

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

    Now in Contentpage, you could modify the visiable propery when button be clicked:

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

    Here is the effect:

    enter image description here