0

I have created a custom control that has horizontal bar there can be N number of boxview in the bar based on number I get from API for example i have a control with limit of 20 controls and i have selected 10 of them so 10 boxview will be on orange and remaining 10 from 20 will be black i need to update control on every checkbox selection and it is working fine for me till i go to next screen and come back to the same screen once i come back to this screen control stops updating wile debug i get data in my code but its not updating on UI.

How i use it in my code

<views:CustomDashControl
        x:Name="customDash"
        Grid.Row="2"
        Grid.ColumnSpan="3"
        HorizontalOptions="FillAndExpand"
        ItemsSource="{Binding ControlData}"
        VerticalOptions="Start" />

My CustomControl XAML

<ContentView
    x:Class="LIRAppV1.Controls.CustomDashControl"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <StackLayout
        Padding="1"
        BackgroundColor="White"
        HorizontalOptions="CenterAndExpand"
        VerticalOptions="FillAndExpand">

        <!--<Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>-->

        <Grid
            x:Name="progressbar"
            BackgroundColor="Transparent"
            ColumnSpacing="0"
            HorizontalOptions="FillAndExpand"
            VerticalOptions="Start">

            <Grid.RowDefinitions>
                <RowDefinition Height="20" />
            </Grid.RowDefinitions>
        </Grid>
    </StackLayout>
</ContentView>

My CodeBehind of custom control

    public partial class CustomDashControl : ContentView
    {
        static int totalCount;
        static Color barColor;

        private static ObservableCollection<CustomControlData> tempData;

        public static ObservableCollection<CustomControlData> TempData
        {
            get { return tempData; }
            set
            {
                tempData = value;
                customDashControl.OnPropertyChanged("TempData");
            }
        }

        static CustomDashControl customDashControl;

        public CustomDashControl()
        {
            try
            {
                InitializeComponent();
                customDashControl = this;
            }
            catch (Exception ex)
            {
                BaseViewModel.HandleException(ex);
            }
        }

        #region Bindable Properties

        public static readonly BindableProperty ItemsSourceProperty =
            BindableProperty.Create("ItemsSource",
                                     typeof(ObservableCollection<CustomControlData>),
                                     typeof(CustomDashControl), new    
                                     ObservableCollection<CustomControlData>(),
                                     BindingMode.Default, null, OnItemsSourceChanged);

        private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
        {
            if (oldValue != newValue)
            {
                (bindable as CustomDashControl).OnPropertyChanged("ItemsSource");

                TempData = (ObservableCollection<CustomControlData>)newValue;

                UpdateBar();
            }
        }

        private static void UpdateBar()
        {
            try
            {
                if (TempData != null && TempData.Count > 0)
                {
                    var control = customDashControl.progressbar;

                    control.ColumnDefinitions.Clear();
                    control.Children.Clear();

                    //Working
                    for (int i = 0, j = 0; i < TempData.Count; i++, j++)
                    {
                        control.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });

                        var tempBox = new BoxView() { Color = TempData[i].BarColor, WidthRequest = TempData[i].BarWidth };

                        control.Children.Add(tempBox, j, 0);

                        j++;

                        control.ColumnDefinitions.Add(new ColumnDefinition() { Width = 1 });

                        control.Children.Add(new BoxView() { Color = Color.White, WidthRequest = 1 }, (j), 0);
                    }

                    Console.WriteLine(control.Children);
                }
            }
            catch (Exception ex)
            {
                BaseViewModel.HandleException(ex);
            }
        }

        public ObservableCollection<CustomControlData> ItemsSource
        {
            get { return (ObservableCollection<CustomControlData>)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }


        public static readonly BindableProperty TotalCountProperty = BindableProperty.Create(propertyName: "TotalCount", returnType: typeof(int), declaringType: typeof(CustomDashControl), defaultValue: 0, propertyChanged: propertyChanges1);

        private static void propertyChanges1(BindableObject bindable, object oldValue, object newValue)
        {
            if (oldValue != newValue)
            {
                var control = bindable as CustomDashControl;
                totalCount = (int)newValue;

                if (totalCount > 0)
                {
                    (customDashControl.BindingContext as CustomDashControlViewModel).totalCount = totalCount;
                }
            }
        }

        public int TotalCount
        {
            get { return (int)GetValue(TotalCountProperty); }
            set { SetValue(TotalCountProperty, value); }
        }

        #endregion
    }

1 Answers1

0

OnAppearing will be executed before the screen comes, when you want an Loaded event that needs to be executed right after the screen comes, there is a workaround.

Create an property in viewmodel like below.

private bool _toggleTemp;
public bool ToggleTemp
{
    get => _toggleTemp;
    set => SetProperty(ref _toggleTemp, value);
}

Add the following line to the last line of the constructor.

LoadingVm.ToggleTemp = true;

Add an Switch to your screen and make IsVisible to false as below.

<Switch IsToggled="{Binding ToggleTemp}" Toggled="Switch_OnToggled" IsVisible="False" />

Now you can write the code that you want to write in Page Loaded in Switch_OnToggled.

private async void Switch_OnToggled(object sender, ToggledEventArgs e)
{ 
    /* Your code goes here... */ 
}

Thanks!

If this does not work refer this --

In the onappearing I wrapped everything in an async call and waited a few hundred ms for the page to get rendered.

await WaitAndExecute(1000, () =>
{
// refresh code
}

protected async Task WaitAndExecute(int milisec, Action actionToExecute)
{
await Task.Delay(milisec);
actionToExecute();
}

https://forums.xamarin.com/discussion/22561/page-loaded-event