Xaml Xamarin表单:无法更新UI上的自定义控件

Xaml Xamarin表单:无法更新UI上的自定义控件,xaml,xamarin,xamarin.forms,xamarin.ios,bindableproperty,Xaml,Xamarin,Xamarin.forms,Xamarin.ios,Bindableproperty,我创建了一个自定义控件,该控件具有水平条。根据我从API获得的数量,该控件中可以有N个boxview。例如,我有一个控件,限制为20个控件,我选择了10个控件,因此10个boxview将显示为橙色,20个控件中的其余10个将显示为黑色 我需要在每个复选框上更新控件,它对我来说工作正常,直到我转到下一个屏幕并回到同一个屏幕。一旦我回到这个屏幕控件停止更新wile debug,我会在代码中获取数据,但它不会在UI上更新 如何在代码中使用它 <views:CustomDashControl

我创建了一个自定义控件,该控件具有水平条。根据我从API获得的数量,该控件中可以有N个boxview。例如,我有一个控件,限制为20个控件,我选择了10个控件,因此10个boxview将显示为橙色,20个控件中的其余10个将显示为黑色 我需要在每个复选框上更新控件,它对我来说工作正常,直到我转到下一个屏幕并回到同一个屏幕。一旦我回到这个屏幕控件停止更新wile debug,我会在代码中获取数据,但它不会在UI上更新

如何在代码中使用它

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

我的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>

自定义控件的代码隐藏

    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
    }
公共部分类CustomDashControl:ContentView
{
静态整数总计数;
静态颜色;
私有静态可观测采集数据;
公共静态可观测收集数据
{
获取{return tempData;}
设置
{
tempData=值;
customDashControl.OnPropertyChanged(“TempData”);
}
}
静态CustomDashControl CustomDashControl;
公共自定义控件()
{
尝试
{
初始化组件();
customDashControl=this;
}
捕获(例外情况除外)
{
BaseViewModel.HandleException(ex);
}
}
#区域可绑定属性
公共静态只读BindableProperty项SourceProperty=
创建(“ItemsSource”,
类型(可观测采集),
typeof(CustomDashControl),新
ObservableCollection(),
BindingMode.Default,null,OnItemSourceChanged);
私有静态资源已更改(BindableObject bindable、object oldValue、object newValue)
{
如果(旧值!=新值)
{
(可绑定为CustomDashControl)。OnPropertyChanged(“ItemsSource”);
TempData=(ObservableCollection)newValue;
UpdateBar();
}
}
私有静态void UpdateBar()
{
尝试
{
if(TempData!=null&&TempData.Count>0)
{
var control=customDashControl.progressbar;
control.ColumnDefinitions.Clear();
control.Children.Clear();
//工作
对于(int i=0,j=0;i0)
{
(customDashControl.BindingContext作为CustomDashControlViewModel)。totalCount=totalCount;
}
}
}
公共整数总数
{
获取{return(int)GetValue(TotalCountProperty);}
set{SetValue(TotalCountProperty,value);}
}
#端区
}

出现将在屏幕出现之前执行,当您希望在屏幕出现之后立即执行加载的事件时,有一种解决方法

在viewmodel中创建一个属性,如下所示

private bool _toggleTemp;
public bool ToggleTemp
{
    get => _toggleTemp;
    set => SetProperty(ref _toggleTemp, value);
}
将以下行添加到构造函数的最后一行

LoadingVm.ToggleTemp = true;
在屏幕上添加一个开关,使IsVisible变为false,如下所示

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

如果这不起作用,请参考此--

在onappearing中,我将所有内容包装在一个异步调用中,并等待数百毫秒,以便呈现页面

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

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

尝试在页面的显示方法中手动调用
UpdateBar
。@ColeX MSFT抱歉,我尝试了你的解决方案,但没有帮助我,还有其他解决方案吗?我尝试了你的解决方案,但仍然无法更新控件
await WaitAndExecute(1000, () =>
{
// refresh code
}

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