Xamarin.Forms binding does not work
Finally is working!
XAML should looks like code below.
Imporant is xmls:viewModel="..."
and <ContentPage.BindingContext>...</>
.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModel="clr-namespace:XamarinTest.ViewModel;assembly=XamarinTest"
x:Class="XamarinTest.MainPage"
>
<ContentPage.BindingContext>
<viewModel:RecordingViewModel/>
</ContentPage.BindingContext>
<ListView x:Name="listView" ItemsSource="{Binding Recordings}" Grid.Row="1" Grid.Column="1">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Horizontal">
<Image Source="Accept" WidthRequest="40" HeightRequest="40" />
<StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand">
<Label Text="{Binding TestName}" HorizontalOptions="FillAndExpand" />
<Label Text="{Binding TestNote}" />
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</ContentPage>
and MainPage.xaml.cs is okey
namespace XamarinTest
{
public partial class MainPage : ContentPage
{
public MainPage()
{
this.InitializeComponent();
this.AllTestViewModel = new RecordingViewModel();
this.BindingContext = AllTestViewModel;
}
public RecordingViewModel AllTestViewModel { get; set; }
}
}
Jakub Kameniar
Updated on July 13, 2022Comments
-
Jakub Kameniar almost 2 years
I try to rewrite my UWP C# app for Windows10 to Xamarin app using XAML. But Binding (for example here in ListView ItemSource=...) is not working for me and I don´t know why.
Visual Studio tells me, Cannot Resolve Symbol Recording due to unknown Data Context.
Here is my XAML (MainPage.xaml) for testing purpose:
<?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:XamarinTest;assembly=XamarinTest" x:Class="XamarinTest.MainPage"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="100" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="100" /> </Grid.ColumnDefinitions> <ListView x:Name="listView" IsVisible="false" ItemsSource="{Binding Recording}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <ViewCell.View> <StackLayout Orientation="Horizontal"> <Image Source="Accept" WidthRequest="40" HeightRequest="40" /> <StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand"> <Label Text="TEST" HorizontalOptions="FillAndExpand" /> <Label Text="TEST" /> </StackLayout> </StackLayout> </ViewCell.View> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </ContentPage>
Here is C# (MainPage.xaml.cs):
namespace XamarinTest { public partial class MainPage : ContentPage { public MainPage() { this.InitializeComponent(); this.AllTestViewModel = new RecordingViewModel(); this.BindingContext = AllTestViewModel; } public RecordingViewModel AllTestViewModel { get; set; } } }
And finally ViewModel (RecordingViewModel.cs):
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using XamarinTest.Model; namespace XamarinTest.ViewModel { public class RecordingViewModel : INotifyPropertyChanged { public ObservableCollection<Recording> Recordings { get; } = new TrulyObservableCollection<Recording>(); public RecordingViewModel() { Recordings.Add(new RecordingTest2() { TestName = "Test 1", TestNote = "Vytvoreni DB", TestTime = new TimeSpan(0, 0, 0) }); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public sealed class TrulyObservableCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged { public TrulyObservableCollection() { CollectionChanged += FullObservableCollectionCollectionChanged; } public TrulyObservableCollection(IEnumerable<T> pItems) : this() { foreach (var item in pItems) { this.Add(item); } } private void FullObservableCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (Object item in e.NewItems) { ((INotifyPropertyChanged)item).PropertyChanged += ItemPropertyChanged; } } if (e.OldItems != null) { foreach (Object item in e.OldItems) { ((INotifyPropertyChanged)item).PropertyChanged -= ItemPropertyChanged; } } } private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) { NotifyCollectionChangedEventArgs args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender)); OnCollectionChanged(args); } } }
Everything (models and viewmodels) are working in native UWP Windows 10 app. Only the Binding and making same view is problem in Xamarin. Could someone please help with binding? Thx.
EDIT
Recording.cs is here:
using System.Linq; using System.Text; using System.Threading.Tasks; namespace XamarinTest.Model { public abstract class Recording : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public string TestName { get; set; } private TimeSpan _testTime; private string _testNote; private string _actualIco = "Play"; private bool _isActive = false; private bool _enabled = true; public double IcoOpacity { get; private set; } = 1.0; public string ActualIco { get => _actualIco; set { if (_actualIco == null) _actualIco = "Admin"; _actualIco = value; NotifyPropertyChanged("ActualIco"); } } public bool IsActive { get => _isActive; set { if (_isActive == value) return; _isActive = value; IcoOpacity = !value ? 1.0 : 0.3; NotifyPropertyChanged("IsActive"); NotifyPropertyChanged("IcoOpacity"); } } public bool Enabled { get => _enabled; set { if (_enabled == value) return; _enabled = value; NotifyPropertyChanged("Enabled"); } } public string TestNote { get => _testNote; set { if (_testNote == value) return; _testNote = value; NotifyPropertyChanged("TestNote"); } } public TimeSpan TestTime { get => _testTime; set { if (_testTime == value) return; _testTime = value; NotifyPropertyChanged("TestTime"); } } protected Recording() { TestName = "Unkonwn"; TestNote = ""; _testTime = new TimeSpan(0, 0, 0); } protected Recording(string testName, string testNote, TimeSpan testTime) { TestName = testName; TestNote = testNote; _testTime = testTime; } public string OneLineSummary => $"{TestName}, finished: " + TestTime; private void NotifyPropertyChanged(string propertyName = "") { var handler = PropertyChanged; handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public abstract bool playTest(); } }
I tried add DataContext in XAML (postet in origin question), because of intellisence like this:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" xmlns:dvm="clr-namespace:XamarinTest.ViewModel" xmlns:system="clr-namespace:System;assembly=System.Runtime" d:DataContext="{system:Type dvm:RecordingViewModel}"
and this to Grid:
<Label Text="{Binding Recordings[0].TestName}" Grid.Row="0" Grid.Column="2" />
IntelliSence is OK, but text doesn´t show in app.
-
Jakub Kameniar almost 7 yearsI added Recording.cs to question. Yes, I think missing DataContext could be a problem. Could you please tell me how exactly I should it write? Because I tried it many times and it wasn´t working.
-
Jakub Kameniar almost 7 yearsOh, yes you right. But it didn´t help. Build and Deploy is sucess, but no text shows.
-
Jakub Kameniar almost 7 yearsI tried DataContext in XAML but it didn´t help, only IntelliSence is working. I edited original question about it.
-
Jakub Kameniar almost 7 yearsThis label I created for testing purpose outside of ListView. Sorry for confusion. But If I do it in Label in ListView it isn´t working too (build and deploy work, but I see only empty page).
-
robjam almost 7 yearsIf you use a static Label: '<Label Text="Test message" Grid.Row="0" Grid.Column="2" />' does it show?
-
Jakub Kameniar almost 7 yearsyes, I have this "for sure" label there all the time.
-
c-sharp-and-swiftui-devni about 2 yearsSame situation thats so odd u think binding context should be enough