Rnta kokoi
Rnta kokoi

Reputation: 51

Binding property not found / some data displayed some not

I am having issues with displaying data, I can see my data FieldValue and FieldDescriptor in the List property however I still see in output that:

Binding: 'Results' property not found on 'ViewModel.ResultPageViewModel', target property: 'Xamarin.Forms.ListView.ItemsSource'

I can't see any data FieldVisualData in the horizontal list view even thought I can see them in the view model adding to detail and the command also can't be found.

Binding: 'EditTextCommand' property not found on 'Model.DocumentData', target property: 'Xamarin.Forms.TapGestureRecognizer.Command'

Maybe you see something that I am missing?

 <StackLayout Spacing="0">
                <!--Pictures-->
        <StackLayout VerticalOptions="Start" Spacing="0" >  
               <controls:HorizontalScrollList VerticalOptions="Start" HeightRequest="300" x:Name="carouselView"  ItemsSource="{Binding Results, Mode=TwoWay}">
                    <controls:HorizontalScrollList.ItemTemplate>
                        <DataTemplate>
                            <Image Source="{Binding Results.FieldVisualData}" 
                                    Margin="5">
                                <!--<Image.GestureRecognizers>
                                    <TapGestureRecognizer
                                        Command="{Binding HandlePreviewTapped, Source={x:Reference vm}}"
                                        CommandParameter="{Binding}"/>
                                </Image.GestureRecognizers>-->
                            </Image>
                        </DataTemplate>
                    </controls:HorizontalScrollList.ItemTemplate>
                </controls:HorizontalScrollList>                          
        </StackLayout>
            
        <StackLayout  VerticalOptions="Start" BackgroundColor="{DynamicResource SeparatorLineColor}" Spacing="10">
              <!--DocumentData-->
             <Label Grid.Row="0" HorizontalOptions="CenterAndExpand" Text="Občanský průkaz" VerticalOptions="End" ></Label>
            <StackLayout BackgroundColor="{DynamicResource PageBackgroundColor}"  VerticalOptions="FillAndExpand">
                <ListView x:Name="list" BackgroundColor="{DynamicResource PageBackgroundColor}"
                    HasUnevenRows="True"
                    HorizontalOptions="CenterAndExpand"
                    VerticalOptions="CenterAndExpand"
                    VerticalScrollBarVisibility="Never"
                    CachingStrategy="RecycleElement"
                   ItemsSource="{Binding Results, Mode=TwoWay}"
                    SeparatorVisibility="Default"
                    SelectionMode="None">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                        <ViewCell>
                                <Grid  BackgroundColor="{DynamicResource PageBackgroundColor}" Padding="10" >
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="15*"/>
                                         <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="12*"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                   <Label Grid.Column="1" Padding="0" Text ="{Binding FieldDescriptor}" Style="{StaticResource SubLabelBlackStyle}" HorizontalOptions="Start" BackgroundColor="{DynamicResource PageBackgroundColor}" HorizontalTextAlignment="Start"/>
                                   <Label Grid.Column="3" Padding="0" Text="{Binding FieldValue}" FontSize="Small" TextColor="#6781a3"  BackgroundColor="{DynamicResource PageBackgroundColor}" HorizontalOptions="Start" HorizontalTextAlignment="Start">
                                       <Label.GestureRecognizers>
                                           <TapGestureRecognizer Command="{Binding EditTextCommand}"  CommandParameter="{Binding FieldValue}" />
                                       </Label.GestureRecognizers>
                                   </Label>
                              </Grid>
                        </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackLayout>
        </StackLayout>    
</StackLayout>
public partial class ResultPage : ContentPage
{
    public ResultPage(IEnumerable<DocumentData> data)
    {
      InitializeComponent();
      BindingContext = new ResultPageViewModel(data);

       //carouselView.ItemsSource = data;
       // list.ItemsSource = data;
     
    }
}

public class ResultPageViewModel : BaseViewModel
{
    public ObservableCollection<DocumentData> Results { get; } = new ObservableCollection<DocumentData>();
    public ICommand EditTextCommand { get; }
    object param = "";
    public ResultPageViewModel(IEnumerable<DocumentData> data)
    {
        EditTextCommand = new Command(async () => await EditTextAsync(param));
        Load(data);
    }

