Layout cycle detected error with two progressRings - c#

I want to create a custom user control with two grids in which I want to load images and until images are loaded I want to show the progressRing control. The problem occurs when I add a second ProgressRing. My XAML looks like this:
<Grid Margin="0,0,0,21" Background="{ThemeResource PhoneAccentBrush}">
<Grid x:Name="leftImage" Margin="10" Width="190" Height="190"
HorizontalAlignment="Left">
<Image x:Name="imageHolderLeft" x:FieldModifier="public" Width="180"
Height="180" ImageFailed="imageHolderLeft_ImageFailed"
ImageOpened="imageHolderLeft_ImageOpened"/>
<Grid>
<ProgressRing x:Name="waitImageLeft" IsActive="True"
VerticalAlignment="Center" HorizontalAlignment="Center"
Background="Transparent"
Foreground="{ThemeResource AppBarBackgroundThemeBrush}"/>
</Grid>
</Grid>
<Grid x:Name="rightImage" Margin="10" Width="190" Height="190"
HorizontalAlignment="Right">
<Image x:Name="imageHolderRight" x:FieldModifier="public" Width="180"
Height="180" ImageOpened="imageHolderRight_ImageOpened"
ImageFailed="imageHolderRight_ImageFailed"/>
<Grid>
<ProgressRing x:Name="waitImageRight" IsActive="True"
VerticalAlignment="Center" HorizontalAlignment="Center"
Background="Transparent"
Foreground="{ThemeResource AppBarBackgroundThemeBrush}"/>
</Grid>
</Grid>
</Grid>
So when I comment out one ProgressRing it works fine, but when there are two of them my program crashes with the following error: Layout cycle detected. Layout could not complete
Does anyone knows why?
Thanks :)

This error indicates that the layout of an element depends on other elements that indirectly depend on the original element. Windows was not able to figure out the overall layout... Much like an infinite loop or infinite recursion.
In your case the cause probably relates to the alignments and sizes. You should be able to solve the problem by simplifying the layout. Keep the outer Grid but add 5 ColumnDefinitions, the middle one having width * and the other ones width Auto. Get rid of the other 4 Grids. Instead, put the two images and progress rings directly into the main Grid in columns number 0, 1, 3, and 4 (using the Grid.Column attached property). Put the desired sizes on the Width and Height properties of the images and progress rings, not on the Grid.

Related

how to give height of a parent to child in UWP

I have a stack panel and it has one grid and I'd like the grid to have same height as stack panel.
I tried playing with VerticalAlignment stretch or height 100% nothing works
I tried setting the values programatically OnNavigatedTo but it doesn't have the effect
Any suggestions to resolve this are welcome
Please find the code below
<StackPanel Grid.Row="0" Grid.RowSpan="4" Background="#CFFF" Visibility="Visible" Orientation="Vertical" Name="ProgressOverlay">
<Grid Name="Overlaygrid"">
<StackPanel VerticalAlignment="Center" Grid.Row="0">
<ProgressBar
IsIndeterminate="True"
IsEnabled="True" Foreground="Black"/>
<TextBlock Visibility="Visible" Foreground="Black" FontSize="25” T HorizontalAlignment="Center" Text="Loading"/>
</StackPanel>
</Grid>
</StackPanel>
A StackPanel takes by default the size needed by its content and shrinks to the size required, while a container control like Grid stretches to the full size available (e.g full page).
If you want to keep the outer StackPanel, you will have to set VerticalAlignment="Stretch" on the StackPanel, not on the Grid.
But since the Grid is the only single content item in your outer StackPanel, you can remove it and move the properties Grid.RowSpan="4" Background="#CFFF" Visibility="Visible" to the Grid. Always try to keep your XAML structure as simple as possible.

XAML element fill all remaining space

