简体   繁体   中英

Xamarin forms how to take the property from a observablecollection and put it into a CarouselView

I want to create a level selector using CarouselView displaying 6 levels per each screen scrolls. I have create a Model for a LevelCard meaning each one of the cards have their own value, I've done this because each level has a number of stars you've scored to be displayed meaning I need to have an instance of each card to update the stars for each level(card).

Ingore PopulateCardInformation method that method isn't finished nor it will be like this, I just made it for quick testing but nothing seems to work.

If you look at the last image you can see while debugging I can select the needed card but I can never actually pull the property to display as text. I've searched every where and this is what I've tried to write in Path=card1[Game] , Path=Game[card1] , Path=card1.Game , Path=Game.card1 every time I add anything to do with a property name it actually looking in my Model.NameOfProperty ... its looking for another model called Game ...

public class LevelCard
{
    public int Game { get; set; }
    public int Score { get; set; }
    public bool IsCompleted { get; set; }
}
public class LevelSelectorPopUpModel : BaseViewModel
{
    ObservableCollection<LevelCard> cards = new ObservableCollection<LevelCard>();
    public ObservableCollection<LevelCard> Cards
    {
        get => cards;
    }

    int game = 1;
    int totalGames;

    public LevelSelectorPopUpModel()
    {
        Initialize();
    }

    async void Initialize()
    {
        totalGames = await LevelReader.GetTotalGames();
        InitializeWidthHeightProperties();
        InitializeCards();
    }

    void InitializeCards()
    {
        LevelCard card1 = new LevelCard();
        LevelCard card2 = new LevelCard();
        LevelCard card3 = new LevelCard();
        LevelCard card4 = new LevelCard();
        LevelCard card5 = new LevelCard();
        LevelCard card6 = new LevelCard();

        cards.Add(card1);
        cards.Add(card2);
        cards.Add(card3);
        cards.Add(card4);
        cards.Add(card5);
        cards.Add(card6);

        PopulateCardInformation();
    }

    void PopulateCardInformation()
    {
        foreach (var card in cards)
        {
            if (totalGames < game)
                return;
            card.Game = game;
            game++;
        }
    }
}

XAML

<CarouselView ItemsSource="{Binding Cards}"
                HorizontalScrollBarVisibility="Always"
                WidthRequest="{Binding Width}"
                HeightRequest="600"
                Margin="10, 0, 10, 0"
                BackgroundColor="Red"
                HorizontalOptions="CenterAndExpand"
                VerticalOptions="CenterAndExpand">

    <CarouselView.ItemTemplate>
        <DataTemplate>
            <Grid RowSpacing="50"
                    VerticalOptions="CenterAndExpand">
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>

                <StackLayout Orientation="Horizontal"
                                WidthRequest="600"
                                HeightRequest="250"
                                BackgroundColor="Orange"
                                VerticalOptions="CenterAndExpand"
                                HorizontalOptions="CenterAndExpand"
                                Margin="0, 10, 0, 0">
                    <Label Text="{Binding Path=card1, FallbackValue='Error'}"
                            BackgroundColor="Purple"
                            WidthRequest="200"
                            HeightRequest="200" />
                    <Label Text="{Binding Path=card2, FallbackValue='Error'}"
                            BackgroundColor="Purple"
                            WidthRequest="200"
                            HeightRequest="200" />
                    <Label Text="{Binding Path=card3, FallbackValue='Error'}"
                            BackgroundColor="Purple"
                            WidthRequest="200"
                            HeightRequest="200" />
                </StackLayout>

                <StackLayout Orientation="Horizontal"
                                WidthRequest="600"
                                HeightRequest="250"
                                BackgroundColor="Orange"
                                Grid.Row="1"
                                VerticalOptions="CenterAndExpand"
                                HorizontalOptions="CenterAndExpand"
                                Margin="0, 0, 0, 10">
                    <Label BackgroundColor="Purple"
                            WidthRequest="200"
                            HeightRequest="200" />
                    <Label BackgroundColor="Purple"
                            WidthRequest="200"
                            HeightRequest="200" />
                    <Label BackgroundColor="Purple"
                            WidthRequest="200"
                            HeightRequest="200" />
                </StackLayout>
            </Grid>
        </DataTemplate>
    </CarouselView.ItemTemplate>
</CarouselView>     

在此处输入图像描述 在此处输入图像描述

A CarousalView is not the best choice to show what you want. However, you can make it work by understanding how it works. The CarousalView internally stores an item as CurrentItem . Each time you scroll it, it will change its CurrentItem to the next item. That means, the first time you see your CarousalView , its CurrentItem is the first card you added to the Cards collection. When you write {Binding card1} in the ItemTemplate it tries to find a property named card1 inside its CurrentItem , which is a Card and does not have such property. If number 6 is fixed, you create a helper class:

public class LevelCardGroup 
{
    public LevelCard Card1 { get; }
    public LevelCard Card2 { get; }
    public LevelCard Card3 { get; }
    public LevelCard Card4 { get; }
    public LevelCard Card5 { get; }
    public LevelCard Card6 { get; }

    public LevelCardGroup(LevelCard card1, LevelCard card2, LevelCard card3,
        LevelCard card4, LevelCard card5, LevelCard card6)
    {
        Card1 = card1;
        Card2 = card2;
        Card3 = card3;
        Card4 = card4;
        Card5 = card5;
        Card6 = card6;
    }
}

And change your view model to add instances of the helper class inside the Cards collection:

ObservableCollection<LevelCardGroup> cards = new ObservableCollection<LevelCardGroup>();
public ObservableCollection<LevelCardGroup> Cards
{
    get => cards;
}

void InitializeCards()
{
    LevelCard card1 = new LevelCard();
    LevelCard card2 = new LevelCard();
    LevelCard card3 = new LevelCard();
    LevelCard card4 = new LevelCard();
    LevelCard card5 = new LevelCard();
    LevelCard card6 = new LevelCard();

    cards.Add(new LevelCardGroup(card1, card2, card3, card4, card5, card6));

    PopulateCardInformation();
}

You have to change PopulateCardInformation as well. And in your view:

<Label Text="{Binding Path=Card1.Game, FallbackValue='Error'}"
    BackgroundColor="Purple"
    WidthRequest="200"
    HeightRequest="200" />

Now the CurrentItem of the CarousalView will be LevelCardGroup which contains a property named Card1 and its value has a property named Game .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM