Mon événement PropertyChanged ne met pas à jour ma vue de liste dans xamarin. Quelqu'un pourrait-il m'aider avec ça?

La méthode Refresh ListView est déclenchée lorsque le texte de la barre de recherche a changé.

Mon Viewmodel:

public class LebensmittelViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Lebensmittel> lebensmittelList = new ObservableCollection<Lebensmittel>();
    public List<Lebensmittel> normalLebensmittelList = new List<Lebensmittel>();
    public event PropertyChangedEventHandler PropertyChanged;

    public LebensmittelViewModel()
    {
        normalLebensmittelList = App.LebensmittelDatabase.getAllLebensmittel();
    }

    public void RefreshListView(string searchBarText)
    {
        LebensmittelList = addItemInCollection(searchBarText);
    }

    public ObservableCollection<Lebensmittel> addItemInCollection(string searchBarText)
    {
        if (searchBarText != null)
        {
            foreach (var item in normalLebensmittelList)
            {
                if (item.Name.Contains(searchBarText) || item.Name.Contains(searchBarText.First().ToString().ToUpper()))
                {
                    LebensmittelList.Add(item);
                };
            }
        }
        return LebensmittelList;
    }

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

    public ObservableCollection<Lebensmittel> LebensmittelList
    {
        get
        {
            return lebensmittelList;
        }
        set
        {
            lebensmittelList = value;
            OnPropertyChanged("LebensmittelList");
        }
    }
}

Einkaufsliste.xaml

<ContentPage.Content>
    <StackLayout Spacing="10" Padding="10">
        <SearchBar x:Name="searchBar" Text="{Binding searchBarText}" Placeholder="Lebensmittel suchen..." VerticalOptions="StartAndExpand">
            <SearchBar.Behaviors>
                <behavior:TextChangedBehavior/>
            </SearchBar.Behaviors>
        </SearchBar>
        <ListView x:Name="listView" ItemsSource="{Binding LebensmittelList}" HasUnevenRows="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout VerticalOptions="FillAndExpand" Orientation="Horizontal" Padding="10">
                            <Label Text="{Binding Name}" YAlign="Center" Font="Large"/>
                            <ia:Checkbox HorizontalOptions="EndAndExpand"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage.Content>

Einkaufsliste.xaml.cs

public Einkaufsliste ()
    {
        InitializeComponent ();
        BindingContext = new LebensmittelViewModel();
    }

Je pense que tout devrait aller bien mais ça ne marche pas. J'espère que quelqu'un pourrait m'aider avec ça,

Merci

Modifier pour Tom:

public void RefreshListView(string searchBarText)
    {
        addItemInCollection(searchBarText);
    }

    public void addItemInCollection(string searchBarText)
    {
        if (searchBarText != null)
        {
            foreach (var item in normalLebensmittelList)
            {
                if (item.Name.Contains(searchBarText) || item.Name.Contains(searchBarText.First().ToString().ToUpper()))
                {
                    AddItemToList(item);
                };
            }
        }
    }

    private void AddItemToList(Lebensmittel item)
    {
        lebensmittelList.Add(item);
        LebensmittelList = lebensmittelList;
    }
0
Marvin L 20 nov. 2018 à 19:57

5 réponses

Meilleure réponse

Comment a-t-il mis en œuvre le comportement TextChangedBehavior? Diffusez-vous le BindingContext en LebensmittelViewModel pour appeler RefreshListView?

Je voudrais me débarrasser du comportement: / et ajouter un événement TextChanged, créer la propriété SearchBarText, car je ne vois pas où elle est déclarée et vous la liez au SearchBar , refactorisez la méthode RefreshListView ... et je pense que cela devrait fonctionner ... :)

Einkaufsliste.xaml.cs

private LebensmittelViewModel vm = new LebensmittelViewModel();
public Einkaufsliste ()
{
    InitializeComponent ();
    BindingContext = vm;
}

public void OnSeachBarTextChange(object e, TextChangedEventArgs args)
{
    vm.RefreshListView();
}

Einkaufsliste.xaml

<ContentPage.Content>
    <StackLayout Spacing="10" Padding="10">
        <SearchBar x:Name="searchBar" Text="{Binding SearchBarText, Mode=TwoWay}" Placeholder="Lebensmittel suchen..." VerticalOptions="StartAndExpand" TextChanged="OnSeachBarTextChange">
        </SearchBar>
        <ListView x:Name="listView" ItemsSource="{Binding LebensmittelList}" HasUnevenRows="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout VerticalOptions="FillAndExpand" Orientation="Horizontal" Padding="10">
                            <Label Text="{Binding Name}" YAlign="Center" Font="Large"/>
                            <ia:Checkbox HorizontalOptions="EndAndExpand"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage.Content>

Viewmodel

private string _searchBarText;

public string SearchBarText
{
    get
    {
        return _searchBarText;
    }
    set
    {
        _searchBarText = value;
        OnPropertyChanged("SearchBarText");
    }
}

public void RefreshListView()
{
    if (!string.IsNullOrEmpty(searchBarText))
    {
        var matches = normalLebensmittelList.Where(x => x.Name.Contains(searchBarText) || x.Name.Contains(searchBarText.First().ToString().ToUpper())
        foreach (var item in matches)
        {
          LebensmittelList.Add(item);
        }
    }
}
0
jjchiw 21 nov. 2018 à 12:01

Il semble que vous ayez du travail supplémentaire avec LebensmittelList. Essayez de faire ce qui suit:

public void RefreshListView(string searchBarText)
{
    // this can be list clearing, if you need it
    addItemInCollection(searchBarText);
    OnPropertyChanged("LebensmittelList");
}

public void addItemInCollection(string searchBarText)
{
    if (searchBarText != null)
    {
        foreach (var item in normalLebensmittelList)
        {
            if (item.Name.Contains(searchBarText) || item.Name.Contains(searchBarText.First().ToString().ToUpper()))
            {
                LebensmittelList.Add(item);
            };
        }
    }
}

Modifier: Je ne sais pas si quelqu'un peut qualifier cette solution d'élégante, mais cela devrait fonctionner.

internal class MyCollection<T> : ObservableCollection<T> 
{
    public void DoCollectionChanged()
    {
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

}

    ... MyCollection<LebensmittelItem> LebensmittelList; // field and property declaration should be changed

public void RefreshListView(string searchBarText)
{
    // this can be list clearing, if you need it
    addItemInCollection(searchBarText);
    LebensmittelList.DoCollectionChanged();
}
0
Miamy 20 nov. 2018 à 20:24

Dans la méthode addItemToCollection, vous appelez la ligne suivante:

LebensmittelList.Add(item);

Dans ce cas, LebensmittelList est une propriété , pas une variable. La ligne LebensmittelList.Add(item); fait effectivement ce qui suit:

var temporaryList = LebensmittelList; // Gets lebensmittelList and assigns to temporaryList
temporaryList.Add(item); // You add the item to the *variable temporaryList*

Essentiellement, vous ajoutez à une instance de lebensmittelList (une copie temporaire), et non la variable lebensmittelList. Une fois que vous avez ajouté cet élément à la liste temporaire, toute la liste (temporaire) est supprimée sans "enregistrer les modifications".

Pour mettre à jour LebensmittelList, il vaut mieux appeler une méthode comme:

private void AddItemToList(object item)
{
    lebensmittelList.Add(item);
    LebensmittelList = lebensmittelList;
}
0
Tom 21 nov. 2018 à 11:04

OnPropertyChanged dans la propriété set est-il appelé lorsque vous effectuez le RefreshListView?

0
Alexander Uddfeldt 21 nov. 2018 à 09:27

Pouvez-vous essayer de remplacer la méthode suivante:

public void RefreshListView(string searchBarText)
{
    LebensmittelList.Clear();
    addItemInCollection(searchBarText);
}

Puisque vous utilisez déjà la collection Observable, vous n'avez pas besoin de remplacer la collection. Vous pouvez ajouter et il sera automatiquement observé et lié. Dites moi si ca marche!

0
Nirmal Subedi 20 nov. 2018 à 17:44