How to get List item from CS to XAML?

VolodymyrSavchenkoVolodymyrSavchenko UAMember ✭✭✭
edited August 2016 in Xamarin.Forms

I'm new with Xamarin Xaml and want to write simple game using it to learn how to use it.
I have Grid filled by BoxView's and want to change their color to that i generating(random) in my Page.xaml.cs file and storing as List of my custom class(List). But i can't.
Can someone explain me how to do what i want to do?:D
I was trying to find some complete materials about xaml, but i found nothing.

`
<Grid.RowDefinitions>



</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView Grid.Row="0" Grid.Column="0" BindingContext="{x:Reference Name=color1}" Color="{Binding Path = Value}"></BoxView>
<BoxView Grid.Row="0" Grid.Column="1" BindingContext="GamePage" Color ="{Binding Path=color1}"></BoxView>
<BoxView Grid.Row="0" Grid.Column="2" Color="Red"></BoxView>
<BoxView Grid.Row="1" Grid.Column="0" BindingContext="GamePage" Color ="{Binding Path=cells[3].bgcolor}"></BoxView>
<BoxView Grid.Row="1" Grid.Column="1" Color="Yellow"></BoxView>
<BoxView Grid.Row="1" Grid.Column="2" BindingContext="GamePage" Color ="{Binding Path=cells[5].bgcolor}"></BoxView>

<Label Grid.Row="2" Grid.Column="0" Text="This is some random string of text to test this page and XAML" BackgroundColor="Navy" TextColor="White" FontSize="25" x:Name ="label"></Label>

<BoxView Grid.Row="2" Grid.Column="1" BindingContext="GamePage" Color="{Binding Path=cells[7].bgcolor}"></BoxView>
<BoxView Grid.Row="2" Grid.Column="2" BindingContext="{x:Reference Name=label}" Color="{Binding Path = BackgroundColor}"></BoxView>  

`

public class cell { public Color bgcolor{get; set;} public string text{get; set;} }

public static List<cell> cells{get; set;}

Tagged:

Best Answer

  • NMackayNMackay GB mod
    Accepted Answer

    Hi,

    The XAML should be

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Name="MyGamePage"
                 x:Class="FitiorXamarin.GamePage">
      <Grid BackgroundColor="White">
        <Grid.RowDefinitions>
          <RowDefinition Height="*" />
          <RowDefinition Height="*" />
          <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <BoxView Grid.Row="0" Grid.Column="0" Color="{Binding Color1, Source={x:Reference MyGamePage}}"></BoxView>
        <BoxView Grid.Row="0" Grid.Column="1" Color="{Binding Color1, Source={x:Reference MyGamePage}}"></BoxView>
        <BoxView Grid.Row="0" Grid.Column="2" Color="Red"></BoxView>
        <BoxView Grid.Row="1" Grid.Column="0" Color ="{Binding cells[0].bgcolor, Source={x:Reference MyGamePage}}"></BoxView>
        <BoxView Grid.Row="1" Grid.Column="1" Color="Yellow"></BoxView>
        <BoxView Grid.Row="1" Grid.Column="2" Color ="{Binding Path=cells[1].bgcolor, Source={x:Reference MyGamePage}}"></BoxView>
    
        <Label Grid.Row="2" Grid.Column="0" Text="This is some random string of text to test this page and XAML" BackgroundColor="Navy" TextColor="White" FontSize="25" x:Name="Mylabel"></Label>
    
        <BoxView Grid.Row="2" Grid.Column="1" Color="{Binding Path=cells[3].bgcolor, Source={x:Reference MyGamePage}}"></BoxView>
        <BoxView Grid.Row="2" Grid.Column="2" Color="{Binding BackgroundColor, Source={x:Reference Mylabel}}"></BoxView>
      </Grid>
    </ContentPage>
    

    And your code behind

    using System;
    using System.Collections.ObjectModel;
    using System.Threading.Tasks;
    
    using Xamarin.Forms;
    
    namespace FitiorXamarin
    {
        public partial class GamePage : ContentPage
        {
            public ObservableCollection<cell> cells { get; set; }
            public static Color Color1 { get; set; }
    
            Random rand = new Random();
            int r = 0;
            int g = 0;
            int b = 0;
    
            public GamePage()
            {
                Randomize();
                cells = new ObservableCollection<cell>();
                Color1 = Color.FromRgb(r, g, b);
    
                cells.Add(new cell
                {
                    text = "00",
                    bgcolor = Color.FromRgb(r, g, b),
                });
    
                Randomize();
                cells.Add(new cell
                {
                    text = "01",
                    bgcolor = Color.FromRgb(r, g, b)
                });
    
                Randomize();
                cells.Add(new cell
                {
                    text = "02",
                    bgcolor = Color.FromRgb(r, g, b)
                });
    
                Randomize();
                cells.Add(new cell
                {
                    text = "10",
                    bgcolor = Color.FromRgb(r, g, b)
                });
                InitializeComponent();
            }
    
            public void CellTapped()
            {
                Randomize();
                this.BackgroundColor = Color.FromRgb(r, g, b);
            }
    
            public class cell
            {
                public Color bgcolor { get; set; }
                public string text { get; set; }
            }
    
            private void Randomize()
            {
                r = rand.Next(0, 255);
                Task.Delay(50);
                g = rand.Next(0, 255);
                Task.Delay(50);
                b = rand.Next(0, 255);
            }
        }
    }
    
    

    I stripped out INotifyPropertyChanged as you were manually setting up the collection, it's just to demonstrate how relative source binding works. I attached what rendered on my Win10 handset.

    Hope it helps.