    public void Load(IEnumerable<DocumentData> data)
    {
        foreach (var result in data)
        {
            var detail = new DocumentData()
            {
                FieldVisualData = result.FieldVisualData,
                FieldDescriptor = result.FieldDescriptor,
                FieldValue = result.FieldValue,
            };
            Results.Add(detail);
          
        }
    }

    public async Task EditTextAsync(object param)
    {
        PromptResult pResult = await UserDialogs.Instance.PromptAsync(new PromptConfig
        {
            InputType = InputType.Password,
            Text = param.ToString(),
            Title = Resources.AppResources.Password_lbl,
        });
    }
}

public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create( "ItemTemplate", typeof(DataTemplate), typeof(HorizontalScrollList), null, propertyChanged: (bindable, value, newValue) => ((HorizontalScrollList)bindable).Populate());

    public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
        "ItemsSource",
        typeof(IEnumerable),
        typeof(HorizontalScrollList),
        null,
        BindingMode.OneWay,
        propertyChanged: (bindable, value, newValue) =>
        {
            var obs = value as INotifyCollectionChanged;
            var self = (HorizontalScrollList)bindable;
            if (obs != null)
                obs.CollectionChanged -= self.HandleItemChanged;

            self.Populate();

            obs = newValue as INotifyCollectionChanged;
            if (obs != null)
                obs.CollectionChanged += self.HandleItemChanged;
        });

    public IEnumerable ItemsSource
    {
        get => (IEnumerable)this.GetValue(ItemsSourceProperty);
        set => this.SetValue(ItemsSourceProperty, value);
    }

    public DataTemplate ItemTemplate
    {
        get => (DataTemplate)this.GetValue(ItemTemplateProperty);
        set => this.SetValue(ItemTemplateProperty, value);
    }

    private bool willUpdate = true;
    private void HandleItemChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
    {
        if (!willUpdate)
        {
            willUpdate = true;
            Device.BeginInvokeOnMainThread(Populate);
        }
    }

    public HorizontalScrollList()
    {
        this.Orientation = ScrollOrientation.Horizontal;
    }

    private void Populate()
    {
        willUpdate = false;

        Content = null;

        if (ItemsSource == null || ItemTemplate == null)
        {
            return;
        }

        var list = new StackLayout { Orientation = StackOrientation.Horizontal };

        foreach (var viewModel in ItemsSource)
        {
            var content = ItemTemplate.CreateContent();
            if (!(content is View) && !(content is ViewCell))
            {
                throw new Exception($"Invalid visual object {nameof(content)}");
            }

            var view = content is View ? content as View : ((ViewCell)content).View;
            view.BindingContext = viewModel;

            list.Children.Add(view);
        }

        if (list.Children.Count == 0)
        {
            list.Padding = 20;
            list.Children.Add(new Label
            {
                WidthRequest = (list as VisualElement).Width - 30,
                HorizontalOptions = new LayoutOptions(LayoutAlignment.Fill, true),
                VerticalOptions = new LayoutOptions(LayoutAlignment.Fill, true),
                HorizontalTextAlignment = TextAlignment.Center,
                VerticalTextAlignment = TextAlignment.Center,
                FontSize = 15,
               
            });
        }

        Content = list;
    }

Upvotes: 1

Views: 883

Answers (1)

Leon Lu
Leon Lu

Reputation: 9234

Do you want to acheve the result like following GIF?

enter image description here

I do not which style or backgroundcolor that you setted, I set it with static background color.

Here is my editted layout.controls:HorizontalScrollList is a picture, so I comment it.

