Silverlight/XNA Data Binding Irregularity - silverlight

I have to preface this with a disclaimer. I'm a novice programmer, I've tried solving this on my own for days but have now completely run out of ideas/blog posts/walkthroughs and other sources. I really appreciate your time in reading and potentially replying.
I am trying to integrate scoreloop into a game I'm developing but am getting some very strange results with data binding and a listbox. My tests (below) imply that there has to be something I'm doing wrong with bindings, but the crazy thing is it actually works the first time I use it, but not for subsequent levels. Here is the important code I'm using:
XAML:
<ListBox x:Name="LeftListBox" Margin="12,48,0,128" ItemsSource="{Binding}" Background="{x:Null}" HorizontalAlignment="Left" Width="240">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<StackPanel Margin="0,0,0,0" Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Text="{Binding Rank}" TextWrapping="NoWrap" />
<TextBlock Text="." Width="54"/>
<TextBlock Text="{Binding Result}" TextWrapping="NoWrap" Width="76"/>
<TextBlock Text="{Binding User.Login}" TextWrapping="NoWrap"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have an event registered to fire whenever scores are loaded, this sets the binding and logs a debug message:
LeftListBox.DataContext = App._scoresController.Scores;
Debug.WriteLine("Scores Loaded");
App._scoresController.Scores contains User.Login, Rank, and Result.
After I beat a level it pulls down scores and displays them int he listbox just like I expect. As soon as it goes through the same cycle for the next level though the listbox is blank. The debug line of "Scores Loaded" always gets logged, so I know the event is firing.
What I've done so far in testing:
Turned on ALL for bindings logging and could not see anything getting logged in the output.
Set a break point at the Debug "Scores Loaded" line and can see that everytime it hits there it correctly assigned the datacontext,
with the correct fields with exactly matching names
Tried using Dispatcher.BeginInvoke(LoadScores); to be sure I was doing it off the UI thread in case this was somehow a threading
issue
Set the background color on the stackpanel to a color that I could use to ensure it wasn't being collapsed or hidden by another control
or a storyboard animation
Created a copy of the same listbox, set listbox.datacontext = this in the same LoadScores() method, then set up local variables
for it to bind to. Found that this exhibited the same behavior,
disappearing on the second time I go to set the datacontext
Created a copy of the listbox and removed all bindings, setting the three text fields manually. This would not disappear, but
showed up every time I beat a level
Beat one level (getting it to work), beat another (getting it to disappear), navigate away from the gamepage.xaml/gamepage.xaml.cs where the gameplay takes place (like to a mainpage.xaml, then back to the gamepage. This does not fix the problem, so I'm assuming the problem is higher up than something inside the gamepage.xaml/gamepage.xaml.cs
I feel like I've got to be doing something painfully stupid/obvious, but I'm a novice programmer, just picking pieces up as I have a need, and this is my first venture into the world of data binding.
I would greatly appreciate any suggestions.
Thanks in advance for your time.

I found the problem. I was wrong when I said I was never leaving the GamePage.xaml.cs and Gamepage.xaml.
I reveiwed my code and found that I was actually jumping out to a transition page that lists the details of the next level, then back to GamePage.
Whenever I left the page, strange things would happen to the App._scoresController.Scores. If I created a private _scoresController.Scores within GamePage.xaml.cs and used that instead of the one in App then everything works. It looks like something strange with Scoreloop.

Related

TextBlock Text Binding an ObservableCollection.Count property

I have a ObservableCollection<Sportisti> that starts out with 0 elements (but is initialized to a new object at the creation of the window). I wanted to bind the Count property to a TextBox. Unfortunately, this causes my application to crash whenever I try to open the window in question.
Now, since I have a ListView on the same page, successfully showing the elements of the collection in question, I thought I could simply extract the number of rows from there, but that also lead to a crash.
<TextBox Text="{Binding ElementName=lvTabela, Path=Items.Count}"
Grid.Row="4" Grid.Column="1" Margin="0,3,60,3"
DockPanel.Dock="Top" IsReadOnly="True" />
Note that in the .xaml file I can see the content of the TextBox is 0.
Any idea why this is happening?
My mistake, I forgot to add the Mode=OneWay to the binding. The problem was that, even though the TextBox wasn't editable, the system recognized this as a potential way of changing the ListView.ItemCount attribute, which is read-only.
My suggestion: Initialize your collection to empty objects in your code when the the list initializes.
This may help you.

Combobox performance after changing ItemsSource

I have a datagrid with a column of comboboxes defined like this:
<DataGridTemplateColumn x:Name="AssortmentQualitySettingsDataGridColumn" Header="Kvaliteter">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=QualityInfoAssortmentCollection}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=ActiveQuality}"></CheckBox>
<TextBlock Text="{Binding Path=QualityName}" IsEnabled="False"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
The ItemsSource is an ObservableCollection of objects. The texts for the textbox in the combobox is however editable in another datagrid and put in another ObservableCollection called QualityItemCollection, and to get the comboboxes in the grid above updated I have an event on the datagrid that fires when that collection is changed. This even causes the QualityInfoAssortmentCollection to be re-read (the combobox needs to be set again also, so there is some looping to get it working).
Now, what happens is that the first time when data is loaded, everything is nice and dandy, however, when the event updating QualityInfoAssortmentCollection has fired the comboboxes above takes 5-7 seconds to drop down when trying to get into it. The refresh itself I have timed and it takes less than a tenth of a second to do. The combobox doesn't have more than 8-10 rows and there no difference trying to use a virtualizingstackpanel as suggested elsewhere. The datagrid displaying it has around 10 rows so it's not even close to any enormous amounts of data that needs to be shuffled.
Edit: More explanation about not being able to use the defining QualityItemCollection. The QualityItemColletion is the same for all items in the above datagrid, but the information about which checkboxes should be checked is set per item in the grid above. Therefore I make a copy of QualityItemCollection into QualityItemAssortmentCollection which also has a bool for the checkbox. There might be a better way to do this?
Edit 2:
Tried the WPF profiler now and it locks up just as the program does and doesn't display anything during the time the program is doing strange things. However, it turns it's something Visual Studio does, since if I run the program alone and not through Visual Studio there is no delay. Yay.
Problem was with the VS debugger. It for some reason makes the combobox excruciatingly slow.
So, fix it?
when the event updating QualityInfoAssortmentCollection has fired the comboboxes above takes 5-7
seconds to drop down when trying to get into it.
Where does it spend time? It is not like there are no profilers around. It is totally possible that this is WPF related, in which case this link:
http://msdn.microsoft.com/en-us/library/aa969767.aspx
also gets you staretd with a WPF level profiler (i.e. you can see where WPF spends the time, which may be some mistake in some WPF definitions).
It is also possible you send too many nonsensible update events (ou should always c hange whether a value HAS vchanged before sending an update notification). So, an upate may updatea property to teh same value triggering another update. A profiler will allow you to find these occurances.
Noone here can help yuo - without code etc. But a profiler should make it QUITE obvious where the time is spent.

