WPF Charts - Rotate XAXIS labels - c#

I am hoping someone can help me. I am an amateur developer (at best) who mainly writes code to help parse log files and I am struggling with charting.
In the code below, I am simply taking in any DataTable (with properly named columns and datatypes) and creating a stacked chart using the WPF toolkit. I am having a very hard time rotating the XAXIS labels.
I have looked at all of these links and tried to integrate them into what I have already done, but nothing is working or I am not exactly sure how to interpret these links. Can anyone guide me through how to rotate my XAXIS after viewing how my chart gets created?
Silverlight: How to change AxisLabelStyle in code behind?
http://blogs.msdn.com/b/delay/archive/2010/03/06/turn-your-head-and-check-out-this-post-how-to-easily-rotate-the-axis-labels-of-a-silverlight-wpf-toolkit-chart.aspx
Create style to rotate axis label in code behind
Here is my code:
XAML:
<Window x:Class="gtseq_stats.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Main" Height="451" Width="685" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" RenderTransform="{Binding StringFormat=\{0:g\}}">
<Grid ForceCursor="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="552*" />
<ColumnDefinition Width="142*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="2,2,0,0" Name="cbx_report_name" VerticalAlignment="Top" Width="320" DisplayMemberPath="report_name_alias" SelectedValuePath="report_data_id" SelectionChanged="cbx_report_name_SelectionChanged" />
<toolkit:Chart Margin="10,31,12,12" Name="OutputChart" Grid.ColumnSpan="2" />
<Button Content="Button" Height="26" HorizontalAlignment="Left" Margin="350,2,0,0" Name="button1" VerticalAlignment="Top" Width="53" Click="button1_Click" FlowDirection="RightToLeft" />
</Grid>
</Window>
And then my C#:
public void BuildStackedChart(DataTable dtResults)
{
OutputChart.Series.Clear();
var palette = OutputChart.Palette;
OutputChart.Palette = null;
OutputChart.Palette = palette;
Dictionary<string, int> dictYAxis = new Dictionary<string,int>();
try
{
//Get a list of distinct Y axis and add them to a dictionary. This will be used later so we can assigne values to the proper dataValues.
var distinctYAxis = (from row in dtResults.AsEnumerable()
//orderby row.Field<string>("fix_line") ascending
select row.Field<string>("YAXIS")).Distinct();
int i = 0;
foreach (var name in distinctYAxis)
{
dictYAxis.Add(name, i);
i++;
}
}
catch
{
MessageBox.Show("Couldn't Properly Load Data. The data must have only 3 columns: XAXIS-DateTime Data Type" + Environment.NewLine + "YAXIS-String Value" + Environment.NewLine + "PLOTVALUES-Number");
return;
}
var dataValues = new List<List<SimpleDataValue>>();
try
{
//Add a new entry for however many YAxis we have (No Data is used at this point are we aren't linking the #'s in the dictionary to the data elements here.
//However, we will use the dictorary to add the enteries and use the numbers to respresent the rows.
foreach(KeyValuePair<string, int> pair in dictYAxis)
{
dataValues.Add(new List<SimpleDataValue>());
}
foreach (DataRow row in dtResults.Rows) // Loop over the rows.
{
dataValues[dictYAxis[row["YAXIS"].ToString()]].Add(new SimpleDataValue { DependentValue = Convert.ToDouble(row["PLOTVALUES"]), IndependentValue = Convert.ToDateTime(row["XAXIS"])});
}
}
catch
{
dataValues.Clear();
}
int i2 = 0;
var stackedSeries = Activator.CreateInstance(typeof(StackedColumnSeries)) as DefinitionSeries;
foreach (var values in dataValues)
{
var definition = new SeriesDefinition();
definition.DependentValuePath = "DependentValue";
definition.IndependentValuePath = "IndependentValue";
definition.Title = dictYAxis.FirstOrDefault(x => x.Value == i2).Key; ;
definition.ItemsSource = values;
stackedSeries.SeriesDefinitions.Add(definition);
i2++;
}
OutputChart.Series.Add(stackedSeries);
}

