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