I have a WPF application and I'm trying to get the elements positioned correctly. There are just four elements, so it should be pretty straight-forward, but I just can't get it working.
One wrinkle is that the window resizes itself to (about) the size of the desktop window when it appears, so it doesn't have a fixed size.
The elements are supposed to be stacked from top to bottom, so a Stack Panel seemed natural. But The third element has to take up all the remaining space that the top two and bottom ones don't. No matter what I tried, it either took up too much space, or too little. I could only seem to get it working if I gave it a concrete pixel size which, as explained above, won't work.
The latest thing I've tried is a Dock Panel. While it looks correct in the Visual Studio designer, when executed, the third element--a Canvas--completely covers the bottom element.
My XAML:
<DockPanel>
<Button x:Name="btnClose" DockPanel.Dock="Top" Content="X"
HorizontalAlignment="Right" Margin="0,5,5,0" VerticalAlignment="Top"
Width="Auto" Height="Auto" Background="Black"
Foreground="White" Click="btnClose_Click"/>
<Label x:Name="lblTitle" DockPanel.Dock="Top" Content="My Title"
HorizontalAlignment="Center" VerticalAlignment="Top" Width="Auto"
Foreground="White" FontWeight="Bold" FontSize="22"/>
<Label x:Name="lblControls" DockPanel.Dock="Bottom" Content="Placeholder"
HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="Auto"
Height="Auto" Foreground="White" FontWeight="Bold" FontSize="22"/>
<Border x:Name="CanvasBorder" BorderBrush="White" BorderThickness="5" >
<Canvas x:Name="cvsChart" Grid.Row="0" HorizontalAlignment="Stretch"
VerticalAlignment="Top" Width="Auto">
</Canvas>
</Border>
</DockPanel>
Any idea about how to get that Canvas to stretch and fill all the space the other three don't take?
UPDATE
Since #Peter Duniho pretty much proved to me that the code worked, I tried an experiment and removed the resizing code I have in place for when the window appears. Taking it out, the window appears absolutely correctly. This is what I do to resize it to (mostly) the desktop size:
public const int WINDOW_OFFSET = 10;
...
int screenWidth = (int)System.Windows.SystemParameters.PrimaryScreenWidth;
int screenHeight = (int)System.Windows.SystemParameters.PrimaryScreenHeight;
// center this window in desktop
Width = screenWidth - WINDOW_OFFSET;
Height = screenHeight - WINDOW_OFFSET;
Left = WINDOW_OFFSET/2;
Top = WINDOW_OFFSET/2;
So I did some poking around, and found a comment here on the 'Stack that said to get the WorkArea instead of the PrimaryScreenHeight. I tried that and voila!, the whole application window appears.
int screenWidth = (int)System.Windows.SystemParameters.WorkArea.Width;
int screenHeight = (int)System.Windows.SystemParameters.WorkArea.Height;
As it turns out, the bottom row was displaying, I just couldn't see it because it appeared below the bottom of the screen. Now I can see it, and I'm back to development heaven!
Thanks to everyone for their input!
There are a number of possible approaches to this. One of the most straightforward is to contain your elements in a Grid and set all but the third row height to Auto:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button x:Name="btnClose" Content="X" Grid.Row="0"
HorizontalAlignment="Right" Margin="0,5,5,0" VerticalAlignment="Top"
Width="Auto" Height="Auto" Background="Black"
Foreground="White" Click="btnClose_Click"/>
<Label x:Name="lblTitle" Content="My Title" Grid.Row="1"
HorizontalAlignment="Center" VerticalAlignment="Top" Width="Auto"
Foreground="White" FontWeight="Bold" FontSize="22"/>
<Label x:Name="lblControls" Content="Placeholder" Grid.Row="3"
HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="Auto"
Height="Auto" Foreground="White" FontWeight="Bold" FontSize="22"/>
<Border x:Name="CanvasBorder" BorderBrush="White" BorderThickness="5" Grid.Row="2">
<Canvas x:Name="cvsChart" Grid.Row="0" HorizontalAlignment="Stretch"
VerticalAlignment="Top" Width="Auto">
</Canvas>
</Border>
</Grid>
The default setting for a grid's row definition height is "*", which says to distribute all of the remaining space among all the rows with that setting. With only one row using that setting, it gets all of the leftover space.
This produces a window that looks like this:
(I set the window background to Gray so that your white text and border would be visible.)
Another option would in fact be to use DockPanel. It appears to me that the main problem in your attempt is that you set the lblControls element to DockPanel.Dock="Bottom" when it should be Top instead. When I change it to Top, it seems to work fine for me.
Based on your comment below, it seems you actually did want lblControls to be set to DockPanel.Dock="Bottom", and in fact the code you posted seems to also do what you want. It's not clear to me what is different from what the code you posted does and what you want it to do. It would be better if you would provide a good Minimal, Complete, and Verifiable code example that reliably reproduces the problem.
Remove the vertical alignment of the Canvas

Change XAML Margin in universal app based on resolution