Check this post [How to: Easily rotate the axis labels of a Silverlight/WPF Toolkit chart]
<charting:ColumnSeries.IndependentAxis>
<charting:CategoryAxis
Orientation="X">
<charting:CategoryAxis.AxisLabelStyle>
<Style TargetType="charting:AxisLabel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:AxisLabel">
<layout:LayoutTransformer>
<layout:LayoutTransformer.LayoutTransform>
<RotateTransform Angle="-60"/>
</layout:LayoutTransformer.LayoutTransform>
<TextBlock Text="{TemplateBinding FormattedContent}"/>
</layout:LayoutTransformer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</charting:CategoryAxis.AxisLabelStyle>
</charting:CategoryAxis>
</charting:ColumnSeries.IndependentAxis>

Related

How to add a XAML Resource (Grid with ItemsControls) to a FlowDocument in Code-Behind multiple times

I am working on a WPF Window that presents the results of some technical calculations inside a FlowDocumentViewer.
Problem: The FlowDocument and all its content is created from Code-Behind because every calculation differs a bit in terms of headers, shown results, and lines. I use different BlockUIContainers which hold a Resource Grid with some ItemsControls to show the results in a formatted order and add it to a Section and then to the Blocks of the Document, but only the last Block is shown inside the Reader.
I don't understand why after using FlowDoc.Blocks.Add(section) multiple times, only the last Block is shown.
I have created a Resource inside the XAML Code to fill it from Code Behind with the results. I need the output to look like this, e.g.:
M,ed = 70 kNm
Q,ed = 25 kN
N,ed = 30 kN
...
To achieve formatting like this, I created a grid with three columns, each containing an ItemsControl with a DataTemplate TextBlock, which has a Binding to a List<> of results.
<Window x:Class="FaceplateInput.Output"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FaceplateInput"
mc:Ignorable="d"
x:Name="OutputWnd"
WindowStartupLocation="CenterScreen"
Title="Output" Height="1000" Width="700">
<Window.Resources>
<Grid x:Key ="TestGrid" x:Name="Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ItemsControl x:Name="ItemsLeft" Grid.Column="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl x:Name="ItemsMid" Grid.Column="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl x:Name="ItemsRight" Grid.Column="2">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window.Resources>
...
<FlowDocumentScrollViewer x:Name="DocReader" Grid.Column="1" Grid.Row="2" Margin="20" MaxWidth="700">
</FlowDocumentScrollViewer>
</Grid>
</Window>
I want to create the FlowDocument in Code-Behind to have control over formatting, especially because the document is created from a single string that is returned by the calculating class.
I build the following test-method to see how FlowDocuments work. The result is that only the added paragraphs and the last section are shown in the output window.
Code-Behind:
namespace FaceplateInput
{
public partial class Output: Window
{
public string PathToImage;
public string PathToBackground;
public string PathToTXTFile;
public Output()
{
InitializeComponent();
CreateFlowDocument();
}
private void CreateFlowDocument()
{
FlowDocument FlowDoc = new FlowDocument();
List<string> leftStr = new List<string>();
List<string> midStr = new List<string>();
List<string> rightStr = new List<string>();
//for Testing purposes, i create some weired data to fill the Lists
for (int i = 0; i < 10; i++)
{
leftStr.Add($"LeftLine {i + 1}");
midStr.Add("=");
rightStr.Add($"RightLine {i + 1}");
}
//Creating a new Container with Resource Grid as UIElement:
BlockUIContainer cont = new BlockUIContainer((UIElement)this.FindResource("TestGrid"));
Grid child = (Grid)cont.Child;
//setting the sources for the ItemsControl:
ItemsControl items1 = (ItemsControl)child.Children[0];
items1.ItemsSource = leftStr;
ItemsControl items2 = (ItemsControl)child.Children[1];
items2.ItemsSource = midStr;
ItemsControl items3 = (ItemsControl)child.Children[2];
items3.ItemsSource = rightStr;
//adding section holding BlockUIContainer to Document
Section section = new Section();
section.Blocks.Add(cont);
FlowDoc.Blocks.Add(section);
//disconnecting UIContainer from parent to avoid Exception
section.RemoveChild(cont.Child);
cont.Child = null;
//another "testline" to see where it puts it in the document
FlowDoc.Blocks.Add(new Paragraph(new Run("TestString 1\n")));
//all the stuff above again to test
leftStr.Clear();
midStr.Clear();
rightStr.Clear();
leftStr.Add("______");
midStr.Add("_____________________");
rightStr.Add("_____________________");
for (int i = 0; i < 20; i++)
{
leftStr.Add($"Left: {(double)i * 324 / 10}\n");
midStr.Add("=\n");
rightStr.Add($"{(double)i * 13 / 2}\n");
}
BlockUIContainer cont1 = new BlockUIContainer((UIElement)this.FindResource("TestGrid"));
Grid child1 = (Grid)cont1.Child;
items1 = (ItemsControl)child1.Children[0];
items1.ItemsSource = leftStr;
items2 = (ItemsControl)child1.Children[1];
items2.ItemsSource = midStr;
items3 = (ItemsControl)child1.Children[2];
items3.ItemsSource = rightStr;
Section section1 = new Section();
section1.Blocks.Add(cont1);
FlowDoc.Blocks.Add(new Paragraph(new Run("TestString 2\n")));
FlowDoc.Blocks.Add(section1);
FlowDoc.Blocks.Add(new Paragraph(new Run("TestString 3\n")));
DocReader.Document = FlowDoc;
}
//...
}
}
I'd appreciate any tips on how to get this working, and maybe how to improve the code itself, or any ideas for completely different approaches.
Greets and thx, Crawliiee
You are setting the first container to null, so that first section is empty. Remove this line:
cont.Child = null;
An alternative could be to use a ListView with GroupView as in the example
https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.listview?view=netframework-4.7.2&f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(System.Windows.Controls.ListView);k(TargetFrameworkMoniker-.NETFramework,Version%253Dv4.7.2);k(DevLang-csharp)%26rd%3Dtrue

