OnApplyTemplate doesn't capture the BindingContext of the parent? - xamarin.forms

In a test project, I'm trying to get the BindingContext of the parent control with template binding,
here, in the MainPage, I have two templates temp1 and temp2
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:MyXam.ViewModels"
xmlns:views="clr-namespace:MyXam.Views"
x:Class="MyXam.Views.MainPage"
x:DataType="vm:MainViewModel">
<ContentPage.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="temp1">
<views:View1/>
</ControlTemplate>
<ControlTemplate x:Key="temp2">
<views:View2/>
</ControlTemplate>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout x:Name="stk">
<Button Text="Switch view" Command="{Binding SwitchViewCommand}"/>
<ContentView x:Name="cv" ControlTemplate="{StaticResource temp2}" VerticalOptions="Start" HorizontalOptions="Center">
<ContentView.Triggers>
<DataTrigger TargetType="ContentView" Binding="{Binding IsView1}" Value="False">
<Setter Property="ControlTemplate" Value="{StaticResource temp2}"/>
</DataTrigger>
<DataTrigger TargetType="ContentView" Binding="{Binding IsView1, Mode=TwoWay}" Value="True">
<Setter Property="ControlTemplate" Value="{StaticResource temp1}"/>
</DataTrigger>
</ContentView.Triggers>
</ContentView>
</StackLayout>
</ContentPage>
I want to get the BindingContext of the MainPage in View2, in the ctor:
SetBinding(BindingContextProperty, new Binding("Parent.BindingContext", source: RelativeBindingSource.TemplatedParent));
but when I try to get its vzlue in the OnApplyTemplate it's null:
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
vm = this.GetValue(BindingContextProperty);
}
However binding is resolved in xaml:
<Label Text="{Binding Name, Source={Reference this}}"/>

I couldn't see the detail of your other code, but you can refer to the following code.
Define a BindableProperty for this Label in xaml.cs and use the Name Property,e.g. x:Name="TestControlView" and binding like this
<Label Text="{Binding Source={x:Reference TestControlView}, Path=TestText}" />
You can check the full demo here.
The main code is like this:
TestControl.xaml.cs(TestControl is a ContentView)
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TestControl : ContentView
{
public static readonly BindableProperty TestTextProperty = BindableProperty.Create(nameof(TestText), typeof(string), typeof(TestControl));
public string TestText
{
get { return (string)GetValue(TestTextProperty); }
set { SetValue(TestTextProperty, value); }
}
public TestControl()
{
InitializeComponent();
}
}
TestControl.xaml
MainPage.xaml
<ListView x:Name="lstView" HorizontalOptions="Fill" HasUnevenRows="True" RefreshAllowed="true" IsPullToRefreshEnabled="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame CornerRadius="10" BackgroundColor="White" Margin="0,5,0,5">
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
<controls:TestControl TestText="{Binding Title}" VerticalOptions="Center"/>
<Label Text="{Binding Type}" FontSize="Medium" TextColor="#F0BB7F" FontAttributes="Bold" VerticalOptions="Center"/>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public ObservableCollection<TestModel> veggies { get; set; }
public MainPage()
{
InitializeComponent();
veggies = new ObservableCollection<TestModel>();
veggies.Add(new TestModel { Title = "Tomato", Type = "Fruit" });
veggies.Add(new TestModel { Title = "Zucchini", Type = "Vegetable" });
veggies.Add(new TestModel { Title = "Tomato" , Type = "Vegetable" });
veggies.Add(new TestModel { Title = "Romaine", Type = "Fruit" });
veggies.Add(new TestModel { Title = "Zucchini", Type = "Vegetable" });
lstView.ItemsSource = veggies;
BindingContext = this;
}
}

Related

Can't get the CollectionView to Display data in my collection