bing maps pushpin and mouseclick

I have several pushpins on the map. When i hover with my mouse over the pushpins i get a dialogbox with some information in it. Now i also want some additional information when i click on the same pushpin. But i can't really figure out how to do this. I tried some things but it didn't work...
This is my code:
<bing:MapItemsControl ItemsSource="{Binding Items}">
<bing:MapItemsControl.ItemTemplate>
<DataTemplate>
<bing:Pushpin bing:MapLayer.Position="{Binding Location}" Background="{Binding Color, Converter={StaticResource brushConverter}}">
<ToolTipService.ToolTip>
<StackPanel>
<TextBlock Text="{Binding Address}" />
<TextBlock Text="{Binding Description}" />
</StackPanel>
</ToolTipService.ToolTip>
</bing:Pushpin>
</DataTemplate>
</bing:MapItemsControl.ItemTemplate>
</bing:MapItemsControl>
</bing:Map>
Has somebody tried to do this or know how to do this, by far thanks!
I know this is an old question, but maybe it will shine a little light on the right solution, and help someone else, if not you.
As I understand, the Tooltip stuff is already working, you just want to handle the clicks.
So here are some suggestions:
1 - The novice solution:
You can handle the event from the code behind. Since only Buttons have the Click event, you can't use that, but I think MouseLeftButtonDown, or even better MouseLeftButtonUp are equally good for this. Of course, if you have different maps on different controls, you will have to repeat this code on every one of them.
2 - The advanced solution:
Use Behaviors! They are like tiny extensions that can cling on to controls and extend their functionality. In your place, I would put a Behavior on the Pushpins, that would open a panel to display the info you want. You can read more about this topic under the link above!