Set Dockpanel size in grid programmatically

My goal is to programmatically set a DockPanel size.
I want it to span from Grid.Column=1, Grid.Row=1, Grid.RowSpan=5
And I know hot to set it statically in xaml, but not in c#.
Explanation to code: In xaml I made a 1row 1 column grid with some textfields and a button in the DockPanel. In when I press the button it should create a grid with as many column/rows as I wrote in the textfields. Then name each column and each row. And know I want to create a Dockpanel on some of these fields but for that I must define where it starts and how far it spans. This is where the problem is.
here is my xaml code how I made it:
<Grid Name="MainWindowGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Name="DockPanel"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<DockPanel Background="LightSalmon" Grid.Row="0" Grid.Column="0" Grid.RowSpan="8">
<StackPanel>
<TextBox Name="txtColums" Text="16"/>
<TextBox Name="txtRows" Text="8"/>
<TextBox Name="txtWindowHeight" Text="800"/>
<TextBox Name="txtWindowWidth" Text="1600"/>
<Button x:Name="ButtonCreate" Content="Create" Click="ButtonCreate_Click"/>
</StackPanel>
</DockPanel>
<ContentControl Content="{Binding}"/>
</Grid>
And my C# code what I have so far:
Methods Methods = new Methods();
Methods.CreateField(MainWindowGrid, txtColums, txtRows, txtWindowHeight, txtWindowWidth, MainWindow1);
int GridColumnCount = MainWindowGrid.ColumnDefinitions.Count;
int GridRowCount = MainWindowGrid.RowDefinitions.Count;
for (int a = 1; a < GridColumnCount; a++)
{
MainWindowGrid.ColumnDefinitions.ElementAt(a).Name = "C" + a;
}
for (int a = 1; a < GridRowCount; a++)
{
MainWindowGrid.RowDefinitions.ElementAt(a).Name = "R" + a;
}
var converter = new System.Windows.Media.BrushConverter();
var brush1 = (Brush)converter.ConvertFromString("#FFFFFFF0");
DockPanel myDockPanel = new DockPanel();
myDockPanel.Background = brush1;
myDockPanel.
At the very end I want to be able to set at which row/column the dockpanel should be and then span it, but I sadly do not know how.
You could use the following methods to set the Grid.Column, Grid.Row and Grid.RowSpan attached properties of myDockPanel:
Grid.SetColumn(myDockPanel, 1); //= <DockPanel ... Grid.Column = "1"
Grid.SetRow(myDockPanel, 1); //= <DockPanel ... Grid.Row = "1"
Grid.SetRowSpan(myDockPanel, 8); //= <DockPanel ... Grid.RowSpan = "8"

