2017-01-14 4 views
16

Ich habe folgendes Label:Fügen Sie mehrere Etiketten in Xamarin Forms

<Label Text="{x:Static local:FontAwesome.FACheck}" FontFamily="FontAwesome" TextColor="Green"/> 

und ein Ereignis auf die Schaltfläche:

correctButton.Clicked += (sender, e) => 
{ 
    App.DB.IncrementScore(); 
}; 

Was das bedeutet ist, jedes Mal wenn ich meine Punktzahl auf eine Schaltfläche klicken wird erhöht durch 1. Was ich machen wollte, ist auch die Anzahl der Label s zu erhöhen, abhängig von der Anzahl der Punkte. Siehe die beigefügten Bild unten:

enter image description here

Wer hat eine Idee, wie ich das erreichen könnte?

+2

ich stark in eine MVVM-Architektur für diesen App suchen würde empfehlen. Sie können Ihre Labels an eine ObservableCollection in Ihrem ViewMidel binden. –

+1

@RobLyndon danke.Ich kenne MVVM, aber ich weiß nicht, wie man es hier anwendet. Können Sie mir ein Codebeispiel zu meinem Problem geben? –

Antwort

7

Es gibt verschiedene Lösungen für diese Frage. Achten Sie darauf, durch alle von ihnen zu lesen, bevor man die Wahl - mein Favorit (die einfachste) ist den ganzen Weg hinunter aufgelistet ...

Ansatz # 1:

Da mehrere Leute vorgeschlagen haben, können Sie schaffen eine Sammlung Kontrolle (ich werde in einem Moment dazu kommen), definieren eine ObservableCollection innerhalb eines Ansichtsmodell, stellen die Binding Context Seite auf eine Instanz dieser Ansichtsmodell, und fügen Sie Elemente in die Sammlung auf die Schaltfläche klicken:

public class MyViewModel() 
{ 
    public ObservableCollection<int> Items { get; set; } = new ObservableCollection<int>(); 
} 

private MyViewModel _viewModel = new MyViewModel(); 
public MainPage() 
{ 
    InitializeComponent(); 

    BindingContext = _viewModel; 
} 

correctButton.Clicked += (sender, e) => 
{ 
    App.DB.IncrementScore(); 
    _viewModel.Items.Add(0); 
}; 

Der Typ ObservableCollection ac tually keine Rolle spielt, da wir die gleichen statischen ItemTemplate für alle Elemente verwenden:

<ContentPage.Resources> 
    <DataTemplate x:Key="ScoreItemTemplate"> 
     <ViewCell> 
      <ViewCell.View> 
       <Label Text="{x:Static local:FontAwesome.FACheck}" FontFamily="FontAwesome" TextColor="Green"/> 
      </ViewCell.View> 
     </ViewCell> 
    </DataTemplate> 
</ContentPage.Resources> 

Das Hauptproblem bei diesem Ansatz ist, dass Xamarin.Forms ListView nicht seine Elemente horizontal angezeigt werden kann. Das heißt, würden Sie einen der verfügbaren HorizontalListView Nuget Pakete herunterladen müssen da draußen, oder verwenden Sie das built-in (only in Xamarin.Forms 2.3 and above!) CarouselView:

<CarouselView ItemTemplate="{StaticResource ScoreItemTemplate}" ItemsSource="{Binding Items}"/> 

Dann werden Sie vielleicht wollen einige Zeit Entfernen aller visuellen Effekte für swiping durch verbringen das Karussell, und für die Auswahl von Elementen, wenn Sie eine horizontale ListView verwenden möchten ...

Stattdessen gibt es zwei alternative Lösungen, die weniger Aufwand verbunden:

Ansatz # 2:

Offensichtlich wäre der einfache Ansatz, die "Vorlage" label in Code zu erstellen:

private Label CreateScoreLabel() 
{ 
    return new Label {Text = FontAwesome.FACheck, TextColor = Color.Green, FontFamily = "FontAwesome"}; 
} 

... ein horizontales StackLayout die Seite hinzufügen:

<StackLayout Orientation="Horizontal" x:Name="LabelStack"/> 

... und neue Labels auf die harte Weise hinzufügen:

correctButton.Clicked += (sender, e) => 
{ 
    App.DB.IncrementScore(); 
    LabelStack.Children.Add(CreateScoreLabel()); 
}; 

Doch all dies scheint eher Hacky für nur eine Liste mit grünen Häkchen zu schaffen. Dies führt uns zu ...

... Ansatz # 3:

Technisch ist dies nicht genau das, was Sie für (Erhöhung der Anzahl der Labels) gefragt, aber nach Ihrem Bildschirm Schuss es könnte Ihre Bedürfnisse auf eine viel einfachere Weise erfüllen.