I change the Command in the TapGestureRecognizer

 <StackLayout Spacing="0">
        <!--Pictures-->
        <StackLayout VerticalOptions="Start" Spacing="0" >
            <!--<controls:HorizontalScrollList VerticalOptions="Start" HeightRequest="300" x:Name="carouselView"  ItemsSource="{Binding Results, Mode=TwoWay}">
                <controls:HorizontalScrollList.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding Results.FieldVisualData}" 
                                    Margin="5">
                            --><!--<Image.GestureRecognizers>
                                    <TapGestureRecognizer
                                        Command="{Binding HandlePreviewTapped, Source={x:Reference vm}}"
                                        CommandParameter="{Binding}"/>
                                </Image.GestureRecognizers>--><!--
                        </Image>
                    </DataTemplate>
                </controls:HorizontalScrollList.ItemTemplate>
            </controls:HorizontalScrollList>-->
        </StackLayout>

        <StackLayout  VerticalOptions="Start" BackgroundColor="White" Spacing="10">
            <!--DocumentData-->
            <Label Grid.Row="0" HorizontalOptions="CenterAndExpand" Text="Občanský průkaz" VerticalOptions="End" ></Label>
            <StackLayout BackgroundColor="Green"  VerticalOptions="FillAndExpand">
                <ListView x:Name="list" BackgroundColor="Red"
                    HasUnevenRows="True"
                    HorizontalOptions="CenterAndExpand"
                    VerticalOptions="CenterAndExpand"
                    VerticalScrollBarVisibility="Never"
                    CachingStrategy="RecycleElement"
                   ItemsSource="{Binding Results, Mode=TwoWay}"
                    SeparatorVisibility="Default"
                    SelectionMode="None">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Grid  BackgroundColor="Beige" Padding="10" >
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="15*"/>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="12*"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Label Grid.Column="1" Padding="0" Text ="{Binding FieldDescriptor}" HorizontalOptions="Start" BackgroundColor="Gray" HorizontalTextAlignment="Start"/>
                                    <Label Grid.Column="3" Padding="0" Text="{Binding FieldValue}" FontSize="Small" TextColor="#6781a3"  BackgroundColor="AliceBlue" HorizontalOptions="Start" HorizontalTextAlignment="Start">
                                        <Label.GestureRecognizers>
                                            <TapGestureRecognizer
                                                Command="{Binding BindingContext.EditTextCommand, Source={x:Reference Name=list}}"  
                                                CommandParameter="{Binding .}"
                                                
                                                
                                                />
                                        </Label.GestureRecognizers>
                                    </Label>
                                </Grid>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackLayout>
        </StackLayout>
    </StackLayout>

Here is layout background code. I add three data to make a test.

 public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            IEnumerable<DocumentData> data = new DocumentData[] { new DocumentData() { FieldDescriptor="test 1", FieldValue=1, FieldVisualData=1 } };
            data = data.Append(new DocumentData() { FieldDescriptor = "test 2", FieldValue = 2, FieldVisualData = 2 });
            data = data.Append(new DocumentData() { FieldDescriptor = "test 3", FieldValue = 3, FieldVisualData = 3 });

            this.BindingContext = new ResultPageViewModel(data);
        }
    }

Here is ResultPageViewModels code.

using Acr.UserDialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;

namespace XFormsListviewMvvm
{
    public class ResultPageViewModel : BaseViewModel
    {
        public ObservableCollection<DocumentData> Results { get; } = new ObservableCollection<DocumentData>();
        public ICommand EditTextCommand { get; }
        object param = "";
        public ResultPageViewModel(IEnumerable<DocumentData> data)
        {
            EditTextCommand = new Command<DocumentData>(async (key) => await EditTextAsync(key));
            Load(data);
        }

        public void Load(IEnumerable<DocumentData> data)
        {
            foreach (var result in data)
            {
                var detail = new DocumentData()
                {
                    FieldVisualData = result.FieldVisualData,
                    FieldDescriptor = result.FieldDescriptor,
                    FieldValue = result.FieldValue,
                };
                Results.Add(detail);

            }
        }

        public async Task EditTextAsync(DocumentData param)
        {
            PromptResult pResult = await UserDialogs.Instance.PromptAsync(new PromptConfig
            {
                InputType = InputType.Password,
                Text = param.FieldValue.ToString(),
                Title = "Insert your Password",
            });
            if (pResult.Ok)
            {
                param.FieldValue = pResult.Text;
            }
          
        }
    }
}

