web-dev-qa-db-fra.com

Liste de mise à jour des formulaires XamarinAfficher l'élémentSource

Ok j'ai un objet ListView qui a un List<Filiale> as ItemSource et j'aimerais actualiser le ItemSource chaque fois que la liste des objets change. Le ListView a un ItemTemplate personnalisé Pour l'instant je l'ai fait:

public NearMe ()
{
    list=jM.ReadData ();
    listView.ItemsSource = list;
    listView.ItemTemplate = new DataTemplate(typeof(FilialeCell));
    searchBar = new SearchBar {
        Placeholder="Search"
    };
    searchBar.TextChanged += (sender, e) => {
        TextChanged(searchBar.Text);
    };
    var stack = new StackLayout { Spacing = 0 };
    stack.Children.Add (searchBar);
    stack.Children.Add (listView);
    Content = stack;
}

public void TextChanged(String text){
        //DOSOMETHING
        list=newList;
}

Comme vous pouvez le voir dans la méthode TextChanged, j'attribue une nouvelle liste à la précédente mais il n'y a aucun changement dans la vue. Dans le ViewCell que j'ai créé, j'affecte le champ Texte des étiquettes avec le SetBinding

10
Davide Quaglio

Ok voici comment j'ai résolu le problème, tout d'abord j'ai créé un "wrapper" qui implémente INotifyPropertyChanged pour la liste que je prenais comme ItemSource comme ceci:

public class Wrapper : INotifyPropertyChanged
    {
        List<Filiale> list;
        JsonManager jM = new JsonManager ();//retrieve the list

        public event PropertyChangedEventHandler PropertyChanged;
        public NearMeViewModel ()
        {
            list = (jM.ReadData ()).OrderBy (x => x.distanza).ToList();//initialize the list
        }

        public List<Filiale> List{ //Property that will be used to get and set the item
            get{ return list; }

            set{ 
                list = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, 
                        new PropertyChangedEventArgs("List"));// Throw!!
                }
            }
        }

        public void Reinitialize(){ // mymethod
            List = (jM.ReadData ()).OrderBy (x => x.distanza).ToList();
        }

Puis dans la classe NearMe:

Wrapper nearMeVM = new Wrapper();
public NearMe ()
        {

            Binding myBinding = new Binding("List");
            myBinding.Source = nearMeVM;
            myBinding.Path ="List";
            myBinding.Mode = BindingMode.TwoWay;
            listView.SetBinding (ListView.ItemsSourceProperty, myBinding); 
            listView.ItemTemplate = new DataTemplate(typeof(FilialeCell));
            searchBar = new SearchBar {
                Placeholder="Search"
            };
            searchBar.TextChanged += (sender, e) => {
                TextChanged(searchBar.Text);
            };
            var stack = new StackLayout { Spacing = 0 };
            stack.Children.Add (searchBar);
            stack.Children.Add (listView);
            Content = stack;
        }
public void TextChanged(String text){
            if (!String.IsNullOrEmpty (text)) {
                text = text [0].ToString ().ToUpper () + text.Substring (1);
                var filterSedi = nearMeVM.List.Where (filiale => filiale.nome.Contains (text));
                var newList = filterSedi.ToList ();
                nearMeVM.List = newList.OrderBy (x => x.distanza).ToList ();
            } else {
                nearMeVM.Reinitialize ();
            }
6
Davide Quaglio

Vous pouvez définir la ItemsSource de ListView sur null, puis le définir à nouveau, qui effectue un rechargement de table. http://forums.xamarin.com/discussion/18868/tableview-reloaddata-equivalent-for-listview

15
danfordham

Vous pouvez définir un modèle de vue de base et l'hériter de INotifyPropertyChanged

public abstract class BaseViewModel : INotifyPropertyChanged
    {
        protected bool ChangeAndNotify<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
        {
            if (!EqualityComparer<T>.Default.Equals(property, value))
            {
                property = value;
                NotifyPropertyChanged(propertyName);
                return true;
            }


            return false;
        }


        protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

puis dans votre viewmodel (Ex. JM) sera hérité de BaseViewModel et peut créer ObservableCollection<YOURLISTCLASS> Liste

Vos champs dans ViewModel (Ex. JM) doivent également implémenter comme suit:

public const string FirstNamePropertyName = "FirstName";
private string firstName = string.Empty;
public string FirstName 
{
    get { return firstName; }
    set { this.ChangeAndNotify(ref this.firstName, value, FirstNamePropertyName); }
} 

J'espère que cela t'aides.

2
SoftSan

Remplacez List par ObservableCollection et implémentez INotifyPropertyChanged pour que les modifications soient reflétées dans votre ListView.

1
Martijn00

Voici mon implémentation actuelle de ce modèle extrait d'une application sur laquelle je travaille, aussi brièvement que possible.


using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace MyNamespace
{
    // This base view model takes care of implementing INotifyPropertyChanged
    // In your extended View Model classes, use SetValue in your setters.
    // This will take care of notifying your ObservableCollection and hence
    // updating your UI bound to that collection when your view models change.
    public abstract class BaseViewModel : INotifyPropertyChanged
    {
        protected void SetValue(ref T backingField, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer.Default.Equals(backingField, value)) return;
            backingField = value;
            OnPropertyChanged(propertyName);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    // Using MvvM, this would likely be a View Model class.
    // However, it could also be a simple POCO model class
    public class MyListItem : BaseViewModel
    {
        private string _itemLabel = "List Item Label";
        public string Label
        {
            get => _itemLabel;
            set => SetValue(ref _itemLabel, value);
        }
    }

    // This is your MvvM View Model
    // This would typically be your BindingContext on your Page that includes your List View
    public class MyViewModel : BaseViewModel
    {
        private ObservableCollection _myListItemCollection
            = new ObservableCollection();

        public ObservableCollection MyListItemCollection
        {
            get { return _myListItemCollection; }
            set => SetValue(ref _myListItemCollection, value);
        }
    }

}



0
JR Lawhorne