How to display array in xaml the way that each line is on separate row and each row is split into separate textblocks?
I split line like so:
string[] splitLines = line.Split(';');
itemsControl.Items.Add(line);
Then, in xaml I display it like so:
<ItemsControl x:Name="itemsControl"
ItemsSource="{Binding itemsControl}"
FontSize="24">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="Auto"
Margin="0 12"
HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Column="0"
Grid.Row="0"
Orientation="Horizontal">
<TextBlock Name="txtblk0" Text="{Binding }" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This way I get each line from my .xls file in separate row, but the separator ';' is included in the returned content of row.
Now I would like to remove ';' separator and put each word from each line on separate textblock, like so:
for (int index = 0; index < splitLines.Length; index++)
{
itemsControl.Items.Add(splitLines[index]);
}
This breaks each line into separate words, but unfortunately, each word is put on separate row(instead to populate 5 textblocks with each line's words.
Any idea how to show each .xls line in separate row, but then also split each line into words and put them in separate textblocks in separate columns?
EDIT
I have tried the solution from Alexej Sommer, I get some erors though:
ItemsData dataitem = new ItemsData
{
value0 = splitLines[0];
value1 = splitLines[1];
value2 = splitLines[2];
value3 = splitLines[3];
value4 = splitLines[4];
}
items.Add(dataitem);
In this piece of code I get first semicolon underscored and error says:
} expected.
Then, values 1 - 4 are underscored and error says:
The name (X) does not exist in the current content
At last, dataitem gets underscored and same error shows up.
EDIT 2 --
I managed to fix the problem. There were problems with braces and code put in a wrong place. Also, instead of:
ItemsData dataitem = new ItemsData
{
value0 = splitLines[0];
value1 = splitLines[1];
value2 = splitLines[2];
value3 = splitLines[3];
value4 = splitLines[4];
}
items.Add(dataitem);
I used:
ItemsData dataitem = new ItemsData
{
value0 = splitLines[0],
value1 = splitLines[1],
value2 = splitLines[2],
value3 = splitLines[3],
value4 = splitLines[4],
};
items.Add(dataitem);
And that solved the problem.
Here is clean working code:
public async void ReadFile()
{
var path = #"CPU.xls";
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
var file = await folder.GetFileAsync(path);
var readFile = await Windows.Storage.FileIO.ReadLinesAsync(file);
foreach (string line in readFile.OrderBy(line =>
{
int lineNo;
var success = int.TryParse(line.Split(';')[4], out lineNo);
if (success) return lineNo;
return int.MaxValue;
}))
{
string[] splitLines = line.Split(';');
ObservableCollection<ItemsData> items = new ObservableCollection<ItemsData>();
for (int index = 0; index < splitLines.Length; index++)
{
ItemsData dataitem = new ItemsData
{
value0 = splitLines[0],
value1 = splitLines[1],
value2 = splitLines[2],
value3 = splitLines[3],
value4 = splitLines[4],
};
items.Add(dataitem);
}
itemsControl.DataContext = items;
}
}
I yet need to fix the layout as for now all the textblocks show up in same column and they overlap.
Thank you Alexej for your help!
Edit 3----
To put textblocks on separate columns in xaml I did like so:
<ScrollViewer>
<ItemsControl x:Name="itemsControl"
ItemsSource="{Binding}"
FontSize="24">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="Auto"
Margin="0 12"
HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Column="0"
Grid.Row="0"
Orientation="Horizontal">
<TextBlock Name="txtblk0" Text="{Binding value0}" />
</StackPanel>
<StackPanel Grid.Column="1"
Grid.Row="0"
Orientation="Horizontal">
<TextBlock Name="txtblk1" Text="{Binding value1}" />
</StackPanel>
<StackPanel Grid.Column="2"
Grid.Row="0"
Orientation="Horizontal">
<TextBlock Name="txtblk2" Text="{Binding value2}" />
</StackPanel>
<StackPanel Grid.Column="3"
Grid.Row="0"
Orientation="Horizontal">
<TextBlock Name="txtblk3" Text="{Binding value3}" />
</StackPanel>
<StackPanel Grid.Column="4"
Grid.Row="0"
Orientation="Horizontal">
<TextBlock Name="txtblk4" Text="{Binding value4}" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
This way each word from line is put on separate column. TextBlocks don't overlap anymore.
Unfortunately I didn't manage do showcase all file(all lines). For now each row in xaml is populated with same line from the file instead of pulling each line into separate rows in xaml.
What should I do in order to list all lines instead of just one line?
I believe that there is problem on C# code side.
First create class for data:
public class itemsdata
{
public string txt0 { get; set; }
public string txt1 { get; set; }
public string txt2 { get; set; }
public string txt3 { get; set; }
public string txt4 { get; set; }
}
after it, create collection
ObservableCollection<itemsdata> items = new ObservableCollection<itemsdata>();
and fill it:
for (int index = 0; index < splitLines.Length; index++)
{
itemsdata dataitem=new itemsdata
{
txt0=splitLines[0];
txt1=splitLines[1];
txt2=splitLines[2];
txt2=splitLines[3];
txt2=splitLines[4];
}
items.Add(dataitem);
}
itemsControl.DataContext = items;
change binging to
ItemsSource="{Binding}"
and add new fields to datatemplate
<TextBlock Name="txtblk0" Text="{Binding txt0}" />
<TextBlock Name="txtblk1" Text="{Binding txt1}" />
<TextBlock Name="txtblk2" Text="{Binding txt2}" />
<TextBlock Name="txtblk3" Text="{Binding txt3}" />
<TextBlock Name="txtblk4" Text="{Binding txt4}" />
Related
I have task to create in C# UWP user created check-list.
But I have stuck from the beginning cause XAML is new for me, so I have no idea what to start from.
So, I have textbox to enter title, task or subtask to in listbox (priviously added to) selected task.
this is my xaml how it looks like now:
<Page
x:Class="Table1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Table1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<TextBox x:Name="txt" HorizontalAlignment="Left" Height="71" Margin="71,247,0,0" Text="TextBox" VerticalAlignment="Top" Width="395"/>
<RadioButton x:Name="title" Content="Add Title" HorizontalAlignment="Left" Margin="71,86,0,0" VerticalAlignment="Top"/>
<RadioButton x:Name="task" Content="Add Task" HorizontalAlignment="Left" Margin="71,123,0,0" VerticalAlignment="Top"/>
<RadioButton x:Name="subtask" Content="Add Subtask" HorizontalAlignment="Left" Margin="71,155,0,0" VerticalAlignment="Top"/>
<ListBox x:Name="listbox" HorizontalAlignment="Left" Height="68" Margin="71,354,0,0" VerticalAlignment="Top" Width="395"/>
<Button x:Name="btn" Content="Button" HorizontalAlignment="Left" Margin="401,483,0,0" VerticalAlignment="Top" Click="btn_Click"/>
</Grid>
</Page>
There are the code:
public class subtasks
{
public string parent { get; set; }
public string subtask { get; set; }
public subtasks(string parenti, string subtaski)
{
parent = parenti;
subtask = subtaski;
}
public void setsub(string parenti, string sub)
{
parent = parenti;
subtask = sub;
}
}
List<string> Tasks = new List<string>();
List<subtasks> sub = new List<subtasks>();
private void btn_Click(object sender, RoutedEventArgs e)
{
string parent = "";
string Title;
string Task;
string Subtask;
if (title.IsChecked==true)
{
Title = txt.Text;
adding(Title, parent, 1);
}
else if (task.IsChecked==true)
{
Task = txt.Text;
adding(Task, parent, 2);
}
else if (subtask.IsChecked==true)
{
parent = listbox.SelectedItem.ToString();
Subtask = txt.Text;
adding(Subtask, parent, 3);
}
else
{
}
}
private void adding(string str, string par, int x)
{
subtasks subi = new subtasks(par,str);
RowDefinition row = new RowDefinition();
TextBlock text = new TextBlock();
if (x==1)
{
print(str);
}
else if (x==2)
{
Tasks.Add(str);
listbox.Items.Add(str);
text.Text = str;
print(str);
}
else
{
sub.Add(subi);
print(str);
}
}
private void print(string title)
{
int step = 0;
Grid gridwin = new Grid();
gridwin.Children.Clear();
RowDefinition row = new RowDefinition();
TextBlock text = new TextBlock();
text.Text = title;
Grid.SetColumn(text, 0);
Grid.SetRow(text, step);
step++;
for (int i = 0; i < Tasks.Count; i++)
{
text.Text = Tasks[i].ToString();
gridwin.Children.Add(text);
Grid.SetColumn(text, 0);
Grid.SetRow(text, step);
step++;
for (int k = 0; k < sub.Count; k++)
{
if (sub[k].parent == Tasks[i])
{
text.Text = sub[k].subtask.ToString();
gridwin.Children.Add(text);
Grid.SetColumn(text, 0);
Grid.SetRow(text, step);
step++;
}
}
}
}
As you see I need to clear and put data every time the button is clicked, cause you never know when user will decide to add new subtask for previously added task. So, the question is, how to make the table with column1 with tasks and subtasks and column2 which is chekbox.
What you want to probably do is to create a DataTemplate. You use this to specify how list items should be displayed and formatted. This way you can specify you want to lay them out as a Grid with two columns like description and CheckBox. Take a look into the documentation to see some examples of DataTemplates. You can also see the Azure Mobile Apps quickstart for UWP, because although it is focused on demonstrating Microsoft Azure integration to UWP, it is actually a to-do app, which should give you some inspiration for building your own.
The layout could look like this:
<ListBox x:Name="listbox" HorizontalAlignment="Left" Height="68" Margin="71,354,0,0" VerticalAlignment="Top" Width="395">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Text}" />
<CheckBox Grid.Column="1" IsChecked="{Binding IsChecked, Mode=TwoWay}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You can see my code is also using {Binding} syntax, which you will also need to learn a bit about to be able to know when the user has checked a to-do item in the list. I suggest you to take a look at a simple tutorial sample like here. In fact, data-binding is one of the most important things when building XAML-based apps and when you get to understand this concept, it will help you a lot on the way to becoming a UWP ninja :-) .
Why dont use the UWP DataGrid with CheckBox?
XAML
<toolkit:DataGrid Grid.Column="0" ItemsSource="{x:Bind myItemsToBind}"
x:Name="dgwDeviceSPNs" MinWidth="100"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible"
AlternatingRowBackground="Transparent"
AreRowDetailsFrozen="False"
AreRowGroupHeadersFrozen="True"
AutoGenerateColumns="False"
CanUserSortColumns="False"
CanUserReorderColumns="True"
RowGroupHeaderPropertyNameAlternative=""
CanUserResizeColumns="True"
MaxColumnWidth="200"
FrozenColumnCount="0"
GridLinesVisibility="Horizontal"
HeadersVisibility="None"
IsReadOnly="True"
RowDetailsVisibilityMode="Collapsed"
SelectionMode="Single">
<toolkit:DataGrid.Columns>
<toolkit:DataGridTemplateColumn MinWidth="10">
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Padding="2">
<CheckBox ToolTipService.ToolTip="{Binding Name}" IsChecked="{Binding IsSelected, Mode=TwoWay}" Content="{Binding Name}"></CheckBox>
</StackPanel>
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
</toolkit:DataGridTemplateColumn>
</toolkit:DataGrid.Columns>
</toolkit:DataGrid>
I have a Silverlight application that is using a ItemsControl. Inside of that ItemsControl I have a DataTemplate that is defined like the following:
XAML
<ItemsControl Grid.Row="1" Grid.ColumnSpan="5" x:Name="dgOdds">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="gRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="OF1" Grid.Column="0" Text="{Binding OddFactor, Mode=TwoWay}" FontWeight="Bold" VerticalAlignment="Center" HorizontalContentAlignment="Center"/>
<TextBox x:Name="OFX" Grid.Column="1" Text="{Binding OddFactor, Mode=TwoWay}" FontWeight="Bold" VerticalAlignment="Center" HorizontalContentAlignment="Center"/>
<TextBox x:Name="OF2" Grid.Column="2" Text="{Binding OddFactor, Mode=TwoWay}" FontWeight="Bold" VerticalAlignment="Center" HorizontalContentAlignment="Center"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have a list of objects:
C#
ObservableCollection<TestObj> SomeList = new ObservableCollection<TestObj>;
SomeList.Add(new TestObj(){ OddType = 1, OddFakctor = 1.1 });
SomeList.Add(new TestObj(){ OddType = 2, OddFakctor = 2.2 });
SomeList.Add(new TestObj(){ OddType = 3, OddFakctor = 3.3 });
this.dgOdds.ItemsSource = this.Collection;
The TestObj class is as follows:
public class TestObj
{
public double OddType { get; set;}
public double OddFakctor { get; set; }
}
I want to display the properties in my controls something like:
If OddType equal 1, than show in TextBox x:Name="OF1",
if OddType equal 2, than show in TextBox x:Name="OFX",
if OddType equal 3, than show in TextBox x:Name="OF3"
How to do this?
since u want to show the OddType equals to 1 or 2 or 3, u can have only a single textblock.
As if 1 is selected, then one of the TextBox would have OF1 and others will be null.
private double _oddfactor;
public double OddFakctor
{
get
{
return _oddfactor;
}
set
{
_oddfactor = value;
OnPropertyChanged(() => OddFakctor);
}
}
if here u update the _OddFakctor , it will bind the text box with the value wat u r passing to that _oddfactor
Please have a look at this image to understand my scenario
So I have the above scenario in my Windows Phone application where I have a ListBox with the below layout.
My XAML for the ListBox
<ListBox x:Name="llsIceCreamBrands" Margin="0,54,0,0" CacheMode="BitmapCache">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,40">
<StackPanel>
<Border BorderBrush="{StaticResource PhoneProgressBarBackgroundBrush}" BorderThickness="3">
<Image Width="200" Height="200" Source="{Binding IceCreamBrandImage }" Margin="3,0,0,0" Stretch="Fill"/>
</Border>
</StackPanel>
<StackPanel>
<Grid Margin="20,-5,0,0" Height="250" >
<StackPanel>
<TextBlock Text="{Binding IceCreamBrandName }" FontWeight="SemiBold" FontSize="34" FontFamily="Segoe WP" Margin="0" TextWrapping="Wrap" Width="184" VerticalAlignment="Top" HorizontalAlignment="Left" Opacity="1" LineStackingStrategy="BlockLineHeight" LineHeight="35" Height="Auto" />
<TextBlock Text="{Binding IceCreamBrandFlavour }" FontWeight="Normal" FontSize="15" FontFamily="Segoe WP" TextWrapping="Wrap" VerticalAlignment="Top" Width="200" Opacity="0.7" HorizontalAlignment="Left" IsHitTestVisible="False" Height="140"/>
</StackPanel>
</Grid>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In C# Code:
void GetIceCreamBrands()
{
string mystring = "";
for (int i = 0; i < dc.IceCreams[cID].Brands.Count; i++)
{
var bmp = new BitmapImage();
if (dc.IceCreams[cID].Brands[i].HasArt)
{
bmp.SetSource(dc.IceCreams[cID].Brands[i].GetImage());
}
else
{
bmp.CreateOptions = BitmapCreateOptions.None;
bmp.UriSource = new Uri("/Assets/Images/IceCreams/Placeholder.png", UriKind.Relative);
}
for (int j = 0; j < dc.IceCreams[cID].Brands.Count; j++)
{
for (int k = 0; k < dc.IceCreams[cID].Brands[j].Flavour.Count; k++)
{
sourceFlavourList.Add(new Flavour
{
FlavourBrand = dc.IceCreams[cID].Brands[j].Name,
BrandFlavourName = dc.IceCreams[cID].Brands[j].Flavour[k].Name
});
}
}
sourceIceCreamBrands.Add(new IceCreamBrands
{
IceCreamBrandName = dc.IceCreams[cID].Brands[i].Name,
IceCreamBrandImage = bmp,
IceCreamBrandFlavour = "Get Flavours here for the particular brand somehow?"
});
}
llsIceCreamBrands.ItemsSource = sourceIceCreamBrands.ToList();
}
I have the above method in my code which successfully gets the brands and their images, but the flavours are also a Collection which I tried to get in a single string by using
string mystring = string.Join(Environment.NewLine, sourceFlavourList.Select(x => x.IceCreamBrandFlavourName));
But this returns the same values for both Ben&Jerrys and Haagen-Dazs - which is an amalgamation of both brands' flavours.
How can I achieve what I'm looking for?
I don't see where you define the variable 'sourceFlavourList' within GetIceCreamBrands(), so I assume you have this defined elsewhere in your code. This would explain why you see the full list of flavours (from both brands) as you keep adding all flavours to this one variable.
So instead of using this full list variable, you would need to bind to a per brand list (which you DO have in your result)., so you can use the same linq you have, but with a different source variable).
Try something like this:
var flavours = string.Join(Environment.NewLine, dc.IceCreams[cID].Brands[j].Flavour.Select(x => x.Name));
sourceIceCreamBrands.Add(new IceCreamBrands
{
IceCreamBrandName = dc.IceCreams[cID].Brands[i].Name,
IceCreamBrandImage = bmp,
IceCreamBrandFlavour = flavours
});
I want to binding my itemscontrol in listbox, but it doesn't work. I want to add some FrameworkElement to Listbox with stack style.
Here is my XAML code:
<ListBox x:Name="listThemes">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" FontWeight="Bold" />
<StackPanel Grid.Row="1" >
<ItemsControl Width="Auto"
Height="Auto"
ItemsSource="{Binding ElementName=listThemes, Path=Items}">
</ItemsControl>
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I don't know how to binding ItemsControl inside ListBox. I try put out the Binding ElementName of ItemsControl but it's always crashes. If the ElementName is page name, it not work.
Testing Class :
public class Testing
{
public string Title { get; set; }
public ObservableCollection<FrameworkElement> Items { get; set; }
}
C# Code :
observableCollection = new ObservableCollection<FrameworkElement>();
for (int i = 0; i < 3; i++)
{
observableCollection.Add(new Button { Content = i.ToString() });
observableCollection.Add(new Canvas
{
Background = new ImageBrush()
{
ImageSource = new BitmapImage(new Uri(#"Assets/ApplicationIcon.png", UriKind.Relative)),
Stretch = System.Windows.Media.Stretch.Fill
},
Height = 100,
Width = 100
});
}
List<Testing> list = new List<Testing>();
for (int i = 0; i < 3; i++)
{
Testing test = new Testing();
test.Title = "Testing";
test.Items = observableCollection;
list.Add(test);
}
listThemes.ItemsSource = list;
First, it crashes because you bind the same elements on three different item. One framework element can't be attach under two different control. So you should place your ObservableCollection in your List<Testing> creating process.
Second, you should set a DataContext to your listThemes control, so its items can find the right data path to bind and then you could remove the ElementName.
Try these code.
List<Testing> list = new List<Testing>();
for (int i = 0; i < 3; i++)
{
Testing test = new Testing();
test.Title = "Testing";
var observableCollection = new ObservableCollection<FrameworkElement>();
for (int j = 0; i < 3; i++)
{
observableCollection.Add(new Button { Content = j.ToString() });
observableCollection.Add(new Canvas
{
Background = new ImageBrush()
{
ImageSource = new BitmapImage(new Uri(#"Assets/ApplicationIcon.png", UriKind.Relative)),
Stretch = System.Windows.Media.Stretch.Fill
},
Height = 100,
Width = 100
});
}
test.Items = observableCollection;
list.Add(test);
}
listThemes.DataContext = list;
listThemes.ItemsSource = list;
Third, I don't think it is a good way to bind your FrameworkElement directly to an ItemsControl. It just look weird.
Update:
If you want to generate different types of items, you can use DataTemplateSelector. Because you already parse the forum data into different type, so please check this post:
How to Control the DataTemplateSelector in Windows Store Apps
It explains how to use DataTemplateSelector to display different type of data.
Why is your inner collection of type FrameworkElement?
Create a custom type for it and set an ItemTemplate for your inner ItemsControl.
<DataTemplate x:Key=NestedItemsTemplate>
....
</DataTemplate>
<ListBox x:Name="listThemes"
ItemsSource="{Binding TestItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" FontWeight="Bold" />
<StackPanel Grid.Row="1" >
<ItemsControl
Width="Auto" Height="Auto"
ItemsSource="{Binding ElementName=listThemes, Path=Items}"
ItemTemplate="{StaticResource NestedItemsTemplate}">
</ItemsControl>
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
I'm trying to use a Pie Chart from the SyncFusion WinRT Studio in my new Win8 C#/XAML store app, and I can't figure out how to set the data on the chart. I have the chart on my page and have tried everything I can find to set the data to make things show up, but I can't get it to work. The sample apps aren't much help because there is 0 code in their pages and I can't figure out what's different. The chart below is copied right from their sample, but it doesn't work in my app. Anyone have any samples of using a SyncFusion chart in a WinRT app?
Chart in XAML:
<Grid Margin="30,15,30,30" x:Name="ChartGrid">
<Grid.Resources>
<local:Labelconvertor x:Key="labelconverter"/>
<Style TargetType="Line" x:Key="lineStyle">
<Setter Property="StrokeThickness" Value="0"/>
</Style>
<DataTemplate x:Key="labelTemplate">
<TextBlock Margin="10,0,0,0" Text="{Binding Converter={StaticResource labelconverter}}" FontSize="26" FontFamily="Segoe UI" FontWeight="Light" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Top" Opacity="0.5"></TextBlock>
</DataTemplate>
<DataTemplate x:Key="legend">
<StackPanel Orientation="Horizontal">
<Grid Margin="10,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Width="15" Height="15" Fill="{Binding Interior}"></Rectangle>
<TextBlock Margin="10,5,5,0" Grid.Column="1" Text="{Binding Item.Expense}"></TextBlock>
</Grid>
</StackPanel>
</DataTemplate>
</Grid.Resources>
<Grid.DataContext>
<local:PieChartViewModel/>
</Grid.DataContext>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Margin="0,0,0,20">
</StackPanel>
<chart:Chart x:Name="ScatterChart" AreaBorderThickness="0" HorizontalAlignment="Center" Grid.RowSpan="2" Visibility="Visible">
<chart:Chart.Header>
<TextBlock FontSize="20" FontFamily="Segoe UI" Margin="0,20,0,10">Agriculture Expenses Comparison</TextBlock>
</chart:Chart.Header>
<chart:Chart.PrimaryAxis>
<chart:ChartAxis></chart:ChartAxis>
</chart:Chart.PrimaryAxis>
<chart:Chart.SecondaryAxis>
<chart:ChartAxis></chart:ChartAxis>
</chart:Chart.SecondaryAxis>
<chart:Chart.Legend>
<chart:ChartLegend CornerRadius="0" ItemTemplate="{StaticResource legend}" CheckBoxVisibility="Visible" BorderThickness="1">
</chart:ChartLegend>
</chart:Chart.Legend>
<chart:PieSeries ItemsSource="{Binding Expenditure}" XBindingPath="Expense" x:Name="pieSeries" ExplodeAll="{Binding Path=IsChecked,ElementName=chkExplode}" ExplodedRadius="{Binding Path=Value,ElementName=slRadius}" Palette="Metro" Label="Expenditures" YBindingPath="Amount">
<chart:PieSeries.AdornmentsInfo>
<chart:ChartAdornmentInfo AdornmentsPosition="Bottom" HorizontalAlignment="Center" VerticalAlignment="Center" ConnectorLineStyle="{StaticResource lineStyle}" ShowConnectorLine="True" ConnectorHeight="30" ShowLabel="True" LabelTemplate="{StaticResource labelTemplate}" SegmentLabelContent="YValue">
</chart:ChartAdornmentInfo>
</chart:PieSeries.AdornmentsInfo>
</chart:PieSeries>
</chart:Chart>
</Grid>
</StackPanel>
</Grid>
Code-Behind called from the LoadState function: (I've tried all of these options and none of them work...)
PieChartViewModel pvm = new PieChartViewModel();
this.DefaultViewModel["PieChartViewModel"] = pvm;
this.DefaultViewModel["DataContext"] = pvm;
this.DefaultViewModel["Items"] = pvm;
this.DefaultViewModel["DefaultViewModel"] = pvm;
this.ScatterChart.DataContext = pvm;
this.ChartGrid.DataContext = pvm;
Object Definition:
public class PieChartViewModel
{
public PieChartViewModel()
{
this.Expenditure = new List<CompanyExpense>();
Expenditure.Add(new CompanyExpense() { Expense = "Seeds", Amount = 20d });
Expenditure.Add(new CompanyExpense() { Expense = "Fertilizers", Amount = 23d });
Expenditure.Add(new CompanyExpense() { Expense = "Insurance", Amount = 12d });
Expenditure.Add(new CompanyExpense() { Expense = "Labor", Amount = 28d });
Expenditure.Add(new CompanyExpense() { Expense = "Warehousing", Amount = 10d });
Expenditure.Add(new CompanyExpense() { Expense = "Taxes", Amount = 10d });
Expenditure.Add(new CompanyExpense() { Expense = "Truck", Amount = 10d });
}
public IList<CompanyExpense> Expenditure
{
get;
set;
}
}
public class CompanyExpense
{
public string Expense { get; set; }
public double Amount { get; set; }
}
I was able to populate the pie chart using the same data without problem. Please find the sample at PieChartDemo
Here is the document that explains how to configure Pie Chart: PieChartHelp
Following are the three APIs used for providing data for generating PieSeries,
ItemsSource - You can provide the data source using this property. Any IEnumerable can be given as data source.
XBindingPath - It is used to provide the path for category data in the source object.
YBindingPath - It is used to provide the path for numeric data in the source object.