If you need to change the value, then layout will display it. you need to implement the BaseViewModel in the DocumentData.

namespace XFormsListviewMvvm
{
    public class DocumentData:BaseViewModel
    {
    

        private object fieldVisualData = "Hello world";
        public object FieldVisualData
        {
            get => fieldVisualData;
            set => SetValue(ref fieldVisualData, value);
        }

        private object fieldValue = "Hello world";
        public object FieldValue
        {
            get => fieldValue;
            set => SetValue(ref fieldValue, value);
        }
        public object FieldDescriptor { get; internal set; }
    
    }
}

=============Update===================

I add your controls:HorizontalScrollList code. And I change the from <Image Source="{Binding Results.FieldVisualData}"> to <Image Source="{Binding FieldVisualData}" >

Here is running gif.Image could be seen normally.

enter image description here

Here is editted layout.

 <StackLayout Spacing="0">
        <!--Pictures-->
        <StackLayout VerticalOptions="Start" Spacing="0" >
            <controls:HorizontalScrollList VerticalOptions="Start" HeightRequest="300" x:Name="carouselView"  ItemsSource="{Binding Results, Mode=TwoWay}">
                <controls:HorizontalScrollList.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding FieldVisualData}" 
                                    Margin="5">
                            <!--<Image.GestureRecognizers>
                                    <TapGestureRecognizer
                                        Command="{Binding HandlePreviewTapped, Source={x:Reference vm}}"
                                        CommandParameter="{Binding}"/>
                                </Image.GestureRecognizers>-->
                        </Image>
                    </DataTemplate>
                </controls:HorizontalScrollList.ItemTemplate>
            </controls:HorizontalScrollList>
        </StackLayout>

        <StackLayout  VerticalOptions="Start" BackgroundColor="White" Spacing="10">
            <!--DocumentData-->
            <Label Grid.Row="0" HorizontalOptions="CenterAndExpand" Text="Občanský průkaz" VerticalOptions="End" ></Label>
            <StackLayout BackgroundColor="Green"  VerticalOptions="FillAndExpand">
                <ListView x:Name="list" BackgroundColor="Red"
                    HasUnevenRows="True"
                    HorizontalOptions="CenterAndExpand"
                    VerticalOptions="CenterAndExpand"
                    VerticalScrollBarVisibility="Never"
                    CachingStrategy="RecycleElement"
                   ItemsSource="{Binding Results, Mode=TwoWay}"
                    SeparatorVisibility="Default"
                    SelectionMode="None">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Grid  BackgroundColor="Beige" Padding="10" >
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="15*"/>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="12*"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Label Grid.Column="1" Padding="0" Text ="{Binding FieldDescriptor}" HorizontalOptions="Start" BackgroundColor="Gray" HorizontalTextAlignment="Start"/>
                                    <Label Grid.Column="3" Padding="0" Text="{Binding FieldValue}" FontSize="Small" TextColor="#6781a3"  BackgroundColor="AliceBlue" HorizontalOptions="Start" HorizontalTextAlignment="Start">
                                        <Label.GestureRecognizers>
                                            <TapGestureRecognizer
                                                Command="{Binding BindingContext.EditTextCommand, Source={x:Reference Name=list}}"  
                                                CommandParameter="{Binding .}"
                                                
                                                
                                                />
                                        </Label.GestureRecognizers>
                                    </Label>
                                </Grid>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackLayout>
        </StackLayout>
    </StackLayout>

Here is layout background code.

   public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            IEnumerable<DocumentData> data = new DocumentData[] { new DocumentData() { FieldDescriptor="test 1", FieldValue=1, FieldVisualData= "https://aka.ms/campus.jpg" } };
            data = data.Append(new DocumentData() { FieldDescriptor = "test 2", FieldValue = 2, FieldVisualData = "https://aka.ms/campus.jpg" });
            data = data.Append(new DocumentData() { FieldDescriptor = "test 3", FieldValue = 3, FieldVisualData = "https://aka.ms/campus.jpg" });

            this.BindingContext = new ResultPageViewModel(data);
        }
    }

Upvotes: 0

Related Questions