I am trying to make a collectionView display the items in a collection I have created but that doe snot work at all. I have been looking around to understand the issue but I can't figure it out. Can someone help me out ? See below the XAML code for a custom control I created and following it the code behind in c#
'''
<StackLayout xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomControls.CustomControl.DataGrid2"
xmlns:local="clr-namespace:CustomControls.CustomControl"
HeightRequest="500"
WidthRequest="500"
Orientation="Horizontal">
<CollectionView x:Name="c2" ItemsLayout="VerticalList" x:DataType="local:DataGrid2" ItemsSource="{Binding Data2see}" >
<CollectionView.Header>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="Small"
FontAttributes="Bold" />
</StackLayout>
</CollectionView.Header>
<CollectionView.Footer>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Xamarin Monkey"
FontSize="Small"
FontAttributes="Bold" />
</StackLayout>
</CollectionView.Footer>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:SomeDataExemple2">
<Grid Padding="10" ColumnDefinitions="100,100,100">
<Button Grid.Column="0" Text ="clickmenow2"/>
<Entry Grid.Column= "1" Text="{Binding Name}"/>
<Entry Grid.Column="2" Text="{Binding First_name}"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
namespace CustomControls.CustomControl
{ using System.Collections.Specialized;
using System.Collections.Generic;
using System.Collections;
using System.Collections.ObjectModel;
public partial class DataGrid2 : StackLayout
{
public DataGrid2()
{
Data2see = new Collection<SomeDataExemple2>();
Data2see.Add(new SomeDataExemple2("hamid", "britel"));
Data2see.Add(new SomeDataExemple2("mernissi", "wadie"));
Data2see.Add(new SomeDataExemple2("mhamed", "chraibi"));
Data2see.Add(new SomeDataExemple2("yazid", "alaoui"));
Data2see.Add(new SomeDataExemple2("amine", "gogole"));
Data2see.Add(new SomeDataExemple2("mehdi", "harras"));
InitializeComponent();
//c2.ItemsSource = Data;
}
public Collection<SomeDataExemple2> Data2see
{
get;
set;
}
}
public class SomeDataExemple2
{
public SomeDataExemple2(string name1, string name2)
{
Name = name1;
First_name = name2;
}
public string Name
{
get; set;
}
public string First_name
{
get;
set;
}
}}
.xaml code, you can use ContentPage instead of StackLayout
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp_test.MainPage"
xmlns:local="clr-namespace:MauiApp_test"
HeightRequest="500"
WidthRequest="500">
<CollectionView x:Name="c2" ItemsLayout="VerticalList" >
<CollectionView.Header>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="Small"
FontAttributes="Bold" />
</StackLayout>
</CollectionView.Header>
<CollectionView.Footer>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Xamarin Monkey"
FontSize="Small"
FontAttributes="Bold" />
</StackLayout>
</CollectionView.Footer>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10" ColumnDefinitions="100,100,100">
<Button Grid.Column="0" Text ="clickmenow2"/>
<Entry Grid.Column= "1" Text="{Binding Name}"/>
<Entry Grid.Column="2" Text="{Binding First_name}"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
.xaml.cs
using System.Collections.ObjectModel;
namespace MauiApp_test;
public partial class MainPage : ContentPage
{
public Collection<SomeDataExemple2> Data2see
{
get;
set;
}
public MainPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
Data2see = new Collection<SomeDataExemple2>();
Data2see.Add(new SomeDataExemple2("hamid", "britel"));
Data2see.Add(new SomeDataExemple2("mernissi", "wadie"));
Data2see.Add(new SomeDataExemple2("mhamed", "chraibi"));
Data2see.Add(new SomeDataExemple2("yazid", "alaoui"));
Data2see.Add(new SomeDataExemple2("amine", "gogole"));
Data2see.Add(new SomeDataExemple2("mehdi", "harras"));
c2.ItemsSource = Data2see
.ToList();
}
public class SomeDataExemple2
{
public SomeDataExemple2(string name1, string name2)
{
Name = name1;
First_name = name2;
}
public string Name
{
get; set;
}
public string First_name
{
get;
set;
}
}
}

Xamarin.Forms Why is my tap command not working?

I have this kind of tap command in my carousel view:
<Image
x:Name="img_adPic"
HeightRequest="150"
Aspect="AspectFill"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Source="{Binding thumbnail}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.TapCommand, Source={x:Reference page}}" CommandParameter="{Binding Path=BindingContext.CurrentIndex, Source={x:Reference page}}"/>
</Image.GestureRecognizers>
</Image>
I gave my contentpage a name :
<ContentPage x:Name="page" >
Now in my class:
public ICommand CarouselItemTapped{ get; set; }
public Page_MainMenuDetail()
{
InitializeComponent();
CarouselItemTapped = new Xamarin.Forms.Command((selectItem) =>
{
});
instance = this;
}
But no matter what I try, the command is NEVER fired. I think i did everything as in the tutorials, why is this not working?
Thank you
You could refer to the code below about how to use the TapCommand. The command would be triggled when you tap on the image.
Xaml:
<ContentPage.Content>
<AbsoluteLayout>
<CarouselView
x:Name="carouselView"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
IndicatorView="indicatorview">
<CarouselView.ItemTemplate>
<DataTemplate>
<Image
x:Name="img_adPic"
Aspect="AspectFill"
HeightRequest="150"
HorizontalOptions="FillAndExpand"
Source="{Binding .}"
VerticalOptions="FillAndExpand">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.TapCommand, Source={x:Reference page}}" />
</Image.GestureRecognizers>
</Image>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView
x:Name="indicatorview"
AbsoluteLayout.LayoutBounds=" 0.5,0.95,100,100"
AbsoluteLayout.LayoutFlags=" PositionProportional"
IndicatorColor=" LightGray"
IndicatorSize=" 10"
SelectedIndicatorColor=" Black" />
</AbsoluteLayout>
</ContentPage.Content>
Code behind:
public partial class Page2 : ContentPage
{
public ICommand CarouselItemTapped { get; set; }
public ICommand TapCommand { get; set; }
public Page2()
{
InitializeComponent();
var list = new List<string>
{
"pink.jpg",
"pink.jpg",
"pink.jpg",
"pink.jpg",
"pink.jpg",
};
carouselView.ItemsSource = list;
//CarouselItemTapped = new Xamarin.Forms.Command((selectItem) =>
//{
//});
//instance = this;
TapCommand = new Command(commandEvent);
this.BindingContext = this;
}
public void commandEvent()
{
}
}

How paint a item selected with differents colors?

i have a collection
<CollectionView SelectionMode="Single"
ItemsSource="{Binding Cities}"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Margin="5">
<Image Source="{Binding Image}" />
<Label TextColor="Black" text="Text"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
How can i painting with diferents colors the image and label when i select a item?
According to your description, you have Image and Label in CollectionView DataTemplate, you want to set Image and Label different background color when you select one item, am I right?
If yes, I suggest you can use binding Background color to do this, please take a look my code:
<ContentPage.Resources>
<Style TargetType="StackLayout">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<CollectionView
ItemsSource="{Binding images}"
SelectionChanged="CollectionView_SelectionChanged"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Margin="5">
<Frame BackgroundColor="{Binding imagecolor}" CornerRadius="5">
<Image Source="{Binding Image}" />
</Frame>
<Label
BackgroundColor="{Binding labelcolor}"
Text="{Binding cityname}"
TextColor="Black" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage.Content>
public partial class Page3 : ContentPage
{
public ObservableCollection<imagemodel> images { get; set; }
public Page3()
{
InitializeComponent();
images = new ObservableCollection<imagemodel>()
{
new imagemodel(){Image="a5.jpg",cityname="beijing",imagecolor=Color.White,labelcolor=Color.White},
new imagemodel(){Image="a6.jpg",cityname="shanghai",imagecolor=Color.White,labelcolor=Color.White},
new imagemodel(){Image="a7.jpg",cityname="shenzhen",imagecolor=Color.White,labelcolor=Color.White},
new imagemodel(){Image="a8.jpg",cityname="xiamen",imagecolor=Color.White,labelcolor=Color.White}
};
this.BindingContext = this;
}
private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
imagemodel previous = (e.PreviousSelection.FirstOrDefault() as imagemodel);
imagemodel current = (e.CurrentSelection.FirstOrDefault() as imagemodel);
//Set the current to the color you want
current.imagecolor = Color.Pink;
current.labelcolor = Color.Green;
if (previous != null)
{
//Reset the previous to defaulr color
previous.imagecolor = Color.White;
previous.labelcolor = Color.White;
}
}
}
public class imagemodel:ViewModelBase
{
public string Image { get; set; }
public string cityname { get; set; }
private Color _imagecolor;
public Color imagecolor
{
get { return _imagecolor; }
set
{
_imagecolor = value;
RaisePropertyChanged("imagecolor");
}
}
private Color _labelcolor;
public Color labelcolor
{
get { return _labelcolor; }
set
{
_labelcolor = value;
RaisePropertyChanged("labelcolor");
}
}
}
The ViewModelbase implement INotifyPropertyChanged interface:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Update:
If you want to use mvvm mode to do this, and put CollectionView_SelectionChanged method in my viewModel, I suggest you can bind SelectionChangedCommand to do this, please take a look my code:
The ContentPage:
<ContentPage.Resources>
<Style TargetType="StackLayout">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<CollectionView
ItemsSource="{Binding images}"
SelectedItem="{Binding CurrentSelection}"
SelectionChangedCommand="{Binding selectioncommand}"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Margin="5">
<Frame BackgroundColor="{Binding imagecolor}" CornerRadius="5">
<Image Source="{Binding Image}" />
</Frame>
<Label
BackgroundColor="{Binding labelcolor}"
Text="{Binding cityname}"
TextColor="Black" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage.Content>
public partial class Page3 : ContentPage
{
public Page3()
{
InitializeComponent();
this.BindingContext = new imageviewmodel();
}
}
The imageviewmodel.cs:
public class imageviewmodel:ViewModelBase
{
public ObservableCollection<imagemodel> images { get; set; }
private imagemodel _PreviousSelection;
public imagemodel PreviousSelection
{
get { return _PreviousSelection; }
set
{
_PreviousSelection = value;
RaisePropertyChanged("PreviousSelection");
}
}
private imagemodel _CurrentSelection;
public imagemodel CurrentSelection
{
get { return _CurrentSelection; }
set
{
if(CurrentSelection!=value)
{
PreviousSelection = CurrentSelection;
_CurrentSelection = value;
RaisePropertyChanged("CurrentSelection");
}
}
}
public Command selectioncommand { get; set; }
public imageviewmodel()
{
images = new ObservableCollection<imagemodel>()
{
new imagemodel(){Image="a5.jpg",cityname="beijing",imagecolor=Color.White,labelcolor=Color.White},
new imagemodel(){Image="a6.jpg",cityname="shanghai",imagecolor=Color.White,labelcolor=Color.White},
new imagemodel(){Image="a7.jpg",cityname="shenzhen",imagecolor=Color.White,labelcolor=Color.White},
new imagemodel(){Image="a8.jpg",cityname="xiamen",imagecolor=Color.White,labelcolor=Color.White}
};
selectioncommand = new Command(changecolor);
}
private void changecolor()
{
foreach(imagemodel model in images)
{
if(model.cityname==CurrentSelection.cityname)
{
model.imagecolor = Color.Pink;
model.labelcolor = Color.Green;
}
else if(PreviousSelection != null && model.cityname==PreviousSelection.cityname)
{
model.imagecolor = Color.White;
model.labelcolor = Color.White;
}
}
}
}
The screenshot is same.
The screenshot:

Xamarin Forms TemplateBinding to Command In BasePage

I have a BasePage created using ControlTemplates that contains a loading overlay for each child to use - This overlay has a "cancel" button on it, but for some reason I can't get ICommands to execute when I tap the buttons. Clicked events work fine but I'd like to understand what the problem is with Commands.
I researched the issue and found I should be binding using Command="{TemplateBinding MyCommand}" since my content is within a ControlTemplate but still no luck, however I am also binding the Text property and this is working fine, so I'm a bit confused.
Here's a cut down version of what I've hacked together.
Here's my BasePage XAML with the button in question:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage x:Name="this" NavigationPage.HasNavigationBar="False" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:helpers="clr-namespace:ShoppingListNEW.MarkupExtensions" xmlns:views="clr-namespace:ShoppingListNEW.Views" x:Class="ShoppingListNEW.Pages.BasePage">
<ContentPage.ControlTemplate>
<ControlTemplate>
<Grid Padding="0" RowSpacing="0" ColumnSpacing="0">
<StackLayout>
<StackLayout.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0,30,0,0"/>
</StackLayout.Padding>
<ScrollView VerticalOptions="FillAndExpand" >
<StackLayout RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}" RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height}" Orientation="Vertical">
<ContentPresenter />
</StackLayout>
</ScrollView>
</StackLayout>
<AbsoluteLayout IsVisible="False" Grid.Row="0" Grid.Column="0" x:Name="loading" BackgroundColor="#85000000" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<ActivityIndicator Color="Lime" Scale="2" IsRunning="true" IsEnabled="true" IsVisible="true" AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="0.5,0.4" />
<Button IsVisible="True" Text="{TemplateBinding MyTextLabel}" AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="0.5,0.5" Command="{TemplateBinding MyCommand}" />
</AbsoluteLayout>
</Grid>
</ControlTemplate>
</ContentPage.ControlTemplate>
</ContentPage>
And here's the C# for that BasePage:
using System;
using System.Windows.Input;
using ShoppingListNEW.Views;
using Xamarin.Forms;
namespace ShoppingListNEW.Pages
{
public partial class BasePage : ContentPage
{
public string MyTextLabel { get; set; } = "This Works";
public ICommand MyCommand { get; set; }
public BasePage()
{
InitializeComponent();
MyCommand = new Command(() =>
{
Console.Write("But this doesn't work :(");
});
}
public void ShowHideLoading(bool showhide, bool allowCancel = false)
{
var loadingLayout = (AbsoluteLayout)GetTemplateChild("loading");
var cancelButton = loadingLayout.FindByName<Button>("btnCancel");
cancelButton.IsVisible = allowCancel;
loadingLayout.IsVisible = showhide;
}
}
}
Any ideas?
On your ControlTemplate binding, please use the following code:
<Button
AbsoluteLayout.LayoutBounds="0.5,0.5"
AbsoluteLayout.LayoutFlags="PositionProportional"
Command="{TemplateBinding BindingContext.MyCommand}"
IsVisible="True"
Text="{TemplateBinding BindingContext.MyTextLabel}" />
I use your code to create simple that you can take a look, please don't set AbsoluteLayout IsVisible="False".
<ContentPage.ControlTemplate>
<ControlTemplate>
<Grid Padding="0">
<StackLayout>
<ScrollView VerticalOptions="FillAndExpand">
<StackLayout
Orientation="Vertical"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Width}">
<ContentPresenter />
</StackLayout>
</ScrollView>
</StackLayout>
<AbsoluteLayout
x:Name="loading"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="#85000000">
<ActivityIndicator
AbsoluteLayout.LayoutBounds="0.5,0.4"
AbsoluteLayout.LayoutFlags="PositionProportional"
IsEnabled="true"
IsRunning="true"
IsVisible="true"
Scale="2"
Color="Lime" />
<Button
AbsoluteLayout.LayoutBounds="0.5,0.5"
AbsoluteLayout.LayoutFlags="PositionProportional"
Command="{TemplateBinding BindingContext.MyCommand}"
IsVisible="True"
Text="{TemplateBinding BindingContext.MyTextLabel}" />
</AbsoluteLayout>
</Grid>
</ControlTemplate>
</ContentPage.ControlTemplate>
public partial class Page19 : ContentPage
{
public Page19()
{
InitializeComponent();
this.BindingContext = new Viewmodel1();
}
}
public class Viewmodel1:ViewModelBase
{
private string _MyTextLabel;
public string MyTextLabel
{
get { return _MyTextLabel; }
set
{
_MyTextLabel = value;
RaisePropertyChanged("MyTextLabel");
}
}
public RelayCommand MyCommand { get; set; }
public Viewmodel1()
{
MyCommand = new RelayCommand(method);
MyTextLabel = "this is test";
}
private void method()
{
Console.WriteLine("this is test!");
}
}
Problem solved. Thanks to Mikolaj Kieres for the answer, it was a simple case of initialising the Command earlier so I moved it up above the InitializeComponent and that kicked it into life. Thanks!

My Application is not working after added custom behavior, cant understand why

I have created a custom stepper Behavior, and added that behavior to a stepper in my xaml, but for some reason after adding the behavior the application doesn't compile, and i get this error:
Position 82:87. No property, bindable property, or event found for 'ValueChangedCommand', or mismatching type between value and property. (ComanderoMovil)
here is my code of the behavior:
using System;
using System.Windows.Input;
using Xamarin.Forms;
namespace ComanderoMovil.Behaviors
{
public class StepperQuantityChangedBehavior : Behavior<Stepper>
{
public static readonly BindableProperty StepperValueChangedProperty =
BindableProperty.Create("ValueChangedCommand", typeof(ICommand), typeof(StepperQuantityChangedBehavior), null);
public ICommand ValueChangedCommand
{
get
{
return (ICommand)GetValue(StepperValueChangedProperty);
}
set
{
SetValue(StepperValueChangedProperty, value);
}
}
protected override void OnAttachedTo(Stepper bindable)
{
base.OnAttachedTo(bindable);
bindable.ValueChanged += Bindable_ValueChanged;
}
protected override void OnDetachingFrom(Stepper bindable)
{
base.OnDetachingFrom(bindable);
bindable.ValueChanged -= Bindable_ValueChanged;
}
private void Bindable_ValueChanged(object sender, ValueChangedEventArgs e)
{
if (ValueChangedCommand == null)
{
return;
}
var stepper = sender as Stepper;
var prueba = e.NewValue;
if (ValueChangedCommand.CanExecute(prueba))
{
ValueChangedCommand.Execute(prueba);
}
}
}
}
and here is my code of the xaml where I add the behavior:
<?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="ComanderoMovil.Views.DishView"
xmlns:converterPack="clr-namespace:Xamarin.Forms.ConvertersPack;assembly=Xamarin.Forms.ConvertersPack"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.UseSafeArea="true"
xmlns:local="clr-namespace:ComanderoMovil.Behaviors"
x:Name="DishSelectedPage">
<ContentPage.ToolbarItems>
<ToolbarItem Icon="shopping_cart" Text="Search" Command="{Binding ShowCartCommand}" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
<ResourceDictionary>
<converterPack:CurrencyConverter x:Key="CurrencyConverter"></converterPack:CurrencyConverter>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<ScrollView>
<StackLayout>
<Label Text="{Binding Dish.Name}"
FontSize="Title"
HorizontalOptions="Center"
FontAttributes="Bold"></Label>
<Label Text="Precio"
FontSize="Subtitle"
HorizontalOptions="Center"
FontAttributes="Bold"></Label>
<Label Text="{Binding Dish.Price1, Converter={StaticResource CurrencyConverter}}"
FontSize="Subtitle"
HorizontalOptions="Center"></Label>
<Label Text="Modificadores"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"></Label>
<ListView ItemsSource="{Binding DishesMods}"
x:Name="ModsListView"
HasUnevenRows="True"
SeparatorVisibility="Default"
SeparatorColor="Black"
IsGroupingEnabled="True"
HeightRequest="{Binding ListHeight}">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell Height="30">
<StackLayout VerticalOptions="FillAndExpand"
Padding="10"
BackgroundColor="DimGray">
<Label Text="{Binding Key}"
TextColor="White"
VerticalOptions="Center"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="20">
<StackLayout Orientation="Horizontal">
<CheckBox Color="#102536">
<CheckBox.Behaviors>
<local:CheckBoxModChangedState ItemCheckedCommand="{Binding BindingContext.SelectedModCommand, Source={Reference DishSelectedPage}}"></local:CheckBoxModChangedState>
</CheckBox.Behaviors>
</CheckBox>
<Label Text="{Binding Name}"
VerticalOptions="Center"></Label>
<Label Text="Precio:"
VerticalOptions="Center"></Label>
<Label Text="{Binding Price}"
VerticalOptions="Center"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Cantidad: "></Label>
<Label Text="1"></Label>
</StackLayout>
<StackLayout>
<Stepper HeightRequest="40"
WidthRequest="40">
<Stepper.Behaviors>
<local:StepperQuantityChangedBehavior ValueChangedCommand="{Binding BindingContext.ModQuantityCommand, Source={Reference DishSelectedPage}}"></local:StepperQuantityChangedBehavior>
</Stepper.Behaviors>
</Stepper>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<ContentView>
<Frame HasShadow="False"
Padding="50">
<Button Padding="20"
Text="Agregar Orden"
TextColor="White"
BackgroundColor="#102536"
Command="{Binding BindingContext.AddOrderCommand, Source={Reference DishSelectedPage}}"></Button>
</Frame>
</ContentView>
</ListView.Footer>
</ListView>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
the funny thing is that, I have added custom behavior for other controls, like the checkbox, and it works without a problem, but only with this new behavior I am having trouble.
Anyone know's what is happening?
public static readonly BindableProperty StepperValueChangedProperty
public ICommand ValueChangedCommand
the issue is on the lines,as the error message said
event found for 'ValueChangedCommand', or mismatching type between
value and property. (ComanderoMovil)
you should change StepperValueChangedProperty to ValueChangedCommandProperty to keep the name consistent with ValueChangedCommand
change
public static readonly BindableProperty StepperValueChangedProperty =
BindableProperty.Create("ValueChangedCommand", typeof(ICommand), typeof(StepperQuantityChangedBehavior), null);
public ICommand ValueChangedCommand
{
get
{
return (ICommand)GetValue(StepperValueChangedProperty);
}
set
{
SetValue(StepperValueChangedProperty, value);
}
}
to
public static readonly BindableProperty ValueChangedCommandProperty =
BindableProperty.Create("ValueChangedCommand", typeof(ICommand), typeof(StepperQuantityChangedBehavior), null);
public ICommand ValueChangedCommand
{
get
{
return (ICommand)GetValue(ValueChangedCommandProperty);
}
set
{
SetValue(ValueChangedCommandProperty, value);
}
}

Resources