Answers

  • NMackayNMackay GBInsider, University mod

    @VolodymyrSavchenko

    You can bind to the page behind using relative source binding. I posted an example here

    https://forums.xamarin.com/discussion/67596/listview-itemssource-binding-in-xaml-problem

    Just make sure you populate the list before calling InitializeComponent()

    I'd recommend the MVVM approach though moving forwards and data binding.

  • VolodymyrSavchenkoVolodymyrSavchenko UAMember ✭✭✭

    @NMack``ay said:
    @VolodymyrSavchenko

    You can bind to the page behind using relative source binding. I posted an example here

    https://forums.xamarin.com/discussion/67596/listview-itemssource-binding-in-xaml-problem

    Just make sure you populate the list before calling InitializeComponent()

    I'd recommend the MVVM approach though moving forwards and data binding.

    Thanks for fast reply.
    I tryed it, but no result. I get error:
    Can't resolve name on Element

    That's what i wrote:

    <BoxView Grid.Row="1" Grid.Column="0" Color ="{Binding cells[0].bgcolor, Source={x:Reference GamePage}}"></BoxView>

    Must be becouse i'm trying to get Item in wrong way, but what is correct?

  • NMackayNMackay GBInsider, University mod

    Do you have a repo project I could have a look at?

  • VolodymyrSavchenkoVolodymyrSavchenko UAMember ✭✭✭

    @NMackay said:
    Do you have a repo project I could have a look at?

    I don't have one, but i attached this page as archive.

  • NMackayNMackay GBInsider, University mod

    Ok,

    Let me take a quick look.

  • NMackayNMackay GBInsider, University mod
    Accepted Answer

    Hi,

    The XAML should be

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Name="MyGamePage"
                 x:Class="FitiorXamarin.GamePage">
      <Grid BackgroundColor="White">
        <Grid.RowDefinitions>
          <RowDefinition Height="*" />
          <RowDefinition Height="*" />
          <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <BoxView Grid.Row="0" Grid.Column="0" Color="{Binding Color1, Source={x:Reference MyGamePage}}"></BoxView>
        <BoxView Grid.Row="0" Grid.Column="1" Color="{Binding Color1, Source={x:Reference MyGamePage}}"></BoxView>
        <BoxView Grid.Row="0" Grid.Column="2" Color="Red"></BoxView>
        <BoxView Grid.Row="1" Grid.Column="0" Color ="{Binding cells[0].bgcolor, Source={x:Reference MyGamePage}}"></BoxView>
        <BoxView Grid.Row="1" Grid.Column="1" Color="Yellow"></BoxView>
        <BoxView Grid.Row="1" Grid.Column="2" Color ="{Binding Path=cells[1].bgcolor, Source={x:Reference MyGamePage}}"></BoxView>
    
        <Label Grid.Row="2" Grid.Column="0" Text="This is some random string of text to test this page and XAML" BackgroundColor="Navy" TextColor="White" FontSize="25" x:Name="Mylabel"></Label>
    
        <BoxView Grid.Row="2" Grid.Column="1" Color="{Binding Path=cells[3].bgcolor, Source={x:Reference MyGamePage}}"></BoxView>
        <BoxView Grid.Row="2" Grid.Column="2" Color="{Binding BackgroundColor, Source={x:Reference Mylabel}}"></BoxView>
      </Grid>
    </ContentPage>
    

    And your code behind

    using System;
    using System.Collections.ObjectModel;
    using System.Threading.Tasks;
    
    using Xamarin.Forms;
    
    namespace FitiorXamarin
    {
        public partial class GamePage : ContentPage
        {
            public ObservableCollection<cell> cells { get; set; }
            public static Color Color1 { get; set; }
    
            Random rand = new Random();
            int r = 0;
            int g = 0;
            int b = 0;
    
            public GamePage()
            {
                Randomize();
                cells = new ObservableCollection<cell>();
                Color1 = Color.FromRgb(r, g, b);
    
                cells.Add(new cell
                {
                    text = "00",
                    bgcolor = Color.FromRgb(r, g, b),
                });
    
                Randomize();
                cells.Add(new cell
                {
                    text = "01",
                    bgcolor = Color.FromRgb(r, g, b)
                });
    
                Randomize();
                cells.Add(new cell
                {
                    text = "02",
                    bgcolor = Color.FromRgb(r, g, b)
                });
    
                Randomize();
                cells.Add(new cell
                {
                    text = "10",
                    bgcolor = Color.FromRgb(r, g, b)
                });
                InitializeComponent();
            }
    
            public void CellTapped()
            {
                Randomize();
                this.BackgroundColor = Color.FromRgb(r, g, b);
            }
    
            public class cell
            {
                public Color bgcolor { get; set; }
                public string text { get; set; }
            }
    
            private void Randomize()
            {
                r = rand.Next(0, 255);
                Task.Delay(50);
                g = rand.Next(0, 255);
                Task.Delay(50);
                b = rand.Next(0, 255);
            }
        }
    }
    
    

    I stripped out INotifyPropertyChanged as you were manually setting up the collection, it's just to demonstrate how relative source binding works. I attached what rendered on my Win10 handset.

    Hope it helps.

  • VolodymyrSavchenkoVolodymyrSavchenko UAMember ✭✭✭
    edited August 2016

    @NMackay said:
    Hi,

    The XAML should be

    Thanks alot.
    I checked it and getting values from ObservableCollection works just great. but not from Color1 value. I hardcoded it to Red, but it returns White anyway. Any ideas?

    UPD:
    It was because "static" attribute. After removing it everything is fine.
    Thanks a lot!

  • NMackayNMackay GBInsider, University mod

    @VolodymyrSavchenko

    I think it's because your binding to a static.

    try changing your XAML to:

    <BoxView Grid.Row="0" Grid.Column="0" Color="{x:Static GamePage.Color1}"></BoxView>

    And in your XAML namespaces

    xmlns:color="clr-namespace:FitiorXamarin"

  • VolodymyrSavchenkoVolodymyrSavchenko UAMember ✭✭✭
    edited August 2016

    @NMackay

    Just wondering if you also can help me with EventHandlers. For example i wand to call CellTapped method in *.xaml.cs part of page when BoxView is tapped.

    Method looks like this:
    public void CellTapped(object sender, ValueChangedEventArgs args) { Randomize(); cells[ 0 ].bgcolor = Color.FromRgb(r, g, b); }

    I'm trying to call it from XAML like this:

    <BoxView.GestureRecognizers> <TapGestureRecognizer BindingContext="GamePage" Command="{Binding CellTapped}"></TapGestureRecognizer> </BoxView.GestureRecognizers>

    UPD:
    Now i can call EventHandler, but nothing happends on form. But i want to change color of tapped BoxView.

    Here's how XAML looks like now:

    <BoxView.GestureRecognizers> <TapGestureRecognizer Tapped ="CellTapped"></TapGestureRecognizer> </BoxView.GestureRecognizers>

    And code:

    public void CellTapped(object sender, EventArgs args) { Randomize(); cells[ 0 ].bgcolor = Color.FromRgb(r, g, b); }

  • NMackayNMackay GBInsider, University mod

    @VolodymyrSavchenko

    Your command example won't work as your calling a method and not a command that that implements the ICommand interface, also your page has no binding context so the gesture has nowhere to look for the command instance.

    The cell isn't changing because your page binds once when it initialises. Your page would have to implement INotifyPropertyChanged and you'd have to Raise the property changed to notify the page it's binding has changed. MVVM Frameworks like MVVMLight, MVVM Cross etc make this easy to implement but it can all be done in Forms.

    I'd recommend reading up on binding and try the samples out there.

    https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_binding_basics/

    If you want an MVVM sample then drop me a PM, I'd recommend getting comfortable with the data binding concepts 1st though.

Sign In or Register to comment.