Problem positioning tiles when some are collapsed

11 posts, 0 answers
  1. Kenneth
    Kenneth avatar
    101 posts
    Member since:
    Apr 2014

    Posted 16 Aug 2015 Link to this post

    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.

  2. Kenneth
    Kenneth avatar
    101 posts
    Member since:
    Apr 2014

    Posted 16 Aug 2015 in reply to Kenneth Link to this post

    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?

     

     

  3. DevCraft banner
  4. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 19 Aug 2015 Link to this post

    Hi Kenneth,

    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
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  5. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 21 Aug 2015 Link to this post

    Hello Kenneth,

    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
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Kenneth
    Kenneth avatar
    101 posts
    Member since:
    Apr 2014

    Posted 21 Aug 2015 in reply to Martin Link to this post

    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 Sub
     
    End Class

  7. Kenneth
    Kenneth avatar
    101 posts
    Member since:
    Apr 2014

    Posted 21 Aug 2015 in reply to Kenneth Link to this post

    Addendum:  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 If
    End Sub

  8. Kenneth
    Kenneth avatar
    101 posts
    Member since:
    Apr 2014

    Posted 22 Aug 2015 in reply to Kenneth Link to this post

    Here 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 Sub
    End Class
     

    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" 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>

  9. Kenneth
    Kenneth avatar
    101 posts
    Member since:
    Apr 2014

    Posted 22 Aug 2015 in reply to Kenneth Link to this post

    comment in code above should read: this is honored.
  10. Kenneth
    Kenneth avatar
    101 posts
    Member since:
    Apr 2014

    Posted 22 Aug 2015 in reply to Kenneth Link to this post

    comment in above code should read: this is honored.
  11. Kenneth
    Kenneth avatar
    101 posts
    Member since:
    Apr 2014

    Posted 24 Aug 2015 Link to this post

    My proposed solution does not work for me in the production project.  The reason is that the last tile is often collapsed so its position changed event never fires.  I ​forced it to be ​visible but for some reason I have not tracked down yet the event still does not fire, something beforehand must be collapsing it.  I considered having a dummy last tile that was always visible until it got re-positioned then hiding it but this introduces a lot of odd complexity in the code because of the way I'm tracking the position and visibility of the tiles (in an integer array that needs to have the same number of elements as there are tiles).  I can't find a reliable indicator as to when it is okay to position tiles.
  12. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 26 Aug 2015 Link to this post

    Hi Kenneth,

    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.
      Private Sub TileView_Loaded(sender As Object, e As RoutedEventArgs)
          Dispatcher.BeginInvoke(New Action(Function()
             Me.Tile2.Position = 0 
            End Function))
      End Sub
    • 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
      '---------------------------------
      Private Sub ItemContainerGenerator_StatusChanged(sender As Object, e As EventArgs)
          Dim generator As ItemContainerGenerator = TryCast(sender, ItemContainerGenerator)
          If generator.Status = System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated Then
              Me.Tile2.Position = 0
          End If
      End Sub

    Please try this and let me know if it works for you.

    Regards,
    Martin
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
DevCraft banner