Binding to images

I'm using a listbox with a template like the following.
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Width="100" />
</DataTemplate>
</ListBox.ItemTemplate>
I bind this to an observable collection conataining 130 paths to images (all do exist, read out using System.IO.Directory) but only a few get really displayed. No exceptions that come up. Only white places where the images should be. Has anybody seen something else.
Sascha
Never seen this before but Binding is suppressing errors by default. When there are errors you can see them when you run in debug en watch in the output window of visual studio and make sure the option of the combobox "Show output from:" is set to "Debug"
Hope that this will help you to the real problem.
EDITED:
If you don't see a problem may you can find it out by hooking into the Image.ImageFailed Event. More help can be found here :
http://msdn.microsoft.com/en-us/library/system.windows.controls.image.imagefailed%28v=VS.95%29.aspx

Silverlight Error "Layout Cycle Detected Layout could not complete" when using custom control

I'm building a custom control in Silverlight by deriving from ContentControl and doing some special formatting to put a dropshadow behind the contents.
I've nearly got it working but have recently ran into a bizarre error. It works fine if it contains anything besides a Border, or a Grid/Stackpanel/etc that does not have an explicitly defined height and width.
I get a JavaScript error in IE, and the text says:
Runtime Error 4008... Layout Cycle Detected... Layout Could Not Complete.
If I specify a height and width on the contained grid/stackpanel/etc it works fine.
There is a ton on the web about this error when too many textboxes are used (over 250), but I'm able to reproduce my error with a single button in a grid.
I have no textboxes at all on the page. The error has to do with a detected infinite loop. I set a few breakpoints in the code and it seems that the "SizeChanged" event is getting called a lot during rendering, and each time the height/width increments by 10.
I'm assuming that setting a default height/width causes it to skip this incrementing of the number, but I have no idea why this error is happening.
Has anyone ran into this or have any ideas?
There is a good blog post on this error here.
Bascially what can happen is you're changing some size in a MeasureOverride somewhere which causes another measure, which changes the size, which causes a measure and so on. I ran into this once before and fixed it by removing any code that caused a layout update or triggered a layout update during the layout cycle.
Update: Since the blog post is gone, quoting it here in full:
Continuing my series of gotchas for Silverlight 2, I wanted to talk about a common error that people are seeing. This error is something new that you might see when moving code from Beta 2 to the Release Candidate or later. In Beta 2, if the layout engine detected a cycle, it didn't throw any errors; as I understand it, the layout was just aborted. But with post Beta2 bits, an error is thrown.
The error you'll get will specify "Layout Cycle Detected" as the message. This error message is very accurate--the layout engine detected a cycle within your layout; or another way to say it, you have an infinite loop in your layout.
The biggest culprit that leads to this error is code within the LayoutUpdated event handler. If your LayoutUpdated event handler does anything to alter the layout of your control, then that will cause the LayoutUpdated event to fire again, and again, and again... :-)
Sometimes you need to have layout altering code within this event handler though, so what is one to do?
First, you should consider whether you really need the layout changes to occur on every call to LayoutUpdated. Would it suffice to handle the Loaded event as well as the Application.Current.Host.Content.Resized event. Between these two events, you'll get notified when the control is loaded into the visual tree, and you'll get notified any time the host is resized, which could cause you to need to change your layout again. Scenarios like modal dialogs should fall into this category.
Second, if you really do need to use LayoutUpdated, you might just need to put some conditions around your layout changes. For instance, if you are calculating a new width and height for your control, before you actually set the width and height, check to make sure the current values differ from what you calculated. This will allow the first LayoutUpdated event to resize your control, which triggers another LayoutUpdated event, but that event will recognize that there's no work to do, and the cycle will end.
These same rules will apply when you're handling the SizeChanged event, or if you're doing any other overrides on the layout of your control.
A common cause is handling SizeChanged and then in the handler doing something that affects the size of the element. Sometimes this is not obvious - it could be modifying child elements which affect the size of their container for instance.
1.If you are using LongListSelector inside ScrollViewer, better remove that. I was facing the same problem and my LongListSelector was inside ScrollViewer. During ItemRealized event, was getting this error.
2.Don't use updatelayout() inside itemrealized..I was using something like
list.UpdateLayout();
list.ScrollTo(e.Container.Content);
Simply use ScrollTo
3.If you are using image inside longlistselector, make sure to set the height and width of the image.
I had the same problem and what i did was put all the layout updates (size changes) in a "invoke" delegate en invoked later, it stops crashing but you there is a good change it's stuck in a loop
I had the same problem but it only occurred extremely rarely, my code hasn't changed for years and only recently someone managed to experience it.
I had a TextBlock inside a LongListSelector DataSource and its FontSize was set to 21. Changing the FontSize to ANY other value fixed the problem for me...
My LongListSelectors is inside a ScrollViewer.
<phone:PanoramaItem x:Name="OwnedGamesPanoramaItem" >
<ScrollViewer Margin="5,-25,0,0">
<StackPanel>
<TextBlock toolkit:TiltEffect.IsTiltEnabled="True" Text="{Binding Path=LocalizedResources.XOwnedGames, Source={StaticResource LocalizedStrings}}" FontFamily="Segoe WP Semibold" CharacterSpacing="10" FontSize="25" Margin="0,10,0,25" TextWrapping="Wrap"/>
<TextBlock x:Name="ownedGameLoadingTextBox" Margin="10" FontSize="26" Text="{Binding Path=LocalizedResources.XLoading, Source={StaticResource LocalizedStrings}}" HorizontalAlignment="Center"/>
<phone:LongListSelector x:Name="OwnedGameListBox" Tap="OwnedGameListBoxTap" ScrollViewer.VerticalScrollBarVisibility="Disabled" ItemRealized="OwnedGameListBox_ItemRealized" ItemUnrealized="OwnedGameListBox_ItemUnrealized" BorderThickness="0,20,0,0" >
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Tap="OwnedGameListBoxTap" Margin="0,0,0,12">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0" Tap="StackPanel_Tap_1">
<Image Width="60" Source="{Binding getSmallImageActualURL}" Height="60" Margin="3" VerticalAlignment="Top" />
<StackPanel Margin="15,0,0,0">
<TextBlock Width="320" TextWrapping="Wrap" Text="{Binding name}" Margin="0,0,0,0" FontSize="32" />
<TextBlock Text="{Binding getTotalPlaytimeFormatted}" Margin="0,0,0,0" TextWrapping="Wrap" FontSize="21" >
<TextBlock.Foreground>
<SolidColorBrush Color="{StaticResource PhoneAccentColor}"/>
</TextBlock.Foreground>
</TextBlock>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</StackPanel>
</ScrollViewer>
</phone:PanoramaItem>
Fix:
<TextBlock Text="{Binding getTotalPlaytimeFormatted}" Margin="0,0,0,0" TextWrapping="Wrap" FontSize="22" >

Resources