Cannot dynamically create columns/rows in WPF

I want to be able to dynamically set a window's size in WPF, and then create as many columns and rows in a grid as I want.
I've created a method for it but it does not seem to work. I also added a border in XAML to see if there are columns and rows but I only see one square.
Also, it throws no error whatsoever.
This is my method:
public void CreateField(Grid MainGrid, TextBox Columns, TextBox Rows, TextBox WHeight, TextBox WWidth, MainWindow MainWindow)
{
int ColumnCount = Int32.Parse(Columns.Text);
int RowCount = Int32.Parse(Rows.Text);
int WindowHeight = Int32.Parse(WHeight.Text);
int WindowWidth = Int32.Parse(WWidth.Text);
MainWindow.MainWindow1.Height = WindowHeight;
MainWindow.MainWindow1.Width = WindowWidth;
for(int a = 0; a <= ColumnCount; a++){
ColumnDefinition c = new ColumnDefinition();
c.Width = new GridLength(WindowWidth / ColumnCount, GridUnitType.Pixel);
MainGrid.ColumnDefinitions.Add(c);
}
for (int a = 0; a <= RowCount; a++)
{
RowDefinition r = new RowDefinition();
r.Height = new GridLength(WindowHeight / RowCount, GridUnitType.Pixel);
MainGrid.RowDefinitions.Add(r);
}
}
In XAML I have this good with only 1 column and 1 row and a dockpanel for the textboxes and buttons.
<Border BorderBrush="Black" BorderThickness="2">
<Grid Name="MainWindowGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Name="DockPanel"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<DockPanel Background="LightSalmon" Grid.Row="0" Grid.Column="0" Grid.RowSpan="8">
<StackPanel>
<TextBox Name="txtColums" Text="16"/>
<TextBox Name="txtRows" Text="8"/>
<TextBox Name="txtWindowHeight" Text="800"/>
<TextBox Name="txtWindowWidth" Text="1600"/>
<Button x:Name="ButtonCreate" Content="Create" Click="ButtonCreate_Click"/>
</StackPanel>
</DockPanel>
<ContentControl Content="{Binding}"/>
</Grid>
</Border>
And according to the parameters written here the method should be executed on button click. But instead of a grid with 16 columns and 8 rows, I only get 1 column 1 row. (you can see the border at the edge)
So what am I doing wrong here? I have no real experience with grids whatsoever, and I am pretty clueless. Hope someone can help me out.
EDIT:
The suggestion of to activate MainGrid.ShowGridLines as said by ASh worked. Did not know about this functionality. As it turns out i do have succesfully created the columns and rows. I thought it not to work because i tried to paint a field in the grid with a color which did not work. Now i wonder, why this does not work as i thought this to be correct code.
var converter = new System.Windows.Media.BrushConverter();
var brush1 = (Brush)converter.ConvertFromString("#FFFFFFF0");
DockPanel myDockPanel = new DockPanel();
Grid.SetColumn(myDockPanel, 3);
Grid.SetRow(myDockPanel, 3);
myDockPanel.Background = brush1;
There was a lot going wrong here and its a magical jar of wonderment why you wanted to do this, however this should point you in a better direction
Some Modifications
Dedicated Grid
Get the ActualHeight and ActualWidth to use
Set GridLines true, so you can see whats happening
Set the Grid alignments to Stretch
Don't alter the size of the window
Xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0"
Grid.Column="0"
BorderBrush="Black"
BorderThickness="2">
<DockPanel Grid.RowSpan="8" Background="LightSalmon">
<StackPanel>
<TextBox Name="txtColums" Text="16" />
<TextBox Name="txtRows" Text="8" />
<TextBox Name="txtWindowHeight" Text="800" />
<TextBox Name="txtWindowWidth" Text="1600" />
<Button x:Name="ButtonCreate"
Click="ButtonCreate_OnClick"
Content="Create" />
</StackPanel>
</DockPanel>
</Border>
<Grid Name="MainWindowGrid"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ShowGridLines="True" />
</Grid>
Code behind
public void CreateField(Grid MainGrid, TextBox Columns, TextBox Rows) // TextBox WHeight, TextBox WWidth, MainWindow MainWindow)
{
var ColumnCount = int.Parse(Columns.Text);
var RowCount = int.Parse(Rows.Text);
var width = MainGrid.ActualWidth;
var height = MainGrid.ActualHeight;
for (var a = 0; a <= ColumnCount; a++)
{
var c = new ColumnDefinition();
c.Width = new GridLength(width / ColumnCount, GridUnitType.Pixel);
MainGrid.ColumnDefinitions.Add(c);
}
for (var a = 0; a <= RowCount; a++)
{
var r = new RowDefinition();
r.Height = new GridLength(height / RowCount, GridUnitType.Pixel);
MainGrid.RowDefinitions.Add(r);
}
}
private void ButtonCreate_OnClick(object sender, RoutedEventArgs e)
{
CreateField(MainWindowGrid, txtColums, txtRows);
}
grid layout is correct. set MainGrid.ShowGridLines=true; to see it
to see dynamically created control you should add it to grid:
MainGrid.Children.Add(myDockPanel);
since grid rows have equal height and columns have equal width, the following lines can be safely removed:
r.Height = new GridLength(WindowHeight / RowCount, GridUnitType.Pixel);
c.Width = new GridLength(WindowWidth / ColumnCount, GridUnitType.Pixel);
if Width/Height is not set, it is defaulted to * which means Grid will size them equally.
as an alternative UniformGrid can be used:
AnotherMainGrid = new UnifromGrid {Rows = RowCount, Columns = ColumnCount };
but in this case child elements must be added consequtively

