Problem summary: code-behind positioning is ignored if some tiles are collapsed unless a delay is introduced.
I have 12 tiles in 2 columns, all in restored state.
When all have their visibility set to visible I can set the position in the constructor of the hosting usercontrol and it works.
However if some of the tiles are collapsed, then the positioning is ignored (it seems) unless I introduce a delay of about 1/2 sec.
I tried putting the positioning code in the usercontrol loaded event, and even in the tileview loaded event, with no improvement.
It seems that if tiles with a position prior the ones being positioned are collapsed the problem occurs.
I noticed that if the position of the 12 tiles are defined in xaml as 0,1,2,3,4,5,6,7,8,9,10,11, that is, in order, then when tiles 2..6 are set to collapsed then the position order at run time is 0,1,2,2,2,2,2,2,3,4,5,6. So the collapsed tiles all have a position of 2, and tile 7 has a position of 2, 8-3, and so on.
When I set the position I only position visible tiles, and then with the position index starting with 0 and ending with visible_count-1, like in the 2nd set of position orders above. I do not set the positions in order of position but rather in order of occurrence, that is for example I iterate through the tile list and set the position of item 0 to 3, item 1 to 0, item 2 to 2, and so on.
I have IsItemsAnimationEnabled = False and PreservePositiojnWhenMaximized=True
I'm giving you all this info because I don't know what is relevant and what is not. Again, if I introduce a timer delay the tiles position properly.
10 Answers, 1 is accepted
Additional Info:
After positioning and the display shows the incorrect position, an inspection of the position values shows the correct position. So the tiles think they are in the correct position, so it looks like a screen update problem? I tried doing a tileview.updatelayout and a layoutroot.updateloayout with no success.
Also a delay as small as 100ms is enough to have the control render correctly, but of course this is not ideal.
Is there a way to force the control to redraw?
Is there an event that fires when the control can accept re-positioning?
I will need some time to check on your scenario. I will contact you as soon as I have more information on the matter.
Regards,
Martin
Telerik
I am not sure that I completely understand your case. This is why I would ask you to send me a runnable code that demonstrates your implementation and the position change with the 1/2 sec delay behavior, so I can test it locally and get better understanding of your scenario.
About the event related to positioning you can use TilesPositionChanged event. As for redrawing the control you can try to call its UpdateLayout() method in the tileview's TilesPositionChanged event handler. You can also try to call the Measure() and Arrange() methods before the UpdateLayout().
Regards,
Martin
Telerik
I have a sample app for you to look at but I don't know how to upload the zip file, it gives error only jpg, gif...etc
So posting here
Here is the xaml
<UserControl xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="TelerikTileViewTest.MainPage" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="800"> <Grid x:Name="LayoutRoot" Background="White"> <telerik:RadTileView Name="TileView"> <telerik:RadTileViewItem Name="Tile1" Header="Tile 1" > <TextBlock Text="Tile 1 Content"/> </telerik:RadTileViewItem> <telerik:RadTileViewItem Name="Tile2" Header="Tile 2" > <TextBlock Text="Tile 2 Content"/> </telerik:RadTileViewItem> <telerik:RadTileViewItem Name="Tile3" Header="Tile 3" > <TextBlock Text="Tile 3 Content"/> </telerik:RadTileViewItem> <telerik:RadTileViewItem Name="Tile4" Header="Tile 4" > <TextBlock Text="Tile 4 Content"/> </telerik:RadTileViewItem> <telerik:RadTileViewItem Name="Tile5" Header="Tile 5" > <TextBlock Text="Tile 5 Content"/> </telerik:RadTileViewItem> </telerik:RadTileView> </Grid></UserControl>
here is the code behing
Partial Public Class MainPage Inherits UserControl Private TileTimer As New Windows.Threading.DispatcherTimer 'sample showing that tile positioning is not honored in code behind in ctor or loaded 'however introducing a slight delay (100 ms in this case) does re-position tiles 'in xaml position is : 1 2 3 4 5 'desired position is : 2 1 3 4 5 Public Sub New() InitializeComponent() TileView.IsItemsAnimationEnabled = False TileView.PreservePositionWhenMaximized = True TileView.IsItemsAnimationEnabled = False TileView.IsVirtualizing = False TileTimer = New Windows.Threading.DispatcherTimer TileTimer.Interval = TimeSpan.FromMilliseconds(100) AddHandler TileTimer.Tick, AddressOf tileTimer_Tick Tile2.Position = 0 'this is not honored End Sub Private Sub MainPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded Tile2.Position = 0 'this is not honored TileTimer.Start() End Sub Private Sub tileTimer_Tick(sender As Object, e As EventArgs) TileTimer.Stop() Tile2.Position = 0 'this is honored End SubEnd ClassAddendum: Visibility/Collapsed of individual tiles does not have anything to do with recreating the problem as I first thought. Is seem that while the control is initializing it is ignoring tile positioning from code behind, once it is fully initialized everything works as expected. My problem is I don't know when it is done 'initializing'. I have animation off so annimationcompleted never fires. TilePositionChanged does fire, once for each tile on load, so this code does work, but it is only a slight improvement over the timer, in that I need to know the order the tiles load and move tiles only after they have been initially positioned.
Private Sub TileView_TilePositionChanged(sender As Object, e As Telerik.Windows.RadRoutedEventArgs) Handles TileView.TilePositionChanged System.Diagnostics.Debug.WriteLine(DirectCast(e.Source, Telerik.Windows.Controls.RadTileViewItem).Name) If DirectCast(e.Source, Telerik.Windows.Controls.RadTileViewItem).Name = "Tile3" Then If _firstTime Then _firstTime = False Tile2.Position = 0 'this is honored End If End IfEnd SubHere is my solution, it's not terrible. Maintain a flag indicating first time initialization is in progress. Once the last tile in xaml is positioned then set tiles to desired position and turn off flag
code
Partial Public Class MainPage Inherits UserControl 'in xaml position is : 1 2 3 4 5 'desired position is : 2 1 3 4 5 Private _firstTime As Boolean = True Public Sub New() InitializeComponent() End Sub Private Sub LastTile_PositionChanged(sender As Object, e As Telerik.Windows.RadRoutedEventArgs) If _firstTime Then _firstTime = False Tile2.Position = 0 'this is not honored End If End SubEnd Classxaml
<UserControl xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="TelerikTileViewTest.MainPage" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="800"> <Grid x:Name="LayoutRoot" Background="White"> <telerik:RadTileView Name="TileView" IsItemsAnimationEnabled="False" PreservePositionWhenMaximized="True"> <telerik:RadTileViewItem Name="Tile1" Header="Tile 1" > <TextBlock Text="Tile 1 Content"/> </telerik:RadTileViewItem> <telerik:RadTileViewItem Name="Tile2" Header="Tile 2" > <TextBlock Text="Tile 2 Content"/> </telerik:RadTileViewItem> <telerik:RadTileViewItem Name="Tile3" Header="Tile 3" > <TextBlock Text="Tile 3 Content"/> </telerik:RadTileViewItem> <telerik:RadTileViewItem Name="Tile4" Header="Tile 4" > <TextBlock Text="Tile 4 Content"/> </telerik:RadTileViewItem> <telerik:RadTileViewItem Name="Tile5" Header="Tile 5" PositionChanged="LastTile_PositionChanged"> <TextBlock Text="Tile 5 Content"/> </telerik:RadTileViewItem> </telerik:RadTileView> </Grid></UserControl>Thank you for the code snippets. I can confirm that the tileview items' Position setting is not respected until the tiles are generated. This behavior in RadTileView is expected since the position setting requires the item to has its ParentTileView set which happens on the tile's generation.
In order to set the Position of a specific item on load of the control you can use couple approaches:
- Subscribe for the RadTileView's Loaded event and set the tile's Position in Dispatcher.
PrivateSubTileView_Loaded(senderAsObject, eAsRoutedEventArgs)Dispatcher.BeginInvoke(NewAction(Function()Me.Tile2.Position = 0EndFunction))EndSub - Or you can subscribe for the StatusChanged event of the ItemContainerGenerator of the tileview and listen for the "ContainersGenerated" status. If the containers are generated set the position.
' subscribe for the Me.TileView.ItemContainerGenerator's StatusChanged event'---------------------------------PrivateSubItemContainerGenerator_StatusChanged(senderAsObject, eAsEventArgs)DimgeneratorAsItemContainerGenerator = TryCast(sender, ItemContainerGenerator)Ifgenerator.Status = System.Windows.Controls.Primitives.GeneratorStatus.ContainersGeneratedThenMe.Tile2.Position = 0EndIfEndSub
Please try this and let me know if it works for you.
Regards,
Martin
Telerik
