Xamarin Forms - access databound object in ViewCell - xamarin

I am creating a ListView whose items I want to directly control with code. I have the following xaml that declares a generic ListView.
<?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:local="clr-namespace:ViewCellClick"
x:Class="ViewCellClick.MainPage">
<ListView x:Name="___listview" HasUnevenRows="True">
<ListView.ItemTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
and then in the code behind, I set up the ItemsSource property.
namespace ViewCellClick
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
___listview.ItemsSource = Repository.GetList();
___listview.ItemTemplate = new DataTemplate(typeof(CustomViewCell));
}
}
and this leverages a custom template defined as...
public class CustomViewCell : ViewCell
{
public CustomViewCell()
{
var stack = new StackLayout();
stack.Children.Add(new Label() { Text = "Label" });
// HOW DO I ACCESS THE MODEL HERE SO I CAN DRAW CUSTOM UI DEPENDING ON THE MODEL INSTANCE?
View = stack;
}
}
}
at this level, I have a very generic custom view cell as it only creates a label. However, say the model is complicated, and depending on the data in the model I would draw a different UI for that ViewCell instance.
How do I get access to the model for each CustomViewCell and then draw the UI according to that model?
I tried BindingContext, but it's null in the CustomViewCell constructor.

The BindingContext of thew ViewCell will have a reference to the current item in the list. You will need to cast it to the appropriate type in order to use it.

Related

How can I change the color of a Label in a template in the C# back end?

I have this template that's simplified for the question:
<?xml version="1.0" encoding="UTF-8"?>
<Frame xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:t="clr-namespace:Japanese.Templates"
xmlns:local="clr-namespace:Japanese;assembly=Japanese"
x:Class="Japanese.Templates.RoundButtonText" x:Name="this">
<Label Text="ABC" />
</Frame>
and this C#
using Xamarin.Forms;
namespace Japanese.Templates
{
public partial class RoundButtonText : BaseFrameButtonTemplate
{
public RoundButtonText()
{
InitializeComponent();
?? = Color.Red;
}
}
}
Can someone help me by telling me how I can change the TextColor of the label in the XAML inside the constructor of the back-end C#. Note that there's much more to this but I'm simplifying what I need for the question as if I know this then I can do the rest.
Specify x:Name="MyLabel" on the Label you want to access.
Then you can access that Label in your back-end C# file like so:
public RoundButtonText()
{
InitializeComponent();
MyLabel.TextColor = Color.Red; //OR
MyLabel.BackgroundColor = Color.Red;
}
That allows you to be able access any public property on the Label

How can I add a ViewCell (created in C#) after another ViewCell created in XAML?

I have this XAML:
<TableSection x:Name="TS2">
<TableSection.Title>
ABC
</TableSection.Title>
<ViewCell x:Name="noa" Tapped="openPicker">
...
</ViewCell>
<ViewCell x:Name="prt" Tapped="openPicker">
...
</ViewCell>
</TableSection>
C#
public partial class TableViewFooter : ViewCell
{
public TableViewFooter()
{
InitializeComponent();
}
}
How can I add a ViewCell (created from new TableViewFooter("AAA",60)) after second ViewCell in C#.
var cmt = new TableViewFooter("AAA",60);
prt.Add(cmt);
This code as is gives an error saying:
Error CS7036: There is no argument given that corresponds to the
required formal parameter 'value' of
'SettersExtensions.Add(IList, BindableProperty, object)'
(CS7036)
You can't add a ViewCell to a ViewCell - but you can append it to TableSection - for e.g., try using:
TS2.Add(cmt);

Xamarin.Forms: Create instance of a DataTemplate

I wan't to create a ContentView with a BindableProperty of type DataTemplate, so that when I use my custom ContentView i can customize how the elements should look like.
But I wan't to arrange and create the contents in code, how can I create an instance from a DataTemplate?
For example, in my custom view, I have a collection of objects, now for each object I want to create a view based on the set data template and set the binding context of that created view to that object.
I worked it out in following way.
I use my custom ContentView in following way:
<controls:MyCustomView Items="{Binding SampleItems}">
<controls:MyCustomView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding SampleProperty}" />
</DataTemplate>
</controls:MyCustomView.ItemTemplate>
</controls:MyCustomView>
then in the code behind of the MyCustomView I declare a ItemTemplate bindable property:
public DataTemplate ItemTemplate
{
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
}
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(
nameof(ItemTemplate),
typeof(DataTemplate),
typeof(MyCustomView),
propertyChanged: (bObj, oldValue, newValue) =>
{
var view = bObj as MyCustomView;
if (view != null)
view.SampleMethodToArrangeItems();
}
);
now let's say that in the SampleMethodToArrangeItems method I want to create and arrange, the items created from the provided data template:
foreach (var item in Items)
{
var itemView = ItemTemplate.CreateContent() as View;
if (itemView != null)
{
itemView.BindingContext = item;
// Do something with the create view e.g. add it to Grid.Children
}
}

Xamarin Forms bind property to label's text

I have Xamarin Forms xaml:
// 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:local="clr-namespace:BlankAppXamlXamarinForms"
x:Class="BlankAppXamlXamarinForms.MainPage">
<Label Text="{Binding myProperty}" />
</ContentPage>
And I have code behind:
// MainPage.xaml.cs
namespace BlankAppXamlXamarinForms {
public partial class MainPage : ContentPage
{
public string myProperty= "MY TEXT";
public MainPage()
{
InitializeComponent();
BindingContext = this;
}
}
}
It should bind myProperty to label's text. However, nothing displays in the label. How to bind myProperty to label's text? (I know I should use ViewModel to be able to notify view about changes of the property but in this example I really just want to bind myProperty from code behind to the label)
You need to declare that you can "get" the variable.
public string myProperty { get; } = "MY TEXT";
If you actually want to change this variable in code, your class will need to implement INotifyPropertyChanged, otherwise it will always be "MY TEXT"

ListBox ItemsSource binding working through code but not through XAML

I have this XAML:
<ListBox x:Name="MyItemsList"
ItemsSource="{Binding MyItems}"
SelectionChanged="ItemsList_SelectionChanged">
The code behind assigns the datacontext of the page to the view model:
DataContext = App.ViewModel;
My ViewModel object defines MyItems (and I initialize MyItems before setting the DataContext):
public ObservableCollection<Item> MyItems;
The end result is that my ListBox doesn't display anything. I tried adding items after the binding, and they don't show up either.
What works is if I set the ItemsSource in code instead of in the XAML:
MyItemsList.ItemsSource = App.ViewModel.MyItems;
Any tips on why this would happen? Thanks.
public ObservableCollection MyItems; - Field, but you should use property!
Property with backing field:
private ObservableCollection<Item> _myItems = new ObservableCollection<Item>();
public ObservableCollection<Item> MyItems{get{return _myItems;}}
If you whant setter, you should implement INotifyPropertyChanged and call OnPropertyChanged("MyItems")

Resources