Telerik RadJumpList using DataVirtualizationMode.Automatic

I have a problem where im trying to use a Telerik Jump List with DataVirtualizationMode.Automatic, but i can't get it to work. The reason why i want to use this, is because i want my app to only download the data(games) which is in the current view of the Jump List control and not the whole data everytime. For example if i have searched for "Batman", and its returning 50 games, i don't want it to download and load all the games, only those i can see in the Jump List control.
Here is a sample of using DataVirtualizationMode.Automatic from Telerik, but i couldn't get it to work with my app: http://www.telerik.com/help/windows-phone/raddataboundlistbox-features-datavirtualization-automatic.html
Below is my Jump List control which i want to use with data virtualization.
MainPage.xaml:
<phone:PivotItem Header="Browse">
<Grid>
<telerikPrimitives:RadTextBox Name="txtSearch" HorizontalAlignment="Left" VerticalAlignment="Top" Height="80" Width="390"/>
<telerikPrimitives:RadImageButton Name="imgBtnSeachGame" VerticalAlignment="Top" HorizontalAlignment="Right" ButtonShape="Ellipse" BorderThickness="2" Margin="0,8,0,0" Click="imgBtnSeachGame_Click"></telerikPrimitives:RadImageButton>
<Controls:RadJumpList Name="jlGameList" ItemsSource="{Binding}" Tap="jlGameList_Tap" Margin="0,90,0,0" DataVirtualizationMode="Automatic">
<Controls:RadJumpList.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="{StaticResource PhoneAccentBrush}"
Padding="{StaticResource PhoneTouchTargetOverhang}"
Margin="0,0,0,0">
<TextBlock Name="tblGameTitle" Style="{StaticResource PhoneTextGroupHeaderStyle}" ManipulationStarted="tblGameTitle_ManipulationStarted" ManipulationCompleted="tblGameTitle_ManipulationCompleted">
<Run Text="{Binding GameTitle}"></Run>
</TextBlock>
</Border>
<Grid Background="#242424" Grid.Row="1">
<Image Name="imgGameList" Margin="0,0,0,0" Stretch="Fill" HorizontalAlignment="Left" VerticalAlignment="Top" Height="96" Width="96">
<Image.Source>
<BitmapImage UriSource="{Binding BoxArtFrontThumb}"
CreateOptions="BackgroundCreation" DecodePixelHeight="96" DecodePixelWidth="96" />
</Image.Source>
</Image>
<TextBlock Margin="110,0,0,0" Text="Platform" FontWeight="Bold" TextWrapping="Wrap" Foreground="YellowGreen" FontSize="{StaticResource PhoneFontSizeNormal}"/>
<TextBlock Name="txtPlatform" Margin="110,20,0,0" Text="{Binding Platform}"></TextBlock>
<TextBlock Text="Release Date" FontWeight="Bold" Margin="110,46,0,0" Foreground="YellowGreen" FontSize="{StaticResource PhoneFontSizeNormal}"/>
<TextBlock Name="txtReleaseDate" Margin="110,66,0,0" Text="{Binding ReleaseDate}"></TextBlock>
<!--</StackPanel>-->
</Grid>
<Grid Grid.Row="2"></Grid>
</Grid>
</DataTemplate>
</Controls:RadJumpList.ItemTemplate>
</Controls:RadJumpList>
</Grid>
</phone:PivotItem>
Below is where i bind my DataContext to my GetGamesListItems ObservableCollection in my GameData class. The imgBtnSearchGame_Click event method is being called when a user have typed for example "Batman" in my textbox txtSearch and tapped the button, it will then send the text to my GetGamesListData method.
MainPage.cs:
GameData gd = new GameData();
public MainPage()
{
InitializeComponent();
jlGameList.DataContext = gd.GetGamesListItems;
}
private void imgBtnSeachGame_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(txtSearch.Text))
{
gd.GetGamesListData(txtSearch.Text, "", "");
}
}
Below is where i download the data in XML for the game name searched for. For example if it is "Batman" it will find and return all games with "Batman". The "BoxArtFrontThumb" Property is where im storing all the images for each game and is using async, because sometimes there can be quite alot of images it has to download and show.
GameData.cs
public void GetGamesListData(string name, string platform, string genre)
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += GetGamesListRequestCompleted;
webClient.DownloadStringAsync(new Uri("http://thegamesdb.net/api/GetGamesList.php?name=" + name));
}
private async void GetGamesListRequestCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
GetGamesListItems.Clear();
var feedXml = XDocument.Parse(e.Result);
var gameDataTasks = feedXml.Root.Descendants("Game").Select(
async x => new GetGamesList
{
ID = (int)x.Element("id"),
GameTitle = (string)x.Element("GameTitle"),
ReleaseDate = (string)x.Element("ReleaseDate") ?? "N/A",
Platform = (string)x.Element("Platform") ?? "N/A",
BoxArtFrontThumb = new Uri(await GetBoxArtFrontThumbAsync((int)x.Element("id")), UriKind.RelativeOrAbsolute),
}).ToList();
var gameData = await Task.WhenAll(gameDataTasks);
foreach (var item in gameData)
{
GetGamesListItems.Add(item);
}
}
}
Below is where its finding and storing the images for the games.
public async Task<string> GetBoxArtFrontThumbAsync(int id)
{
var client = new HttpClient();
var result = await client.GetStringAsync("http://thegamesdb.net/api/GetArt.php?id=" + id);
var feedXml = XDocument.Parse(result);
var gameData = feedXml.Root.Descendants("Images").Select(x => new GetArt
{
BoxArtFrontThumb = new Uri(GetBoxArtFrontThumb(x), UriKind.RelativeOrAbsolute),
}).ToList();
return gameData.Single().BoxArtFrontThumb.ToString();
}
private static string GetBoxArtFrontThumb(XElement gameNode)
{
string data = "http://thegamesdb.net/banners/" + (string)gameNode.Descendants("boxart")
.FirstOrDefault(b => (string)b.Attribute("side") == "front");
if (data == "http://thegamesdb.net/banners/")
{
data = "/NoImage.jpg";
}
return data;
}
I really hope i explained this well enough and hope that there is someone that can help me solve this problem. Thanks.
Although you are using JumpList, the mechanism for Virtualizing the data is the same as the DataBoundListBox. (You can find more information here in the DataBoundListBox docs. There is a good tutorial using an OData service.)
In order for the Automatic mode to work properly, you need to be using Telerik's VirtualizingDataCollection object and initialize it with the proper arguments (count and page size).
I don't see this in the code you have provided above, can you please open a support ticket so that I can investigate further? See my comment above for the link. Let me know the ticket number and I'll provide further assistance.

