N. Smeding
N. Smeding

Reputation: 394

Can't set properties on nested classes from Xaml

The error that Xamarin gives back: Type Foo not found in xmlns clr-namespace:AmsterdamTheMapV3

The problem is that I am trying to define Foo but whatever I do it doenst work. I think that the problem is inside the xmls:local namespace. Maybe I make a stupid mistake inside my code.

This is a Xamarin.forms project for windows, android and apple.

Xaml file:

<?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:Class="AmsterdamTheMapV3.CityGuide"
             xmlns:local="clr-namespace:AmsterdamTheMapV3">
  <Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />
  <ScrollView Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
    <StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"  Spacing="0">

      <!-- Button1 -->
      <Image
          x:Name="CityGuideButton1"
          Source="shopping_gray.png"
          Aspect="Fill"
          HorizontalOptions="FillAndExpand"
                VerticalOptions ="FillAndExpand"
          local:Foo.Tag="button1">
        <Image.GestureRecognizers>
          <TapGestureRecognizer
            Tapped="Categorie_Onclick"
            NumberOfTapsRequired="1"/>
        </Image.GestureRecognizers>
      </Image>
    </StackLayout>
  </ScrollView>
</ContentPage>

Cs file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;

namespace AmsterdamTheMapV3
{
    public partial class CityGuide : ContentPage
    {
        public CityGuide()
        {
            InitializeComponent();
        }

         public class Foo
        {
            public static readonly BindableProperty TagProperty = BindableProperty.Create("Tag", typeof(string), typeof(Foo), null);

            public static string GetTag(BindableObject bindable)
            {
                return (string)bindable.GetValue(TagProperty);
            }

            public static void SetTag(BindableObject bindable, string value)
            {
                bindable.SetValue(TagProperty, value);
            }
        }


        async void Categorie_Onclick(Object sender, EventArgs args)
        {
            Image cmd = sender as Image;
            string txt = Foo.GetTag(cmd);
            await Navigation.PushAsync(new CategoriePage(txt));
        }
    }
}

I hope that somewann can help me.
I can give more info if needed.
thank you in advance!

Upvotes: 4

Views: 1645

Answers (2)

Stephane Delcroix
Stephane Delcroix

Reputation: 16232

You can't reference nested classes from Xaml.

You can quote me on this, or google it, but this is an universal truth. The reason is that Xaml Parsers would not be able to differentiate an Attached (Bindable|Dependency)Property from a nested class access, based on the dot sign.

In your case, move your Foo class from within CityGuide directly to the namespace and it should work.

Your xmlns declaration xmlns:local="clr-namespace:AmsterdamTheMapV3" is correct without the assembly= part as you are referring to the current assembly.

More info on a similar answer:https://stackoverflow.com/a/14546917/1063783

Some might ask why not use the + sign for nested class (like it's done in Reflection). The problem is that an a name containing a + sign is not a valid xml-element name (https://www.xml.com/pub/a/2001/07/25/namingparts.html)

Upvotes: 10

Bruno Caceiro
Bruno Caceiro

Reputation: 7199

You are missing the assembly reference.

xmlns:local="clr-namespace:AmsterdamTheMapV3; assembly=AmsterdamTheMapV3">

From Xamarin:

To access classes local to the shared application PCL, such as AppConstants, XAML programmers often use the prefix local. The namespace declaration must indicate the CLR (Common Language Runtime) namespace name (also known as the .NET namespace name, which is the name that appears in a C# namespace definition or in a using directive) and the assembly containing the code.

Upvotes: -1

Related Questions