none
C#/XAML: Wie schreibt man Zeilen untereinander z.B. für einen Highscore-Liste RRS feed

  • Frage

  • Hallo zusammen,

    ich möchte eine Tabelle für z.B. eine Highscore erstellen. Welche Funktion macht in diesem Zusammenhang mehr Sinn. ListView oder trage ich die einzelnen Werte einfach via Stackpanel in eine TextBox ein ? Gibt es eigentlich eine Funktion, um Werte der Größe nach zu sortieren?

    Freue mich auf eure Vorschläge,
    LG Michael

    Montag, 3. März 2014 09:21

Antworten

  • Hallo,
    da es sich sicherlich um eine dynamische Liste handelt (die sich verändern kann), würde ich auf ein Control mit einer ItemsSoure setzen. Das könte u.a. eine ListBox sein. Ein StackPanel würde ich dafür nicht nutzen.

    Nachfolgend mal ein kurzes Beispiel, wie du es machen könnest. Zunächst eine Klasse User:

    public class User
    {
        //ggf. INotifyPropertyChanged implementieren
        public string Name { get; set; }
        public long HighScore { get; set; }
    }
    In der Page-Klasse brauchst du dann eine Auflistung:
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.HighScores = new ObservableCollection<User>();//Initialisieren
            this.HighScores.Add(new User() { Name = "A", HighScore = 100 });//Beispieldaten
            this.HighScores.Add(new User() { Name = "B", HighScore = 200 });//Beispieldaten
            this.HighScores.Add(new User() { Name = "C", HighScore = 50 });//Beispieldaten
            this.HighScores.Add(new User() { Name = "D", HighScore = 150 });//Beispieldaten
    
            this.HighScores = new ObservableCollection<User>(this.HighScores.OrderBy(x => x.HighScore));
            //Liste sortieren, die ObservableCollection muss dafür neu erstellt werden
            //Der Lambdaausdruck (mit => ) bestimmt, welche Eigenschaft zum sortieren genutzt werden soll
    
            this.DataContext = this;//Datacontext für Binding setzen
            this.InitializeComponent();
        }
    
        public ObservableCollection<User> HighScores { get; set; }
    }
    Im XAML kannst du dann einfach die Bindung vollziehen:
    <ListBox Width="200" ItemsSource="{Binding HighScores}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Margin="0" Text="{Binding Name}"/>
                    <TextBlock FontSize="10" Grid.Row="1" Margin="0" HorizontalAlignment="Right" ><Run>Punkte: </Run><Run Text="{Binding HighScore}"/></TextBlock>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    Eventuell solltest du noch ein ControlTemplate für die Items schreiben, damit man diese nicht mehr auswählen kann bzw. die Farbeffekte verschwinden.



    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert Michael80xxx Montag, 3. März 2014 17:52
    Montag, 3. März 2014 14:01
  • Hallo,
    eigentlich handelt es sich hierbei um eine neue Frage, darum wäre im Forum eine neue Frage auch passender gewesen. Ausnahmsweise trotzdem mal mein Lösungsansatz dazu:

    Zunächst solltest du den neuen Eintrag einfach hinzufügen:

    var newItem =new User() { Name = i, HighScore = z };
    this.HighScores.Add(newItem);
    Anschließend sortierst du die Liste neu. Das ist jetzt allerdings etwas komplizierter. Denn ein einfaches neuzuweisen der ObservableCollection geht nicht. Würdest du das machen, würde die GUI nicht mehr auf eine Änderung reagieren. Also müssen wir einen kleinen Umweg gehen:
    var orderedList = new ObservableCollection<User>(this.HighScores.OrderByDescending(x => x.HighScore));//Liste sortieren
    this.HighScores.Clear();//Alte Items entfernen
    foreach (var item in orderedList)//Sortierte Liste durch gehen
        this.HighScores.Add(item);//Wieder neu einfügen
    Jetzt kannst du prüfen ob mehr als 5 Elemente in der Liste sind und wenn ja, das Letzte heraus löschen:
    while (this.HighScores.Count > 5)//Lösche solange es mehr als 5 Elemente sind
        this.HighScores.Remove(this.HighScores.Last());//Letztes entfernen
    Zum Schluss kannst du prüfen, an welcher Stelle das anfangs neu hinzugefügte Item liegt:
    switch (this.HighScores.IndexOf(newItem))
    {
        case -1:
            //Nicht in der Liste
            break;
        case 0:
            //1. Platz
            break;
        default:
            //sonstiger Platz
            break;
    }





    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert Michael80xxx Samstag, 22. März 2014 17:34
    Dienstag, 18. März 2014 16:34

