При отрисовке ListView наблюдается моргание строчек
В Xamarin.Forms сделал на базе MVVM вывод данных из таблицы в ListView. Сборка под Андроид.
В DataTemplate:
<DataTemplate>
<ViewCell>
<ContentView>
<ContentView.Resources>
<Style BasedOn="{StaticResource LightGrayLabel}" TargetType="Label">
<Setter Property="TextColor" Value="{Binding RowColor, Mode=OneWay}"/>
</Style>
</ContentView.Resources>
<Grid Padding="0" Margin="0" RowSpacing="1" ColumnSpacing="15">
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.35*"/>
<ColumnDefinition Width="0.20*"/>
<ColumnDefinition Width="0.15*"/>
<ColumnDefinition Width="0.30*"/>
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal" HorizontalOptions="StartAndExpand">
<Image Source="{Binding StockName.Image, Mode=OneWay}" VerticalOptions="Center" WidthRequest="16" HeightRequest="16"/>
<Label Text="{Binding StockName.Name, Mode=OneTime}"/>
<Label Text="{Binding BatchName, StringFormat='({0})'}" IsVisible="{Binding BatchVisible, Mode=OneWay}"/>
</StackLayout>
<Label HorizontalOptions="EndAndExpand" Grid.Row="1">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding LifeTimeManager.LifeTimeString, Mode=OneWay}" />
<Span Text=" — "/>
<Span Text="{Binding ExpiryDate, Mode=OneWay, StringFormat='{}{0:d}'}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label Text="{Binding Location, Mode=OneWay}" HorizontalOptions="Start" Grid.Column="1"/>
<Label HorizontalOptions="EndAndExpand" Grid.Column="2">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding TotalLenValue, Mode=OneWay}" />
<Span Text="("/>
<Span Text="{Binding LengthUnit, Mode=OneWay}"/>
<Span Text=")"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label HorizontalOptions="StartAndExpand" Grid.Column="1" Grid.Row="1" Text="{Binding LifeTimeManager.TimeToReadyString, Mode=OneWay}"/>
<ProgressBar Progress="{Binding ProgressValue, Mode=OneWay}" Grid.Column="2" Grid.Row="1" ProgressColor="{Binding ProgressColor, Mode=OneWay}" IsVisible="{Binding ProgressVisibility, Mode=OneWay}"/>
<Label Grid.Column="3" HorizontalOptions="EndAndExpand">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding LenghtValue, Mode=OneWay}"/>
<Span Text="("/>
<Span Text="{Binding LengthUnit, Mode=OneWay}"/>
<Span Text=") x "/>
<Span Text="{Binding WidthValue, Mode=OneWay}"/>
<Span Text="("/>
<Span Text="{Binding LengthUnit, Mode=OneWay}"/>
<Span Text=") "/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label Grid.Column="3" Grid.Row="1" Text="{Binding MaterialName, Mode=OneWay} " HorizontalOptions="EndAndExpand"/>
</Grid>
</ContentView>
</ViewCell>
</DataTemplate>
Моя задача только отображать данные, без их редактирования. Получается в модели перед отображением рассчитывается статус строки, и в зависимости от статуса изменятся ее цвет. Перерасчет статуса выполняется каждую секунду.
Проблема что у клиента на планшете наблюдается перерисовка с задержкой. Сначала весь ListView отрисовывается в едином цвете по умолчанию, а затем строки обновляются и раскрашиваются в свои цвета, через секунду-две такой эффект повторяется. При этом у себя проверил в дебаггере при отладке свойства в модели не обновляются, никаких изменений не вижу, а отрисовка в цвете по умолчанию вообще не выполняется ни при каких обстоятельствах.
Кто-нибудь может подсказать в чем может быть причина такого поведения?
Оптимизация:
Сделал во ViewCell замену Grid на RelativeLayout, включил на ListView кэширование, сообразил что стиль прописал в шаблоне, вынес его на уровень ListView. Частота моргания уменьшилась, теперь вместо 1сек оно наблюдается раз в 5 секунд.
<ListView ItemsSource="{Binding MaterialStock}" Grid.Column="2" Grid.Row="0" x:Name="CTStockList" RowHeight="34"
SeparatorVisibility="None" CachingStrategy="RecycleElement">
<ListView.Resources>
<Style BasedOn="{StaticResource LightGrayLabel}" TargetType="Label">
<Setter Property="TextColor" Value="{Binding RowColor, Mode=OneWay}"/>
</Style>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<RelativeLayout>
<Image Source="{Binding StockName.Image, Mode=OneWay}" WidthRequest="16" HeightRequest="16" />
<Label Text="{Binding StockWithBatch, Mode=OneTime}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=X, Constant=18}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=0.35,Constant=-18}"/>
<BoxView Color="{StaticResource BorderColor}" HeightRequest="1"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Y, Constant=32}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"/>
<Label HorizontalTextAlignment="End"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Y, Constant=17}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=0.35}"><!--Text="{Binding ExpireInfo, Mode=OneWay}"-->
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding LifeTimeManager.LifeTimeString, Mode=OneWay}" />
<Span Text="{Binding ExpiryDate, Mode=OneWay, StringFormat=' — {0:d}'}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label Text="{Binding Location, Mode=OneWay}" HorizontalTextAlignment="Start"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.35 , Constant=15}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=0.35,Constant=-85}"/>
<Label HorizontalTextAlignment="End"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.7 , Constant=-60}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=80}">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding TotalLenValue, Mode=OneWay}" />
<Span Text="{Binding LengthUnit, Mode=OneWay, StringFormat='({0})'}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label HorizontalTextAlignment="Start" Text="{Binding LifeTimeManager.TimeToReadyString, Mode=OneWay}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.35 , Constant=15}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Y, Constant=17}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=100}"/>
<ProgressBar Progress="{Binding ProgressValue, Mode=OneWay}"
ProgressColor="{Binding ProgressColor, Mode=OneWay}"
IsVisible="{Binding ProgressVisibility, Mode=OneWay}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.35 , Constant=120}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Y, Constant=17}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=0.35,Constant=-100}"/> <!---->
<Label HorizontalTextAlignment="End"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.70 , Constant=30}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=0.30, Constant=-30}">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding LenghtValue, Mode=OneWay}"/>
<Span Text="{Binding LengthUnit, Mode=OneWay, StringFormat='({0}) x '}"/>
<Span Text="{Binding WidthValue, Mode=OneWay}"/>
<Span Text="{Binding LengthUnit, Mode=OneWay, StringFormat='({0})'}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label Text="{Binding MaterialName, Mode=OneWay} " HorizontalTextAlignment="End"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.70 , Constant=30}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Y, Constant=17}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=0.30, Constant=-30}"/>
</RelativeLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Есть еще идеи как можно оптимизировать?