I am working on a Universal app for Wp8.1/WinRt.
For the phone, I have a gridview that displays grids containing stackpanels as 'ItemTemplate'.
The grids have margins specified explicitly, like so:
<GridView ItemsSource="{Binding CurrentItems}">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="140" Margin="6,0,6,6" x:Name="I_WANT_TO_ADJUST_MY_MARGINS">
<Border Background="{StaticResource PhoneAccentBrush}"/>
<Grid Height="140" Width="140">
<Image VerticalAlignment="Top" Margin="10" Width="100" Height="100" Source="{Binding Converter={StaticResource ImageConverter}}" HorizontalAlignment="Center" />
</Grid>
<Grid VerticalAlignment="Bottom">
<Border Background="{StaticResource PhoneBackgroundBrush}" Opacity="0.6"/>
<TextBlock Text="{Binding DisplayedName}" Style="{StaticResource BodyTextBlockStyle}" Margin="3" TextWrapping="Wrap"/>
</Grid>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
This looks great on a 6" inch phone giving me a 3 column look. But on a small phone, while I get two columns, the amount of negative space on the right is horrible.
I want to be able to make the margins of the grid I_WANT_TO_ADJUST_MY_MARGINS bigger if the screen is smaller?
Note: This layout is specifically for running on the phone.
This is how I solved it:
Add two datatemplates (big/small screen) to a resources dictionary - I used the page resources, but you can probably use any.
Add a DataTemplateSelector to the page resources. Specify the above two templates as properties, like so:
<local:WpDataTemplateSelector x:Key="WpDataTemplateSelector" BigScreenTemplate="{StaticResource BigScreen}" SmallScreenTemplate="{StaticResource SmallScreen}"></converters:WpDataTemplateSelector>
In the DataTemplateSelector use the following to determine screen width:Window.Current.Bounds.Width
Specify the ItemTemplateSelector property on the GridView

XAML WP8 and making a 'TextBlock' scroll down

Alright, so I have a XAML page with a TextBlock in a Windows Phone 8 application. My dilemma is this:
I pragmatically add more content (formatted lines with Inlines.Add(new Run...) to the TextBlock. The text block is currently filled from bottom to up because of the ScrollViewer in the sense that a line appears in the bottom after another. I would also be fine with them starting to appear from the top as long as the TextBlock would continue to scroll down (actually this might look better) once it is full. My TextBlock is inside a ScrollViewer as below:
<Popup x:Name="send_message_xaml" Grid.Row="1" VerticalOffset="0" Width="750" Height="auto">
<StackPanel Orientation="Vertical" Margin="0,0" Width="auto" Height="auto">
<ScrollViewer Height="345" HorizontalAlignment="Left" Margin="0,0,0,0" Name="scrollViewer1" VerticalAlignment="Bottom" Width="420" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="message_log" Margin="40,50,0,0" TextWrapping="Wrap" Width="420" VerticalAlignment="Top" FontSize="22"/>
</ScrollViewer>
<TextBox x:Name="message_to_send" InputScope="Chat" Width="480" KeyDown="message_to_send_KeyDown" Margin="15,0"/>
</StackPanel>
</Popup>
How can I get the textblock to scroll so that the newest appended message is always at the bottom? I found a bunch of these threads but none seem to solve my problem so far. Do I need to add some code somewhere with the appending?
You need to update the VerticalOffset based on the ScrollableHeight. When you add new inlines to the TextBlock, its height is going to change and that will notify the parent ScrollViewer. So, after you add new items to the inlines, run the Measure method and update the VerticalOffset.
Here is an example.

Scrollable textblock in windows phone 7

I am trying to create a scrollable text block.
But it dont seem to works.
How should i go about doing it?
Below is my code:
<Grid x:Name="ContentGrid" Grid.Row="1">
<ScrollViewer>
<TextBlock Height="517" HorizontalAlignment="Left" Margin="33,16,0,0" Name="textBlockRules" Text="" VerticalAlignment="Top" Width="414" FontSize="25" TextWrapping="Wrap" /></ScrollViewer>
Even though you didn't mention explicitly, I'm guessing that your aim is to show some large text without getting chopped.
For such a requirement there are helpful threads on stackoverflow:
1. Need to show large amount of text on windows phone 7 screen
2. Programmatically determining max fit in textbox (WP7)
On the other hand, if all you want is have text blocks in a sequence, you can use a ListBox that is databound to a list.
You have to set the maximum height of the ScrollViewer and could set the Visibility for the Scrollbars to Auto.
Here is the example from the msdn:
<ScrollViewer Height="200" Width="200" HorizontalScrollBarVisibility="Auto" Canvas.Top="60" Canvas.Left="340">
<TextBlock Width="300" TextWrapping="Wrap"
Text="I am the very model of a modern Major-General, I've information vegetable, animal, and mineral, I know the kings of England, and I quote the fights historical, From Marathon to Waterloo, in order categorical; I'm very well acquainted, too, with matters mathematical, I understand equations, both the simple and quadratical, About binomial theorem I'm teeming with a lot o' news, With many cheerful facts about the square of the hypotenuse." />
</ScrollViewer>
Set scrollviewerHorizontalBar to visibal, make textbok stretch and make sure your text is long enough, something like this:
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Name="Scroller">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinWidth="100" Width="{Binding ElementName=Scroller, Path=ViewportWidth}"
TextWrapping="Wrap" Text="Some really long text that should probably wordwrap when you resize the window." />
</ScrollViewer>

Categories

Resources