Dovrei piuttosto passare stringhe o oggetti a DropDownList?

0

Sto scrivendo un elenco a discesa personalizzato. Voglio renderlo riutilizzabile (ovviamente), quindi ho un metodo PopulateList . Posso popolare la lista in due modi però. Innanzitutto, passa una lista o una matrice di stringhe a PopulateList . Ma quasi mai non voglio selezionare una stringa , giusto? Il più delle volte si tratta di oggetti complessi. Ad esempio, supponiamo di avere una classe Dog con due proprietà, Name e Breed . Voglio mostrare un elenco a discesa con i nomi dei cani. Posso fare listOfDogs.Select(x => x.Name).ToList() e lì ce l'ho, una lista di cani che posso passare a PopulateList . Ora, dal momento che quelle sono stringhe e il mio menu a discesa non conosce gli oggetti stessi, quando aumenterà l'evento ItemSelected , non sarà in grado di dire quale oggetto è stato selezionato, ma piuttosto quale string e dovrò fare il mapping sul lato della gestione. E va bene, ma quella parte di mappatura è piuttosto brutta.

Il secondo modo è questo:

void PopulateList<T>(List<T> list, Func<T, string> selector )
{
    var stringValues = list.Select(selector).ToList();
    ...
}

e usarlo in questo modo:

var list = new List<Dog>
{
    new Dog {Breed = "German Shepard", Name = "Nancy"},
    new Dog {Breed = "Collie", Name = "Stacy"} // weird name choices, I know
};

PopulateList(list, dog => dog.Name);

In questo modo, il menu a discesa non si preoccuperà di quale tipo di oggetti ha a che fare e sarà in grado di sapere quale oggetto è stato selezionato e io sarò in grado di avvolgerlo magnificamente in EventArgs e passalo al gestore dell'evento.

La mia domanda è: quali sono i vantaggi dell'utilizzo del secondo approccio? È una complessità inutile?

EDIT:

Ho finito per implementarlo in questo modo:

async Task<T> PopupSelect<T>(string title, List<T> objects, Func<T, string> selector, bool hasDefault, T defaultObject = default(T))

È molto facile da usare. Ad esempio:

_button.Clicked += async delegate
{
    var list = new List<Tuple<string, string>>()
    {
        Tuple.Create("asdf", "Dog"),
        Tuple.Create("a", "Cat"),
        Tuple.Create("d", "Mouse"),
        Tuple.Create("e", "Rat"),
        Tuple.Create("r", "Hamster"),
        Tuple.Create("2", "Elephant"),
        Tuple.Create("344", "Lion"),
        Tuple.Create("ascv", "Tiger"),
        Tuple.Create("vv", "Buffalo"),
    };

    var selected = await PopupSelect("Select a pet", list, s => s, true, list[5]);

    if (selected == null)
        Debug.WriteLine("Sorry, no value was selected");
    else
        Debug.WriteLine(selected.Item2);
    
posta nicks 20.09.2016 - 07:55
fonte

2 risposte

1

In generale, ho trovato molto utile mettere gli oggetti negli elenchi a discesa. Mi ha fornito una certa flessibilità a volte. Ecco una situazione utile che ho avuto: avevo bisogno di avere un elenco a discesa di mesi in un anno, ordinato cronologicamente. Tuttavia, volevo avere una lista di nomi di mesi, e avevo anche bisogno di avere la mia lista localizzata, il che significa che i nomi dei mesi sarebbero in lingue diverse, a seconda dell'impostazione della lingua selezionata. Ho quindi implementato una classe DropDownMonth (o qualcosa del genere) che conteneva il numero ordinale del mese (per l'ordinamento e il recupero rapido del numero intero necessario per la successiva creazione di alcune date) e un override del metodo ToString che ha restituito il nome del mese nella lingua desiderata. Ho quindi inserito gli oggetti di quella classe nel menu a discesa e il problema è stato risolto.

L'alternativa sarebbe quella di spingere le stringhe nel dropdwon e quindi ottenere il numero di un mese dall'indice selezionato della lista, che a me non sembrava una soluzione elegante.

Per tornare alla tua domanda, anche se interessante, credo che il secondo approccio che hai elencato sia inutilmente complesso e che otterresti esattamente quello che volevi posizionando oggetti con il metodo ToString sovrascritto nel menu a discesa.

L'unica situazione in cui il tuo secondo approccio sarebbe molto elegante è se hai un elenco di oggetti che vuoi inserire in diversi elenchi a discesa con ciascun menu a discesa che mostra una proprietà diversa di un oggetto. In tal caso, direi che il secondo approccio sarebbe un modo per andare.

    
risposta data 20.09.2016 - 08:57
fonte
1

Scriverò entrambi, francamente. È possibile definire la stessa funzione con due prototipi. Per mantenere DRY , lo strumento basato su oggetti può chiamare internamente quello basato su stringhe. Gli sviluppatori che lavorano sulla tua base di codice principale dovrebbero avere la possibilità di utilizzare qualsiasi cosa sia più conveniente nella loro situazione.

void PopulateList<T>(List<T> list, Func<T, string> selector )
{
    var stringValues = list.Select(selector).ToList();
    PopulateList(stringValues);
}

void PopulateList(List<String> list)
{
    //Populate the list here
}
    
risposta data 20.09.2016 - 22:14
fonte

Leggi altre domande sui tag