简体   繁体   中英

Do I really need a static class to manage favorites?

Hi have a conception problem. I work on a pro app to calculate some scores. I do it with C# / Xamarin.Forms. I want to manage favorites, so that the user can have a limited score list to find its favorites faster.

I have 4 tabs :

  1. Entire score list ==> navigates to chosen score
  2. Favorites list ==> navigates too
  3. & 4. : not a problem here

So I want that when the user adds/deletes a score from the favorites list, this is changed in the first and the second tab. For the moment I have this :

public static class FavoritesManager
{
    public static ObservableCollection<string> FavoritesList = new ObservableCollection<string>();

    // Indexer does not work because static class ==> this is one of the problems
    // public bool this[string key] { get => this.Favs.Contains(key); }
}

// My ViewModel
public class ScoreListViewModel : ViewModelBase
{
    // Each Category is a List<Score>. Score has 3 properties : string Title, string Detail, bool IsFavorite
    public ObservableCollection<Category> Categories { get; set; }

    public ScoreListViewModel()
    {
        this.InitializeCategories();

        FavoritesManager.FavoritesList.CollectionChanged += OnFavoritesChanged;
    }

    // When favorites list has changed ==> event CollectionChanged
    public void OnFavoritesChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        this.InitializeCategories();
    }

    public void InitializeCategories()
    {
        this.Categories = new ObservableCollection<Category>
        {
            new Category ("Cat1")
            {
                new Score("Foo", "Bar", FavoritesManager.FavoritesList.Contains("Foo"))
            }
        };
    }

    // Command used to add a favorite
    public ICommand AddToFavorites => new Command<string>((fav) =>
    {
        FavoritesManager.FavoritesList.Add(fav);
    });
}

So I have 2 questions :

  1. How to avoid dependency of ViewModel to the static class FavoritesManager ? Do I really need a static class or is there another way to "share" it in real time through different views ? Because if I decide to change favorites management, when I will have 30-40 scores in the list, it will be very difficult...

  2. Is there a way to avoid complete reinitialization of the Categories list each time I change just 1 thing (1 favorite) ? This is, I think, mostly a XAML / Binding question...

Thanks for your help, Galactose

The class doesn't need to be static. Simply have one static instance of a not-static class. This is one way to implement a "Singleton Pattern".

Details:

public class FavoritesManager
{
    // The only instance. Readonly, because it is never re-assigned.
    public readonly static It => new FavoritesManager();

    // "get", so that it is a `property`. This is necessary for `ObservableCollection` to be seen via binding.
    public readonly ObservableCollection<string> FavoritesList {get;} = new ObservableCollection<string>();

    // Private, so no other instances can be created.
    private FavoritesManager()
    {
    }

    ...
}

Usage:

    ... FavoritesManager.It...

Then do everything you are accustomed to doing, such as defining an indexer. And refer to the one instance (from code in other classes) by FavoritesManager.It .


Re your Binding question, my answer may be incomplete. However, note the one change I've made: XAML Bindings only see properties : the ObservableCollection must be a property (have a getter).

You might also need to make FavoritesManager be a BindableObject:

 public class FavoritesManager : Xamarin.Forms.BindableObject

Thanks a lot for your help. I've heard about singleton pattern previously, but never used it... It's perfect for this usage !

Yet, I did little changes to better implement it in C# (taken from https://jlambert.developpez.com/tutoriels/dotnet/implementation-pattern-singleton-csharp/ solution #4) :

public sealed class FavoritesManager
{
    // Instance for Singleton pattern
    public static FavoritesManager Instance { get; } = new FavoritesManager();

    // Singleton pattern : no other instance permitted ==> static & private constructor
    static FavoritesManager()
    { }

    private FavoritesManager()
    { }

    // Collection of all favorites
    public ObservableCollection<string> Favorites { get; private set; } = new ObservableCollection<string>();

    // If needed, access from indexer
    public bool this[string key]
    {
        get => this.Favorites.Contains(key);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM