Das Konzept ist entstanden aus dieser Diskussion: Wie designe ich die Datenbank für ein Quiz mit drei verschiedenen Fragearten? und setzt sie quasi etwas fort.
Ihr könnt gerne - wenn ihr wollt - Antworten posten, Erweiterungen, Verbesserungen, Alternativen - am besten wäre natürlich mit angehängtem, lauffähigen Zips, auf der Vorlage basierend oder auch from Scratch.
Datenmodell
Bildle gugge: QuizFrage ist Zuordnungstabelle einer m:n - Relation, deren Datensätze jeweils eine Frage einem Quiz zuordnet.
Problem1: Polymorphie
Das komplizierte ist jetzt, dass es 3 verschiedene Arten von Fragen gibt:
- SpellFrage: verlangt eine buchstaben-getreue Antwort
- BildFrage: Ein Bild wird gezeigt, dazu eine Frage, ebenfalls buchstaben-getreu zu beantworten
- McFrage - Multiple Choice: Mehrere Antwortmöglichkeiten, von denen eine richtig ist
Richtige Polymorphie wird aber vom Dataset nicht unterstützt, und würfe auch Präsentations-Probleme auf, die imo erst in Wpf eine wirkliche Antwort finden (DataTemplates).
Hier ists so gelöst, dass ein QuizFrage-(Zuordnungs-)Datensatz gleich 3 Verweise hat, auf jede Frage-Art einen.
Business-Logik muss nun sicherstellen, dass immer mindestens 2 der Verweise genullt sind - anders gesagt: Dass ein Zuordnungs-Datensatz nur eine Frage zuordnet, nicht 3 verschiedene auf einmal.
Diese "Umgehung der Polymorphie" erweist sich bei der Präsentation als überraschend praktisch: Dem User werden die verschiedenen Frage-Arten ja als Spalten präsentiert, und indem er in eine Spalte eingibt hat er bereits die Art der zugeordneten Frage bestimmt.
Problem2: Multiple Choice
Ein anderer Trick ist die wechselseitige Relation zwischn McFrage und McAntwort:
Nämlich eine McFrage hat logisch viele Antwort(-Optionen), ist also übergeordnet.
Aber gleichzeitig hat sie auch einen Verweis (also einen Fremdschlüssel, untergeordnet) auf die richtige Antwort.
Gui-Logik sorgt nun dafür, dass wenn die DGV-Checkbox-Zelle der IsTrue-Spalte angeklickt wird, dass dann die Parent-Frage ihren Verweis auf diese Antwort setzt.
IsTrue ist übrigens eine berechnete Spalte, darin gar kein Wert eingebbar ist, sondern sie berechnet sich selbst, mit folgender Expression (eingetragen im Dataset-Designer):
count(child.ID)=1
also wenn es genau eine ChildRow gibt, ist dieses die richtige Antwort.
Da die ChildRow einer McAntwortRow aber gleichzeitig immer auch die ParentRow (McFrageRow) ist, kann es zu einer Antwort auch nur maximal 1 ChildRow geben.
Und wenn es sie gibt ist damit IsTrue true, und diese Antwort also als die einzig richtige gekennzeichnet
(ups - mir fällt grad auf: das ist ja gar kein Multiple-Choice, da ist ja nur Choice 8o)