Associa selezione dalla GUI con codice eseguibile

4

Attualmente sto scrivendo una GUI per un'applicazione C # che rispetti i seguenti requisiti software (e sto lottando con la progettazione concettuale):

  1. Avere una GUI con alcune scelte di diverse operazioni da eseguire.
  2. Ogni scelta possibile nella GUI dovrebbe avere alcune sottoselezioni da cui l'utente può scegliere.
  3. Ciascuna selezione deve corrispondere a un determinato oggetto da utilizzare.
  4. Ciascuna delle sotto-selezioni deve corrispondere con un determinato metodo da eseguire (appartenente all'oggetto selezionato).

In una frase, sto cercando di associare le scelte / opzioni a diverse parti del codice eseguibile.

Voglio davvero capire un modo per separare queste "scelte / selezioni" dall'applicazione, ma con la mia attuale esperienza di livello, l'unica cosa che so come fare è fare una grande istruzione switch e hard-code selezioni / operazioni di sub-selezione basate sulle stringhe hard-coded. C'è ottenuto come un altro modo di associare le selezioni con le operazioni, ma non riesco a capire.

Diciamo che ho deciso di usare XML e ho codificato tutte le possibili selezioni, tutto ciò che mi avrebbe permesso di fare è popolarle sulla GUI. Dovrei ancora codificare i valori nell'applicazione per prendere le decisioni su cosa fare quando vengono selezionati correttamente? Semplicemente non vedo nessun altro modo.

Nel caso qualcuno fosse curioso, sto usando WPF per costruire questa applicazione.

    
posta Snoop 07.07.2016 - 15:12
fonte

3 risposte

1

Probabilmente avrei un modello di oggetto che assomigliava a questo:

public interface ISelectionModel
{
    string DisplayName { get; }
    List<string> SubSelections { get; }
    void RunSubSelection(string sub);
}

public SelectionBaseModel : ISelectionModel
{
    private string _displayName;
    private List<string> _subSelections;

    public string DisplayName { get { return _displayName; }}
    public List<string> SubSelections { get { return _subSelections; }}
}

public SelectionAModel : ISelectionModel
{
    public SelectionAModel()
    {
        _displayName = "Selection A";
        _subSelections = new List<string>() { "Sub 1", "Sub 2", "Sub 3" });
    }

    public void RunSubSelection(string sel)
    {
        switch(sel)
        {
            case "Sub 1":
                Method1();
                break;
            case "Sub 2":
                Method2();
                break;
            case "Sub 3":
                Method3();
                break;
        }
    }

    private void Method1() { .. }
    private void Method2() { .. }
    private void Method3() { .. }
}

C'è un po 'di hardcoding, ma è inevitabile perché penso che devi scrivere i tuoi metodi di codice. Tuttavia, sarebbe diviso, quindi solo i metodi rilevanti per SelectionA dovrebbero essere nel modello SelectionA, oppure i metodi condivisi per tutte le selezioni potrebbero andare nel modello Base.

A scopo di visualizzazione, avresti un elenco o una raccolta di oggetti ISelectionModel associati a qualsiasi controllo tu scelga di visualizzare la raccolta, e ogni elemento verrà visualizzato usando un altro controllo con un oggetto Origine per visualizzare le voci del sottomenu. Quando fai clic su un elemento secondario per eseguirlo, devi semplicemente chiamare qualcosa come SelectedSelection.Run(SelectedSelection.SelectedSub) dal tuo ICommand .

Ogni oggetto figlio potrebbe essere autonomo e potrebbe essere inizializzato da un file XML, se lo si desidera. Puoi anche rendere dinamico l'elenco delle stringhe, ad esempio:

  • "Selezione A1" di tipo SelectionAModel con { "Sub 1", "Sub 2" }
  • "Selezione A2" di tipo SelectionAModel con { "Sub 2", "Sub 3" }
  • "Selezione A3" di tipo SelectionAModel con { "Sub 1", "Sub 2", "Sub 3" }
  • "Selezione B" di tipo SelectionBModel con { "Sub 4", "Sub 5" }
risposta data 07.07.2016 - 23:09
fonte
0

Un modo per farlo:

  • Le selezioni nell'interfaccia utente sono un ItemsControl con un ItemTemplate appropriato (ad esempio ToggleButton ), associato a una raccolta di oggetti (o visualizzazione di modelli che li rappresentano).
  • Le sottoselezioni nell'interfaccia utente sono anche un ItemsControl , associato a una raccolta che rappresenta i metodi dell'oggetto selezionato (questa volta ItemTemplate potrebbe essere Button ).
  • I metodi vengono recuperati utilizzando reflection.

Il nucleo di questo design è il modello di visualizzazione dell'intero controllo, che potrebbe essere simile a questo:

public class SelectionsViewModel : INotifyPropertyChanged
{
    private SelectionViewModel selection;

    public SelectionsViewModel(IEnumerable<object> selections)
    {
        Selections = selections.Select(s => new SelectionViewModel(this, s));
    }

    public IEnumerable<SelectionViewModel> Selections { get; }

    public SelectionViewModel Selection
    {
        get { return selection; }
        set
        {
            selection = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(Subselections));
        }
    }

    public IEnumerable<SubselectionViewModel> Subselections =>
        CreateSubselections(Selection?.Selection);

    private static IEnumerable<SubselectionViewModel> CreateSubselections(object selection)
    {
        if (selection == null)
            return Enumerable.Empty<SubselectionViewModel>();

        return from m in selection.GetType().GetMethods(Public | Instance | DeclaredOnly)
               // methods with no parameters, except property getters
               where !m.GetParameters().Any() && !m.Name.StartsWith("get_")
               select new SubselectionViewModel(m.Name, () => m.Invoke(selection, null));
    }

    // INPC implementation omitted
}
    
risposta data 07.07.2016 - 22:10
fonte
0

Questo mi sembra esattamente ciò che ICommand interfaccia e l'associazione dei comandi sono per. Si desidera eseguire un comando, con un determinato parametro, quando viene eseguita una determinata azione dell'interfaccia utente. Questo è esattamente ciò che ICommand è progettato per fare.

Collega solo il Command della sotto-selezione alla corrispondente proprietà ICommand nel tuo modello di vista, ed è CommandParameter alla selezione di livello superiore. (Potresti aver bisogno di un po 'di codice per recuperare l'oggetto reale che desideri, ma probabilmente puoi trovare un modo per associare correttamente quell'oggetto come parametro.)

    
risposta data 08.07.2016 - 00:07
fonte

Leggi altre domande sui tag