Martin
Martin

Reputation: 1213

ContentView does not update binding property

I created a custom control to be used in a listview. It almost works fine except for the custom property viewProgress that returns a boolean value based on the status of my order. Although the status gets his value correctly the boolean never gets reread and so the binding never receives a true value. I tried using breakpoints to detect if OnPropertyChanged is being run but it seems to never get there. The Item property seems to never get set, even though the data is bound. What am I doing wrong?

The ContentView:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:HandTerminal"
             x:Class="HandTerminal.OrderItem">
  <ContentView.Content>
        <StackLayout>
            <Frame
                Margin="10,6,10,6"
                Padding="10"
                CornerRadius="10">
                <StackLayout>

                    <StackLayout
                        Padding="0"
                        HorizontalOptions="Fill"
                        Orientation="Horizontal">
                        <Label
                            FontAttributes="Bold"
                            FontSize="Medium"
                            Text="Ordernumber"
                            TextColor="{DynamicResource TitleTextColor}" />

                        <Label
                            FontSize="Medium"
                            HorizontalOptions="FillAndExpand"
                            HorizontalTextAlignment="End"
                            Text="{Binding Item.Ordernumber}"
                            TextColor="{DynamicResource SubtleTextColor}" />
                    </StackLayout>

                    <StackLayout
                        IsVisible="{Binding viewProgress}"
                        Orientation="Horizontal"
                        HorizontalOptions="FillAndExpand">
                        
                        <Label
                            HorizontalOptions="Start"
                            Text="Picked"
                            TextColor="{DynamicResource HighlightTextColor}" />

                        <ProgressBar 
                            HorizontalOptions="FillAndExpand"
                            Progress="{Binding Item.PickedProgress}" />

                        <StackLayout
                            HorizontalOptions="End"
                            Orientation="Horizontal"> 

                            <Label
                                Text="{Binding Item.TotalPicked}"
                                TextColor="{DynamicResource HighlightTextColor}" />
                            <Label
                                Text="/"
                                TextColor="{DynamicResource HighlightTextColor}" />
                            <Label
                                Text="{Binding Item.TotalAmount}"
                                TextColor="{DynamicResource HighlightTextColor}" />
                        </StackLayout>
                    </StackLayout>

                </StackLayout>
            </Frame>
        </StackLayout>
    </ContentView.Content>
</ContentView>

Codebehind:

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace HandTerminal
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class OrderItem : ContentView
    {
        public OrderItem()
        {
            InitializeComponent();
            Content.BindingContext = this;
        }

        public static BindableProperty ItemProperty = BindableProperty.Create(
            propertyName: "Item",
            returnType: typeof(Order),
            declaringType: typeof(OrderItem),
            defaultValue: new Order(),
            defaultBindingMode: BindingMode.OneWay);

        public Order Item
        {
            get
            {
                return (Order)GetValue(ItemProperty);
            }
            set
            {
                SetValue(ItemProperty, value);
                OnPropertyChanged("Item");
                OnPropertyChanged("viewProgress");
            }
        }
        
        public static BindableProperty viewProgressProperty = BindableProperty.Create(
            propertyName: "viewProgress",
            returnType: typeof(bool),
            declaringType: typeof(OrderItem),
            defaultValue: false,
            defaultBindingMode: BindingMode.OneWay);

        public bool viewProgress
        {
            get
            {
                if (Item.Status == OrderStatus.Picking)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    }
}

The ContentPage that uses the custom control:

<?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="HandTerminal.Orders"
             xmlns:controls="clr-namespace:HandTerminal"
    xmlns:d="clr-namespace:HandTerminal;assembly=HandTerminal">
    <ContentPage.Content>
        <StackLayout
            Orientation="Vertical"
            VerticalOptions="CenterAndExpand">

            <ListView
                HasUnevenRows="True"
                ItemsSource="{Binding Orders}"
                VerticalOptions="StartAndExpand">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <controls:OrderItem Item="{Binding .}" />
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Upvotes: 0

Views: 434

Answers (1)

Juan Sturla
Juan Sturla

Reputation: 1304

I tried your code and my suggestions are:

  1. Create a viewProgressConverter

     public class viewProgressConverter : IValueConverter{
    
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
     {
         OrderStatus myOrder =(OrderStatus) value ;
         if (myOrder == OrderStatus.Picking)
             return true;
         else return false;
     }
    
     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
     {
         throw new NotImplementedException();
     }    }
    

You will have to add it to your AppResources in the App.Xaml

2.Modify your OrderItem View, Removing all the "Item." binding directly to your Order

<StackLayout
                    HorizontalOptions="FillAndExpand"
                    IsVisible="{Binding Status, Converter={StaticResource progressConverter}}"
                    Orientation="Horizontal">
  1. You can delete the Content.BindingContext = this; and comment/delete all the bindeable properties

Upvotes: 1

Related Questions