entfernen den Text des bestehenden Label (wie es nichts beim Start angezeigt werden soll), und es stattdessen einen eindeutigen Namen geben:

<Label x:Name="ScoreLabel" FontFamily="FontAwesome" TextColor="Green"/> 

nun eine einfache Erweiterung Methode für die string Typ definieren, die eine bestimmte Zeichenfolge wiederholt für eine bestimmte Anzahl von Malen:

public static class StringExtensions 
{ 
    public static string Repeat(this string input, int num) 
    { 
     return String.Concat(Enumerable.Repeat(input, num)); 
    } 
} 

(Es gibt mehrere Möglichkeiten, diese wiederholen Funktion so performant wie möglich zu machen, habe ich einfach die einfachste Einzeiler verfügbar gewählt haben, suchen Sta ckOverflow für eingehende Gespräche ...)

Sie können nun mit der Single Label Kontrolle in XAML definiert arbeiten und weisen nur einige Häkchen, um es auf die Schaltfläche klicken:

correctButton.Clicked += (sender, e) => 
{ 
    App.DB.IncrementScore(); 
    ScoreLabel.Text = FontAwesome.FACheck.Repeat(App.DB.Score); // replace parameter by whatever method allows you to access the current score number 
}; 

Natürlich kann dieser Ansatz auch angepasst werden, um dem MMVM-Weg zu folgen, indem Sie einfach eine öffentlich bindbare string Eigenschaft verwenden, anstatt das Attribut Text des Labels direkt zu setzen, aber dafür würde ich Ihnen raten, einen Anfänger MVVM Tutorial zu sehen.

+0

danke. Ich probiere Ansatz # 3 aus, aber ich bekomme einen Fehler 'String wurde nicht als gültiger Boolean erkannt. Irgendeine Idee warum? –

+0

Bei welcher Zeile wird dieser Fehler ausgelöst? Können Sie auch den genauen Button-Klick-Handler anzeigen, nachdem Sie ihn an Ihre Bedürfnisse angepasst haben? – andreask

+1

Sorry, es ist mein Fehler. Ich habe eine "IsVisible" -Eigenschaft in meinem Etikett hinzugefügt, während ich an Code früher bastelte, aber den Wert leer ließ. Ich werde den Code mehr mit Ihrer Lösung bearbeiten und Sie dann wissen lassen, wenn es funktioniert. –

1

Wenn der Punktestand ein Maximum hat, fügen Sie einfach die maximale Anzahl der Beschriftungen hinzu und binden Sie deren Sichtbarkeit.

Oder Sie können eine Listenansicht von Beschriftungen erstellen und die Quelle an eine Sammlung binden, die Sie bei Bedarf inkrementieren.

+0

Ich könnte dies tun, aber es ist keine sehr saubere Lösung, da ich maximale Anzahl von 20 Punkten habe. –

+0

Ich aktualisiert, um eine andere Idee vorzuschlagen. –

0

Hinweis: Ich bin mir nicht sicher, ob diese Antwort richtig ist, aber es ist zu lang für einen Kommentar. Testen Sie es einfach und wenn es nicht funktioniert, lösche ich diese Antwort


Sie können Steuerelemente programmgesteuert hinzufügen. Denken Sie daran, dass Sie auf Ihrem MainThread ein Label hinzufügen müssen, da es sich um eine Änderung der Benutzeroberfläche handelt. Fügen Sie diese auf Ihre Clicked Veranstaltung:

correctButton.Clicked += (sender, e) => 
{ 
    App.DB.IncrementScore(); 
    Device.BeginInvokeOnMainThread(() => // On MainThread because it's a change in your UI 
    { 
     Label label = new Label(); 
     label.Text = "{x:Static local:FontAwesome.FACheck}"; // Not sure if this is right syntax... 
     label.FontFamily = "FontAwesome"; 
     label.TextColor = Color.Green; 
     stackPanel.Children.Add(label); 
    }); 
}; 

Falls Sie ein Grid haben, können Sie Grid.Row und Grid.Column mit dem SetValue Methode eines Control gesetzt:

label.SetValue(Grid.RowProperty, 1); 
label.SetValue(Grid.RowProperty, 2); 
1

Fügen Sie einfach einen neuen Label-Code in das Button-Klick-Ereignis ein, wodurch neue Kinder in Ihrem Score-Stapel hinzugefügt werden.

cs Seite Code: -

button.Clicked += (sender, e) => 
    { 
     App.DB.IncrementScore(); 
     lblStack.Children.Add(new Label {Text = FontAwesome.FACheck, TextColor = Color.Green, FontFamily = "FontAwesome"}); 
    }; 

xamal Code

<StackLayout Orientation="Horizontal" x:Name="lblStack"/> 

enter image description here

+0

diese ans sieht einfache lösung .. –