Alle Antworten

  • Hallo,
    da es sich sicherlich um eine dynamische Liste handelt (die sich verändern kann), würde ich auf ein Control mit einer ItemsSoure setzen. Das könte u.a. eine ListBox sein. Ein StackPanel würde ich dafür nicht nutzen.

    Nachfolgend mal ein kurzes Beispiel, wie du es machen könnest. Zunächst eine Klasse User:

    public class User
    {
        //ggf. INotifyPropertyChanged implementieren
        public string Name { get; set; }
        public long HighScore { get; set; }
    }
    In der Page-Klasse brauchst du dann eine Auflistung:
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.HighScores = new ObservableCollection<User>();//Initialisieren
            this.HighScores.Add(new User() { Name = "A", HighScore = 100 });//Beispieldaten
            this.HighScores.Add(new User() { Name = "B", HighScore = 200 });//Beispieldaten
            this.HighScores.Add(new User() { Name = "C", HighScore = 50 });//Beispieldaten
            this.HighScores.Add(new User() { Name = "D", HighScore = 150 });//Beispieldaten
    
            this.HighScores = new ObservableCollection<User>(this.HighScores.OrderBy(x => x.HighScore));
            //Liste sortieren, die ObservableCollection muss dafür neu erstellt werden
            //Der Lambdaausdruck (mit => ) bestimmt, welche Eigenschaft zum sortieren genutzt werden soll
    
            this.DataContext = this;//Datacontext für Binding setzen
            this.InitializeComponent();
        }
    
        public ObservableCollection<User> HighScores { get; set; }
    }
    Im XAML kannst du dann einfach die Bindung vollziehen:
    <ListBox Width="200" ItemsSource="{Binding HighScores}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Margin="0" Text="{Binding Name}"/>
                    <TextBlock FontSize="10" Grid.Row="1" Margin="0" HorizontalAlignment="Right" ><Run>Punkte: </Run><Run Text="{Binding HighScore}"/></TextBlock>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    Eventuell solltest du noch ein ControlTemplate für die Items schreiben, damit man diese nicht mehr auswählen kann bzw. die Farbeffekte verschwinden.



    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert Michael80xxx Montag, 3. März 2014 17:52
    Montag, 3. März 2014 14:01
  • Hallo,

    und danke für die schnelle Antwort.

    Ich bekomme aber leider dich folgenden Fehlermeldung angezeigt:

    "Fehler 1 Inkonsistenter Zugriff: Eigenschaftentyp System.Collections.ObjectModel.ObservableCollection<HighScore.User>' ist weniger zugreifbar als Eigenschaft 'HighScore.MainPage.HighScores' "

    Ich bin mit ObservableCollection noch nicht vertraut und verstehe, die Meldung nicht, woran es liegt.

    LG Michael

    Montag, 3. März 2014 17:45
  • Hallo nochmal,

    jetzt habe ich den Fehler gefunden :-)

    Vielen Dank für Deine Lösung zu meinem Problem,

    noch einen schönen Abend,

    LG Michael

    Montag, 3. März 2014 17:51
  • Hallo zusammen,

    ich habe mit meiner Liste ein Problem, mit dem ich nicht wirklich voran komme und hoffe, dass mir jdm. dabei weiterhelfen kann.

    Die Liste funktioniert soweit super, jetzt wollte ich diese um ein Detail erweitern und komme einfach nicht weiter :-(
    Wenn ein Spieler eine Spiel abgeschlossen hat, kann er sich in die Bestenliste, die nicht länger als 5 Plätze ist, eintragen - sofern er die entsprechende Punktezahl erreicht hat. Wenn er in die Liste kommt, wird der letzte Platz der Liste gelöscht.
    Daher wollte ich eine Prüfung vornehmen.

    In einem ersten Schritt ich folgendes:

    if (HighScores.Count == 5)
                    {
    
                        HighScores.RemoveAt(4);
                        HighScores.Add(new User() { Name = i, HighScore = z });
                        this.HighScores = new ObservableCollection<User>(this.HighScores.OrderByDescending(x => x.HighScore));
                    }
                    else
                    HighScores.Add(new User() { Name = i, HighScore = z });
                    NoEntry.Text = "Leider nicht geschafft";
                    this.HighScores = new ObservableCollection<User>(this.HighScores.OrderByDescending(x => x.HighScore));

    Jetzt soll zusätzlich aber noch eine Anzeige erfolgen, dass man z.B. eine neue HighScore erreicht hat. Doch wie frage ich in der Tabelle ab, ob jdm. den 1. Platz erreicht hat ?

    Weißt jdm. vielleicht eine Lösung zu dem Problem ?

    Danke vorab, und viele Grüße

    Michael

    Dienstag, 18. März 2014 11:38
  • Hallo,
    eigentlich handelt es sich hierbei um eine neue Frage, darum wäre im Forum eine neue Frage auch passender gewesen. Ausnahmsweise trotzdem mal mein Lösungsansatz dazu:

    Zunächst solltest du den neuen Eintrag einfach hinzufügen:

    var newItem =new User() { Name = i, HighScore = z };
    this.HighScores.Add(newItem);
    Anschließend sortierst du die Liste neu. Das ist jetzt allerdings etwas komplizierter. Denn ein einfaches neuzuweisen der ObservableCollection geht nicht. Würdest du das machen, würde die GUI nicht mehr auf eine Änderung reagieren. Also müssen wir einen kleinen Umweg gehen:
    var orderedList = new ObservableCollection<User>(this.HighScores.OrderByDescending(x => x.HighScore));//Liste sortieren
    this.HighScores.Clear();//Alte Items entfernen
    foreach (var item in orderedList)//Sortierte Liste durch gehen
        this.HighScores.Add(item);//Wieder neu einfügen
    Jetzt kannst du prüfen ob mehr als 5 Elemente in der Liste sind und wenn ja, das Letzte heraus löschen:
    while (this.HighScores.Count > 5)//Lösche solange es mehr als 5 Elemente sind
        this.HighScores.Remove(this.HighScores.Last());//Letztes entfernen
    Zum Schluss kannst du prüfen, an welcher Stelle das anfangs neu hinzugefügte Item liegt:
    switch (this.HighScores.IndexOf(newItem))
    {
        case -1:
            //Nicht in der Liste
            break;
        case 0:
            //1. Platz
            break;
        default:
            //sonstiger Platz
            break;
    }





    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert Michael80xxx Samstag, 22. März 2014 17:34
    Dienstag, 18. März 2014 16:34
  • Hallo,

    super und vielen Dank.

    LG Michael

    Samstag, 22. März 2014 17:34