Coverflow with Out of Memory

i am working on Windows 8 Phone Application.
I have issue where i am loading image with text on top of the images one by one.Its called coverflow feature.
I am getting Out of memory exception
for (int j = 0; j < items.Count; j++)
{
for (int i = 0; i < items.Collection.Count; i++)
{
Myobj obj = items[j].Collection[i];
if (obj.correct == 1)
{
coverflow.Add(new CoverFlow(items[j].Text, answer.TextTwo));
}
}
}
CarouselList.ItemsSource = coverflow;
DataTemplate :
<DataTemplate x:Key="DataTemplate1">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Height="400" Width="400" CornerRadius="30,30,30,30">
<Border.Background>
<ImageBrush ImageSource="Images/sample.png" />
</Border.Background>
</Border>
<Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="5,20,5,5"
Foreground="#000000"
Text="{Binding Title}"/>
</Grid>
<Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Bottom">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="5,5,5,20"
Foreground="#000000"
Text="{Binding SubTitle}"/>
</Grid>
</Grid>
</DataTemplate>
Here the there are around 300+ items that displays one after the other:
Like this :
Its not working at all i tried to reduce the widht and height from 400 to 200 it works but i want the image size to 400 so that it looks good.
how can i avoid this Out Of Memory even if my images are 400*400
This is going to be really from the top of my head. Haven't dealt with this in a while.
1.Write yourself a function which will return you a bunch of items
public List<Item> GetFirstItems()
{
return items.Collection.Take(50);
}
public Item GetOtherItems(int skip)
{
return items.Collection.Skip(skip).Take(25)
}
2.Hook up to the SelectionChangedEvent for your control
//keep this somewhere so you know where you are in the list
var currentBatch = 0;
private void SelectionChanged(sender object, ChangedEventArgs e)
{
var position = e.CurrentItemIndex % 25;
if(position > currentBatch)
{
currentBatch = position;
var newItems = GetOtherItems(currentBatch * 25);
//take the global list of items and modify it;
//because we are moving right we only need the last 25 so we
//can skip the first 25
coverflow= coverflow.Skip(25);
//add your new items
coverflow.AddRange(newItems);
CarouselList.ItemsSource = coverflow; // you will have to clear the source first
}
else if(position < currentBatch)
{
currentBatch = position;
var newItems = GetOtherItems(currentBatch * 25);
//take the global list of items and modify it;
//because we are moving left we only need the first 25 so we
//can take the first 25
coverflow= coverflow.Take(25);
//add your new items
newItems.AddRange(coverflow);
coverflow = newItems;
CarouselList.ItemsSource = coverflow; // you will have to clear the source first
}
}
One more thing you will have to take care of is memorizing which was the current item and setting it again to be the current item.
This is all written from the top of my head and I have no idea if it work with your control but I hope it will at least help you a bit :)

Categories