Reputation: 93
I'm trying to create a ContentPage
that contains a TabView
from XamarinCommunityToolkit
.
Lets say that the Tabs define an ObservableCollection
of Categories, and every TabViewItem
should load a ContentView and passes a GroupId as an Argument / Property, and then I use that GroupId to filter Products list.
What's the best way to passe an argument to the ContentView ?
Update :
I've tried to use BindablePropertiy but, in the debugger, I can see the newValue recieved, but nothing shows in the Label :
MainPage.xaml
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
mc:Ignorable="d"
x:Class="mynamespace.Views.MainPage"
Title="{Binding Title}"
xmlns:local="clr-namespace:mynamespace.Views"
xmlns:vm="clr-namespace:mynamespace.ViewModels"
xmlns:model="clr-namespace:mynamespace.Models"
x:Name="MainPage">
<ContentPage.Content>
<xct:TabView Grid.Row="0"
TabStripPlacement="Top"
TabStripBackgroundColor="White"
TabStripHeight="48"
TabIndicatorColor="Orange"
TabIndicatorHeight="2"
TabItemsSource="{Binding Categories}">
<xct:TabView.TabViewItemDataTemplate>
<DataTemplate>
<Grid>
<Label Text="{Binding Name}"
FontAttributes="Bold"
VerticalOptions="Center"
Padding="6, 0"/>
</Grid>
</DataTemplate>
</xct:TabView.TabViewItemDataTemplate>
<xct:TabView.TabContentDataTemplate>
<DataTemplate>
<local:GroupView GroupId="{Binding Id}" />
</DataTemplate>
</xct:TabView.TabContentDataTemplate>
</xct:TabView>
</ContentPage.Content>
GroupView.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace mynamespace.Views
{
public partial class GroupView : ContentView
{
public string GroupId
{
get { return (string)GetValue(GroupIdProperty); }
set { SetValue(GroupIdProperty, value); }
}
public static readonly BindableProperty GroupIdProperty = BindableProperty.Create(
nameof(GroupId),
typeof(string),
typeof(GroupView),
"Default_V",
defaultBindingMode: BindingMode.OneWay,
propertyChanged: GroupIdChanged
);
private static void GroupIdChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (ProductListPage)bindable;
control.GroupId = newValue?.ToString();
}
public GroupView()
{
InitializeComponent();
BindingContext = this;
}
}
}
GroupView.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="mynamespace.Views.GroupView">
<ContentView.Content>
<StackLayout>
<Label Text="{Binding GroupId}" /> <!-- Shows nothing -->
</StackLayout>
</ContentView.Content>
</ContentView>
Category class :
public class Category
{
private string id;
private string name;
private string description;
public string Id { get => id; set => id = value; }
public string Name { get => name; set => name = value; }
public string Description { get => description; set => description = value; }
}
ProductListViewModel.cs
public class ProductListViewModel : BaseViewModel
{
public string GroupId { get; set; }
public ProductListViewModel()
{
}
public ProductListViewModel(string groupId)
{
GroupId = groupId;
}
}
Update :
[0:] Binding: 'GroupId' property not found on 'mynamespace.Models.Category', target property: 'Xamarin.Forms.Label.Text'
Upvotes: 1
Views: 458
Reputation: 14956
Don't assign bindings internally inside custom controls. You could do like this:
public partial class GroupView : ContentView
{
GroupViewModel _viewModel;
public string GroupId
{
get { return (string)GetValue(GroupIdProperty); }
set { SetValue(GroupIdProperty, value); }
}
public static readonly BindableProperty GroupIdProperty = BindableProperty.Create(
nameof(GroupId),
typeof(string),
typeof(GroupView),
"Default_V",
defaultBindingMode: BindingMode.OneWay,
propertyChanged: GroupIdChanged
);
private static void GroupIdChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (GroupView)bindable;
control.GroupId = (string)newValue;
control.label.Text = control.GroupId;
}
public GroupView()
{
InitializeComponent();
}
}
then in xaml:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="mynamespace.Views.GroupView">
<ContentView.Content>
<StackLayout>
<Label x:Name="label" />
</StackLayout>
</ContentView.Content>
</ContentView>
Upvotes: 1