Trouble loading lots of images from web - c#

I am trying to make a simple instagram feed display with WPF. I have a ListView which is bound to an ObservableCollection of image url's retrieved from the Instagram API. For some reason, I can only load the first 10 or so (even though I am trying to bind more). If I try to load lower resolution images, then it seems to work ok. But I'm not talking about massive images anyway (maybe around 100k each).
Here is some example code with a list of hard coded images from instagram. For me, this only loads the first 10, then misses number 11, then loads number 12. I have no idea why.
XAML:
<ListView x:Name="List" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.CanContentScroll="False">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width="250" Height="250" Background="Orange">
<Image Margin="3" Source="{Binding}" Stretch="Uniform" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Code behind:
List<string> content = new List<string>()
{
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23498621_155088151891201_5838888733310451712_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/e15/23421369_1935881716650536_2751759012239245312_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23498900_2424691114423634_1760461413358239744_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23498900_2424691114423634_1760461413358239744_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23347618_263128534210376_920911369891479552_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23421069_1500830839998934_8413516091602501632_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23417348_742804169243503_6556496499100876800_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23347902_2017564028488677_2880579113104441344_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23421331_334537296949861_4296430067371737088_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23421331_334537296949861_4296430067371737088_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23416590_1928818560779337_7080637368553701376_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/sh0.08/e35/p640x640/23421758_491705774540588_6178820534202007552_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23421099_1728264697245367_6448825186568372224_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23416994_133163334113394_1499431022142423040_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23421239_1483718185060885_8134914164545028096_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23280089_1942832749376286_3936575794389712896_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23347674_2006888666245374_7306582919252803584_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23347388_119626992143009_7585283007787827200_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23421865_900301160123071_1326331715420946432_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23421253_148762415872849_1558483017121398784_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/sh0.08/e35/p640x640/23507217_1953269574998281_6711372701967056896_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/sh0.08/e35/p640x640/23507217_1953269574998281_6711372701967056896_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23498098_2009691429314434_8349013357923139584_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/e15/23347679_315062128974030_5091325576380153856_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/sh0.08/e35/p640x640/23421083_1777350415899180_3004366087824343040_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/sh0.08/e35/p640x640/23421083_1777350415899180_3004366087824343040_n.jpg",
"https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/23498903_773821689486761_9202713497564086272_n.jpg"
};
List.ItemsSource = content;

You're running into the maximum connection limit to the same host for your application.
In your app.config file, you can add the following underneath configuration:
<system.net>
<connectionManagement>
<add address="*" maxconnection="1000" />
</connectionManagement>
</system.net>
You can read more about this here. Obviously you should tailor your entry to what your application actually needs.

Related

Can you bind multiple LineSeries to an oxyplot in WPF using MVVM pattern?

