Hello guys,
I'm struggling to change the Button visibility when the ListView is not empty. I have tried to create an ValueConvertor to return false when my list is empty and true when the list has 1 or more items. The thing is that after the ListView gets 1 or more elements the IsVisible property of the button is not binding anymore. At the start of the application the "Convert" method of the ValueConverter is executed and the button visibility is set to false.
This is my xaml code :
<ContentPage.BindingContext> <viewModels:OrdersPageViewModel/> </ContentPage.BindingContext> <StackLayout> <ListView x:Name="OdersViewList"> ... </ListView> <Button Text="Commit" Clicked="Button_CommitClicked" HorizontalOptions="Center" IsVisible="{Binding OrderListItems, Converter={StaticResource ListIsNull}}"/> </StackLayout>
This is my ViewModel:
public class OrdersPageViewModel : INotifyPropertyChanged { public ObservableCollection<OrderListItem> OrderListItems {get; set;} public event PropertyChangedEventHandler PropertyChanged; public OrdersPageViewModel() { OrderListItems = new ObservableCollection<OrderListItem>(); OrderListItems.CollectionChanged += OrderListItems_CollectionChanged; } void OnPropertyChanged([CallerMemberName] string propertyName = null) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } private void OrderListItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged("OrderListItems"); } }
This is my ValueConverter:
public class ListIsNullConvert : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { ObservableCollection<OrderListItem> list = (ObservableCollection<OrderListItem>)value; if (list.Count == 0) { return false; } return true; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Your code works fine on my side . So you could provide the code about add the items .
In addition , you could implement ti without using ValueConverter
public class ViewModel:INotifyPropertyChanged { public ObservableCollection<productDetails> OrderListItems { get; set; } bool isVisible=false; public bool IsVisible { get { return isVisible; } set { if(isVisible!=value) { isVisible = value; OnPropertyChanged("IsVisible"); } } } public ViewModel() { OrderListItems = new ObservableCollection<productDetails>(); OrderListItems.CollectionChanged += OrderListItems_CollectionChanged; Add(); } async void Add() { //add items after 3s await Task.Delay(3000); OrderListItems.Add(new productDetails()); OrderListItems.Add(new productDetails()); OrderListItems.Add(new productDetails()); OrderListItems.Add(new productDetails()); } public event PropertyChangedEventHandler PropertyChanged; void OnPropertyChanged([CallerMemberName] string propertyName = null) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } private void OrderListItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { IsVisible = OrderListItems.Count == 0 ? false : true; } }
<Button Text="Commit" Clicked="Button_Clicked" HorizontalOptions="Center" IsVisible="{Binding IsVisible}"/>
If you want to set the bindingContext in xaml
<ContentPage.BindingContext> <local:xxxViewModel/> // local here is the namespace of the project. </ContentPage.BindingContext>
Answers
You could try to use a new
and in your
then
Your code works fine on my side . So you could provide the code about add the items .
In addition , you could implement ti without using ValueConverter
in ViewModel
in xaml
I updated my code and now i'm using an
public bool IsButtonVisible
property and in the xaml<Button Text="Commit" IsVisible="{Binding IsButtonVisible}"/>
I also had some problems with thePropertyChanged
event because it was always null so I declared like thispublic event PropertyChangedEventHandler PropertyChanged = delegate {};
. Now the thing is that when the list has 1 or more items the button becomes visible, but when the list count is again 0 and theIsButtonVisible
is set tofalse
, the button remains visible.This is my ViewModel
This is the xml
I use PropertyChanged.Fody to execute INPC
Attached a video
Which of the above posts did you follow, the one from @LucasZhang or the one from @AlessandroCaliaro ?
It looks like @AlessandroCaliaro is using Fody to add PropertyChanged invocation during the build process, whereas @LucasZhang is not assuming use of Fody. Unless you are using Fody, you will need to invoke PropertyChanged explicitly as per the code from @LucasZhang
I made a sample for testing the binding of the Button visibility. Below you can see the whole code. The problem is that the Button is always visible this time, and I can not change its visibility state. The visibility of the second button is changed in the clicked event of the first button.
If I can make this sample test code work I'm sure I can make the other one work.
JohnHardman in response to your question, I'm following both posts but I'm also using the
INotifyPropertyChanged
in my code.ViewModel:
Xaml:
Xaml.cs:
I saw that placing
this.BindingContext = testPageViewModel;
afterInitializeComponent
works, but I don't want to involve the code here I want to set theBindingContext
from the XAML file. Any ideea how I can set theBindingContext
of myTestPage.xml
totestPageViewModel
property of myTestPage.xaml.cs
class ?If you want to set the bindingContext in xaml