【问题标题】:Add multiple labels in Xamarin Forms在 Xamarin Forms 中添加多个标签
【发布时间】:2017-01-14 07:34:43
【问题描述】:

我有以下标签:

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

还有一个按钮事件:

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

每次单击按钮时,我的分数都会增加 1。我想要做的也是根据分数的数量增加 Labels 的数量。见下图:

有人知道我如何实现这一目标吗?

【问题讨论】:

  • 我强烈建议您研究一下这个应用程序的 MVVM 架构。您可以将标签绑定到 ViewMidel 中的 ObservableCollection &lt;string&gt;
  • @RobLyndon 谢谢。我知道 MVVM,但我不知道如何在这里应用它。你能给我一些与我的问题相关的代码示例吗?

标签: c# xamarin xamarin.forms


【解决方案1】:

这个问题有不同的解决方案。一定要在选择之前通读所有这些 - 我最喜欢的(最简单的)一直列出来......

方法一:

正如一些人建议的那样,您可以创建一些集合控件(我稍后会谈到),在 ViewModel 中定义一个 ObservableCollection,将 Page 的 Binding Context 设置为该 ViewModel 的一个实例,然后单击按钮将项目添加到集合中:

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);
};

ObservableCollection 的类型实际上并不重要,因为我们对所有项目使用相同的静态 ItemTemplate

<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>

这种方法的主要问题是 Xamarin.Forms ListView 无法水平显示其项目。这意味着,您需要下载可用的HorizontalListView Nuget 软件包之一,或使用built-in (only in Xamarin.Forms 2.3 and above!) CarouselView

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

然后,如果您选择使用水平 ListView,您可能希望花一些时间来移除所有用于滑动轮播和选择项目的视觉效果...

相反,有两种替代解决方案涉及更少的工作:

方法 #2:

显然,简单的方法是在代码中创建“模板”标签:

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

...向页面添加水平的StackLayout

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

...并以艰难的方式添加新标签:

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

然而,仅仅创建一个绿色复选标记列表,这一切似乎都相当老套。这导致我们...

...方法 #3:

从技术上讲,这并不完全符合您的要求(增加标签的数量),但根据您的屏幕截图,它可能会以更简单的方式满足您的需求。

删除现有标签的文本(因为它在启动时不会显示任何内容),而是给它一个唯一的名称:

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

现在,为string 类型定义一个简单的扩展方法,它将给定的字符串重复一定次数:

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

(有多种方法可以使这个 repeat 函数尽可能高效,我只是选择了最简单的单行,搜索 StackOverflow 进行详细讨论...)

您现在可以使用 XAML 中定义的单个 Label 控件,只需在单击按钮时为其分配几个复选标记:

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
};

当然,这种方法也可以适应 MMVM 方式,只需使用公共可绑定的string 属性,而不是直接设置标签的Text 属性,但为此我建议您采取看一个初学者的 MVVM 教程。

【讨论】:

  • 谢谢。我正在尝试方法#3,但我收到错误string was not recognized as a valid boolean。知道为什么吗?
  • 在哪一行抛出这个错误?此外,您能否在根据您的需要进行调整后显示确切的按钮单击处理程序?
  • 对不起,这是我的错误。我之前在修改代码时在标签中添加了IsVisible 属性,但将值留空。我将使用您的解决方案更多地处理代码,然后让您知道它何时有效。
  • 一定要使用方法#3,你会从减少标签数量中节省很多性能。可能创建 5 个标签来创建 5 个检查是多余的。这也消除了水平StackLayoutCarouselView 的需要,您可以使用Label 间距选项来放置检查。方法 3 应标记为答案,并应适当修改问题。
【解决方案2】:

只需在按钮单击事件中插入新的标签代码,这将在您的分数堆栈中添加新的子项。

cs页面代码:-

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

xamal 代码

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

【讨论】:

    【解决方案3】:

    如果分数有最大值,只需添加最大数量的标签并绑定它们的可见性。

    或者您可以创建一个标签列表视图并将源绑定到您在需要时递增的集合。

    【讨论】:

    • 我可以这样做,但它不是一个非常干净的解决方案,因为我最多有 20 分。
    【解决方案4】:

    注意:我不确定这个答案是否正确,但评论太长了。只是测试它,如果它不起作用,我将删除这个答案


    您可以通过编程方式添加控件。请记住,您需要在 MainThread 上添加 Label,因为这是对 UI 的更改。将此添加到您的 Clicked 事件中:

    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);
        });
    };
    

    如果您有Grid,您可以使用SetValueControl 方法设置Grid.RowGrid.Column

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-18
      • 2017-01-21
      • 1970-01-01
      • 2019-12-02
      • 2016-12-19
      • 2017-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多