I have a Pivot with several PivotItems, one of which contains a canvas that places its items in dynamic locations (depending on the data). I get the data, and I can place the items in their place before the user can choose this item (this isn't the first pivot). However, only when I select the PivotItem, the canvas renders itself, so you can see it flicker before it's shown as it should.
Is there a way to force the canvas to render before it's shown, so everything's prepared by the time the user sees it?
My code looks something like this:
In the page.xaml.cs:
private async void GameCenterView_OnDataContextChanged(object sender, EventArgs e)
{
// Load data...
// Handle other pivots
// This is the problem pivot
if (ViewModel.CurrentGame.SportTypeId == 1)
{
_hasLineups = ViewModel.CurrentGame.HasLineups.GetValueOrDefault();
HasFieldPositions = ViewModel.CurrentGame.HasFieldPositions.GetValueOrDefault();
// I only add the pivot when I need it, otherwise, it won't be shown
if (_hasLineups)
{
if (MainPivot.Items != null) MainPivot.Items.Add(LineupPivotItem);
}
if (HasFieldPositions)
{
// Here I place all the items in their proper place on the canvas
ArrangeLineup(ViewModel.TeamOneLineup, TeamOneCanvas);
ArrangeLineup(ViewModel.TeamTwoLineup, TeamTwoCanvas);
}
}
// Handle other pivots
}
private void ArrangeLineup(ObservableCollection<PlayerInLineupViewModel> teamLineup, RationalCanvas canvas)
{
if (teamLineup == null)
return;
foreach (var player in teamLineup)
{
var control = new ContentControl
{
Content = player,
ContentTemplate = LinupPlayerInFieldDataTemplate
};
control.SetValue(RationalCanvas.RationalTopProperty, player.Player.FieldPositionLine);
control.SetValue(RationalCanvas.RationalLeftProperty, player.Player.FieldPositionSide);
canvas.Children.Add(control);
}
}
The canvas isn't the stock canvas. I created a new canvas that displays items according to their relative position (I get the positions in a scale of 0-99).
The logic happens in the OverrideArrange method:
protected override Size ArrangeOverride(Size finalSize)
{
if (finalSize.Height == 0 || finalSize.Width == 0)
{
return base.ArrangeOverride(finalSize);
}
var yRatio = finalSize.Height/100.0;
var xRatio = finalSize.Width/100.0;
foreach (var child in Children)
{
var top = (double) child.GetValue(TopProperty);
var left = (double) child.GetValue(LeftProperty);
if (top > 0 || left > 0)
continue;
var rationalTop = (int) child.GetValue(RationalTopProperty);
var rationalLeft = (int) child.GetValue(RationalLeftProperty);
if (InvertY)
rationalTop = 100 - rationalTop;
if (InvertX)
rationalLeft = 100 - rationalLeft;
child.SetValue(TopProperty, rationalTop*yRatio);
child.SetValue(LeftProperty, rationalLeft*xRatio);
}
return base.ArrangeOverride(finalSize);
}
Thanks.
There are several tricks you could try. For example:
ArrangeOverride
you can short-circuit the logic if the size hasn't changed since last time you executed (and the data is the same)Pivot
that tell you to get ready for presentation - PivotItemLoading
for examplePivot
, but instead be in the parent container (eg a Grid
) and have it with Opacity
of zero. Then set it to 100 when the target PivotItem
comes into view.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With