I am trying to plot multiple LineSeries elements in one <oxy:PlotView /> element in WPF using C# in Oxyplot where I am using the MVVM pattern. Say I have the (hypothetical) situation that I am tracking cars with a position as a function of time. Say I have the following files:
Model
Car.cs
View
DisplayView.xaml
DisplayView.xaml.cs
ViewModel
DisplayViewModel.cs
On initialization I create three car elements (in DisplayViewModel.cs : Cars = new List<Car>{ new Car(), ...};) with their corresponding displacement vs. time data PlotData = new List<DataPoint>{ new DataPoint(0,1), new DataPoint(1,4), ...}; and CarName.
DisplayView.xaml (1):
<ListBox ItemsSource="{Binding Path=Cars}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<oxy:Plot Title="{Binding CarName}" Height="400" Width="500">
<oxy:Plot.Series>
<oxy:LineSeries ItemsSource="{Binding Path=PlotData}"/>
</oxy:Plot.Series>
</oxy:Plot>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This works as expected. It shows a <ListBox /> with the three (separate) graphs. However this is not what I am trying to achieve. I would like to do something like the following:
DisplayView.xaml (2):
<ItemsControl ItemsSource="{Binding Path=Cars}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=CarName}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This displays the three individual car names as is expected, so I know I have the data source connected correctly. However, wrapping this <ItemsControl>...</ItemsControl> element with <oxy:Plot><oxy:Plot.Series>...</oxy:Plot.Series></oxy:Plot> and changing the <TextBlock /> element to a <oxy:LineSeries /> element and binding its ItemsSource property to the earlier mentioned DataPoint field yields the errors A value of type 'ItemsControl' cannot be added to a collection or dictionary of type 'collection`1'. and The specified value cannot be assigned to the collection. The following type was expected: "Series"..
DisplayView.xaml (doesn't work):
<oxy:Plot Title="Displacement plot">
<oxy:Plot.Series>
<ItemsControl ItemsSource="{Binding Path=Cars}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<oxy:LineSeries ItemsSource="{Binding Path=PlotData}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</oxy:Plot.Series>
</oxy:Plot>
I am new to the MVVM pattern - and C# and WPF programming in general - and I see the DisplayView.xaml.cs code-behind file needs to be empty. I can get the three LineSeries to display in one graph when using the code behind, but I am trying to utilize the power of MVVM. Can someone give me pointers on how I should fix this? I am just not experienced enough (yet) to play around with the code, so some explanation would be appreciated. What files do I need to add, what methods do I need to create and where do I create these? Is this even possible in the way I envision?
Kind regards,
Tom
I think I grasp the concept (after writing down my thoughts and questions in this post), so I am answering my own question. In DisplayView.xaml I added a <PlotView /> as such: <oxy:PlotView x:Name="DisplayPlotView" Model="{Binding PlotModel}" />. I also created a PlotModel in DisplayViewModel.cs, which is fine by the MVVM-pattern, as far as I understand. I loop through Cars to add the different series by doing:
foreach(Car car in Cars)
{
PlotModel.Series.Add(car.PlotData);
}
Where I now made the PlotData a LineSeries in the Car.cs. This shows the three lines in one graph.

UWP App, Add loading page while content loads

I am building a UWP app which gets content from the internet, as I am pulling images it often takes some time to load. I would like to have a loading screen when a user navigates to one of these pages that has an image.
I have attempted to use a progress ring which is visible while the content is being loaded and collapses when content has loaded, however this has been unsuccessful.
What would be the best way to do this.
Thanks in advance.
You can create a placeholder (image with text "image is loading").
If you have a ListView or some other data control you can use attribute Phase for this purpose:
<ListView ItemsSource="{x:Bind myimages}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:ImageInfo">
<StackPanel Orientation="Vertical">
<Grid>
<Image Source="Assets/placeHolderImage.jpg" x:Phase="0" />
<Image Source="{x:Bind Url}" x:Phase="3" />
</Grid>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
As you can seein this template one image is placed over another. First is loading image with Phase="0" and when another one with Phase="3" is loaded it's placed over

ListBox: Out Of Memory Exception on WP8

I have two ListBoxs in my pivot and each has an image.
<DataTemplate x:Key="PostsFieldItemTemplate" >
...
<Image Grid.Row="0" Margin="5" Width="100" Height="100" HorizontalAlignment="Left" Source="{Binding WImage}" Stretch="UniformToFill"/>
...
</DataTemplate>
<DataTemplate x:Key="ItemTemplateListBoxAnimation">
...
<Image Width="235" Height="210" Grid.Row="0" Source="{Binding tImage}" Stretch="UniformToFill"/>
...
</DataTemplate>
And i add url string to image in my code
PostsField.Items.Add(new ListPost(post.id, api.improveText(post.title), api.improveText(post.excerpt), post.attachments[0].url, api.improveDate(post.date)));
GridImages.Items.Add(new TempGrid(post.id, post.attachments[0].url, api.improveText(post.title), api.improveDate(post.date)));
Then i press on my button "LOAD MORE" and at some point I recieve exception (Out Of Memory). I commented out <Image Source="{Binding MyImage}"... /> in my ItemTemplates and all is ok..
Can you tell me please, what should i do to improve my Images ?
there is a limit on memory usage for app here is the details. you can find detail here
as you mentioned that you are loading images form API(web API I think). and showing them in list box on some button click and at some point out of memory exception is thrown. now on low memory phone, an app can use upto 150MB of phone memory. when your app exceeds that limit it throws this exception is thrown. what you can do is to remove/dispose previously added images from listbox to release the memory and than add new Images.
You can check the memory limit available to your app by checking the ApplicationWorkingSetLimit value using the DeviceExtendedProperties.GetValue(String) method. For an example of how to do this see How to disable features in apps for lower-memory phones for Windows Phone 8
Hope this helps

XAML SampleData Binding to Values of a List of Strings

OK, so I've searched and searched and searched, and I can't find an answer to this specific angle of my question. I know how to bind to a List, and how to make it auto-updating by making it an ObservableCollection instead of a List. However, with just a list of Strings, how the heck to I bind to the value of each List element?
<DataTemplate x:Key="PageTiles">
<Grid Background="{StaticResource PhoneAccentBrush}"
Margin="6,0,6,12">
<StackPanel VerticalAlignment="Bottom">
<TextBlock Text="{Binding}"
Margin="6,0,0,6" />
</StackPanel>
</Grid>
</DataTemplate>
Here's the LongListSelector that pulls from the list:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" VerticalAlignment="Top" Height="60">
<phone:LongListSelector Margin="0,0,-12,0"
ItemsSource="{Binding PageTitles}"
LayoutMode="Grid"
GridCellSize="150,150"
ItemTemplate="{StaticResource PageTiles}"
SelectionChanged="LongListSelector_SelectionChanged">
</phone:LongListSelector>
</Grid>
Now, I've used a similar layout before to do tiles based off a List of classes that have string properties, but never with a List of strings, and I can't find anything to guide me in the right direction.
So it turns out #har07 was right. The Text="{Binding}" I'd put in the text value was valid, my cell size was just too large for it to show in the 60 high grid that I'd made. Reduced the height of it to less than the stack panel's height and bam, there it was. I didn't even do that on purpose, that's just how I'd left it while I didn't know what to put in there, and because I hadn't recompiled to get the associations fixed, it wasn't finding anything to put in as elements.
So, to recap, to get the values of a List directly instead of something that's part of that value, a simple "{Binding}" does the trick. Lesson learned: double check your size values before running for help XD.

Display several videos in MediaElement

Via an XML file, I have to get a title, the link of a video and a date for display on WindowsPhone 8.
I browse the file with the following code:
foreach (var item in xElement.Elements("channel").Elements("item"))
{
var feed = new Feed
{
Link = item.Element("description").Value,
PubDate = DateTime.Now,
Title = item.Element("title").Value
};
Results.Items.Add(feed);
}
This code retrieves the values ​​correctly. I use the binding to link the two :
<ScrollViewer Grid.Row="1" BorderThickness="0">
<ItemsControl Name="Results" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock TextWrapping="Wrap"
Text="{Binding Path=Title}" />
<MediaElement Name="Media"
Source="{Binding Path=Link}"
Stretch="Fill"
AutoPlay="True" />
<TextBlock Text="{Binding Path=PubDate}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
The problem is that only two videos are displayed (and not always the same). I don't know where the error is it, because all the data is retrieved, including links to my videos.
I would also add controls to the MediaElement such as : Play, Stop,... But I don't know where to place the code.
I'm sorry for my English ! I'm French. Thanks all.
A while ago I remember reading on MSDN that the number of active MediaElement that are fully supported on Windows Phone is one (this was either 7.0 or 7.1 mind you). I can no longer find this reference on MSDN, but if you search the web, you'll find similar assertions (though with no MSDN quotes or whatever).
Try having just the one and see if it works as you expect, and then try to go up to two.

Categories