What is the function of Message sender in xamarin.forms - xamarin

What is the function of Message sender in xamarin.forms? In my app I have cart contain list view and a Grant Total label. Is it possible to update the label using message sender? I can get the total amount from my sqlite db I need to update it to the view.
This is my number picker index change event in view cell
numPicker.SelectedIndexChanged += (sender, args) =>
{
// var price = _cartQuery.GetSum();
sender = BindingContext;
// cm_items item = (cm_items)sender;
if(Int32.Parse(btn_NumBtn.Text)<=1)
{
lbl_Price.Text = ((numPicker.SelectedIndex + 1) * (Int32.Parse(lbl_Price.Text))).ToString();
btn_NumBtn.Text = (numPicker.SelectedIndex + 1).ToString();
}
else
{
int a = Int32.Parse(lbl_Price.Text);
int b = Int32.Parse(btn_NumBtn.Text);
int c = a / b;
lbl_Price.Text = ((numPicker.SelectedIndex + 1) * c).ToString();
btn_NumBtn.Text = (numPicker.SelectedIndex + 1).ToString();
}
_cartQuery.UpdatePicker((BindingContext as CartDB).Cart_Item_Id, numPicker.SelectedIndex + 1, Int32.Parse(lbl_Price.Text));
price = _cartQuery.GetSum();
// App.Instance.ViewModel.TotalAmount = price;
// _cartDB.total = App.Instance.ViewModel.TotalAmount;
Calculate_price();
numPicker.IsEnabled = false;
};
Calculate_price method
public double Calculate_price()
{
try
{
var price = 0;
price = _cartQuery.GetSum();
App.Instance.ViewModel.TotalAmount = price;
return price;
}
catch (Exception ex)
{
throw ex;
}
}
In my view i have a label named grant total, i need to update the total on e number picker change
Label lbl_amnt = new Label
{
// Text = viewModel.Price.ToString(),
// Text=CartCell.price.ToString(),
Text = price.ToString(),
FontSize = 18,
FontAttributes = FontAttributes.Bold,
TextColor = Color.FromRgb(102, 204, 102),
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.EndAndExpand,
};
lbl_amnt.SetBinding(Label.TextProperty, "TotalAmount");
update to my post as per the comment from #Grish
In my view model i have this TotalAmount as a property
public double _TotalAmount;
public double TotalAmount
{
get { return _TotalAmount; }
set { _TotalAmount = value; OnPropertyChanged("TotalAmount");}
}
I think the better solution is i notify but the thing is view is not binding

Binding is definitely the answer in your case. I think the problem is that you bind string (label's text) to property of type double.
You should specify IValueConverter or stringFormat parameters in your call to SetBinding.
Check this link:
https://forums.xamarin.com/discussion/19146/binding-to-integers

Related

Adding a swipe to next gesture using Syncfusion.SfChart

Currently on my app when the user selects their 'symptom' they are directed to the detail page which shows their symptom chart with the populated feedback data from their selected symptom.
Is their a way i can add a swipe gesture to allow the user to swipe to the next symptom chart without having to go back to main symptoms page and selecting a symptom.
Currently this is how i populate my chart :
public async Task GetSymptomFeedback(string id)
{
SymptomFeedbackData.Clear();
symptomChart.Series.Clear();
BusyIndicator.IsRunning = true;
SymptomFeedbackData = await symptomsfeedbackmanager.getUserSymptomFeedback(id);
foreach (var FeedbackItem in SymptomFeedbackData)
{
FeedbackItem.Idusersymptomid = FeedbackItem.Id + ',' + FeedbackItem.Usersymptomid;
}
IEnumerable<SymptomFeedback> OrdreredFeedbackData = SymptomFeedbackData.OrderBy(X => X.DateTime);
LineSeries columnseries = new LineSeries
{
ItemsSource = OrdreredFeedbackData,
XBindingPath = "DateTime",
YBindingPath = "Intensity",
DataMarker = new ChartDataMarker
{
ShowLabel = true,
ShowMarker = true,
MarkerHeight = 5,
MarkerWidth = 5,
MarkerColor = Xamarin.Forms.Color.Purple
}
};
BusyIndicator.IsRunning = false;
symptomChart.PrimaryAxis.ShowTrackballInfo = true;
if (columnseries.ItemsSource != null)
{
symptomChart.Series.Add(columnseries);
}
symptomChart.ChartBehaviors.Add(new ChartTrackballBehavior());
//Sort Collection by datetime
SymptomsList.ItemsSource = OrdreredFeedbackData.Reverse();
}
Solution:
Through your code, we can see you query the data through the id of symptom. So, I guess you pass this id as parameter when you go to the detail page from main symptoms page.
Is their a way i can add a swipe gesture to allow the user to swipe to
the next symptom chart without having to go back to main symptoms page
and selecting a symptom.
In additional, you can pass a array of id of all symptoms to detail page. Let's name this array as symptomIdArray.
Then add a SwipeGestureRecognizer to your view.
var DownSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Down };
var UpSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Up };
DownSwipeGesture.Swiped += OnSwiped;
UpSwipeGesture.Swiped += OnSwiped;
this.Content.GestureRecognizers.Add(DownSwipeGesture);
this.Content.GestureRecognizers.Add(UpSwipeGesture);
In the OnSwiped, you can get last or next id through the symptomIdArray and currentID , and then you can choose to reload your current page or go to a new page to swipe to the next symptom chart, here is code:
public Array symptomIdArray; // ids of all symptom
public string currentID; // You selected id of current symptom
void OnSwiped(object sender, SwipedEventArgs e)
{
int index = Array.IndexOf(symptomIdArray, currentID);
switch (e.Direction)
{
case SwipeDirection.Up:
if (index ==0)
{
//first one
break;
}
string lastID = (string)symptomIdArray.GetValue(index-1);
//1.You can refresh current page with lastId
GetSymptomFeedback(lastID);
//2.You can go to a new page with lastID ID and symptomIdArray
Navigation.PushAsync(new NewPage(lastID, symptomIdArray));
break;
case SwipeDirection.Down:
// Handle the swipe
if (index == symptomIdArray.Length-1)
{
//Last one, no more
break;
}
string nextID = (string)symptomIdArray.GetValue(index+1);
//1.You can refresh current page with next currentID
GetSymptomFeedback(nextID);
//2.You can go to a new page with nextID ID and symptomIdArray
Navigation.PushAsync(new NewPage(nextID, symptomIdArray));
break;
}
}
Update:
Add SwipeGestureRecognizer:
SfChart chart = new SfChart();
chart.Title.Text = "Chart";
//Config chart....
...
chart.Series.Add(series);
this.Content = chart;
var DownSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Down };
var UpSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Up };
DownSwipeGesture.Swiped += OnSwiped;
UpSwipeGesture.Swiped += OnSwiped;
chart.GestureRecognizers.Add(DownSwipeGesture);
chart.GestureRecognizers.Add(UpSwipeGesture);
And onSwipe:
void OnSwiped(object sender, SwipedEventArgs e)
{
switch (e.Direction)
{
case SwipeDirection.Up:
Console.WriteLine("up");
break;
case SwipeDirection.Down:
Console.WriteLine("down");
break;
}
}
Let me know if you have any question.

winforms, help needed to create a dynamic tablelayoutpanel with buttons

I am trying to create a dynamic tablelayout which creates adds a skill and gives that skill 1 level and a increase decrease button. I am struggling with having the buttons access the level label. I thought about finding the location of the button that was clicked, but could figure out how to do that.
In advance, Thank you.
example:
1
this is what i have so far:
private void skilladded(object sender, EventArgs e)
{
int i = 1;
int[] position= { 0,0};
bool test = false;
//string select;
int k=0;
for (i=1;i<=skillstableLayoutPanel.RowCount;i++)
{
Control c= skillstableLayoutPanel.GetControlFromPosition(0,i);
if (c!=null&&addskillswin.selected==c.Text)
{
test = true;
k = i;
break;
}
else if(c==null)
{
k = i;
break;
}
}
if (test==false)
{
Label newskill = new Label();
Label newskilllvl = new Label();
TableLayoutPanel buttontable = new TableLayoutPanel();
Button up = new Button();
Button down = new Button();
buttontable.ColumnCount = 2;
buttontable.RowCount = 1;
buttontable.RowStyles.Add(new RowStyle(SizeType.Percent,100f));
buttontable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent,50f));
buttontable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50f));
buttontable.Margin = new Padding(0,0,0,0);
buttontable.Dock = DockStyle.Fill;
buttontable.Controls.Add(up, 0, 0);
buttontable.Controls.Add(down, 1, 0);
up.BackgroundImage = Properties.Resources.up;[enter image description here][2]
down.BackgroundImage = Properties.Resources.down;
up.BackgroundImageLayout=ImageLayout.Stretch;
down.BackgroundImageLayout = ImageLayout.Stretch;
newskill.Text = addskillswin.selected;
newskilllvl.Text = "1";
up.Margin = new Padding(0, 0, 0, 0);
down.Margin = new Padding(0, 0, 0, 0);
skillstableLayoutPanel.Controls.Add(newskill,0,k);
skillstableLayoutPanel.Controls.Add(newskilllvl, 1, k);
skillstableLayoutPanel.Controls.Add(buttontable, 2, k);
skillavaillabel.Text = (Convert.ToInt32(skillavaillabel.Text) - 1).ToString();
skillpointlvl = Convert.ToInt32(newskilllvl.Text);
up.MouseClick += new MouseEventHandler(skillup);
down.MouseClick += new MouseEventHandler(skilldown);
}
if (test==true)
{
skillstableLayoutPanel.GetControlFromPosition(1, k).Text = (Convert.ToInt32(skillstableLayoutPanel.GetControlFromPosition(1, k).Text) + 1).ToString();
skillavaillabel.Text = (Convert.ToInt32(skillavaillabel.Text) -1).ToString();
}
}
private void skillup(object sender, EventArgs e)
{
skillpointlvl++;
}
private void skilldown(object sender, EventArgs e)
{
skillpointlvl--;
}
Instead of this:
up.MouseClick += new MouseEventHandler(skillup);
down.MouseClick += new MouseEventHandler(skilldown);
Try something like this:
up.MouseClick += ((o, me) =>
{
int currentLevel = Int32.Parse(newskilllvl.Text);
currentLevel++;
newskilllvl.Text = currentLevel.ToString();
});
down.MouseClick += ((o, me) =>
{
int currentLevel = Int32.Parse(newskilllvl.Text);
currentLevel--;
newskilllvl.Text = currentLevel.ToString();
});
Your skillup or skilldown event handler could potentially process each sender and see from which button the click originated, but you'd have to uniquely name each button and do a lot of string comparisons to see which button corresponds to which skill level label. The code above adds an anonymous handler to each button, which allows us to essentially tie the button being clicked to its corresponding skill label.
Personally though, I would not store all these values in labels like you have done. I would either store them in properties on the form, or better yet in a class of their own. I would also put all this logic somewhere else beside the form, like in a Presenter or Controller (or class library), and follow a design pattern such as MVC or MVP. This will make maintaining and changing the application easier in the long run.
Also, consider using camel case and Pascal case for your variable names. All lowercase variables are harder for experienced programmers to read.

dynamically change an image via c# script in Xamarin forms

I have a cross platform app which I need to show a set of images when the user clic in a button, so, I put these image files named as "img000.png" to "img029.png" in a folder in the PCL solution and make al these images as "EmbeddedResource", after,I fill a List with all these images and its work fine at now, i.e. the image is shown like I want, but when I click in the button to show the next image in the list the image don't go to the next.
I have this:
//...
public class ImageSetPage : BasePage
// BasePage encapsule a ContentPage...
{
private string directory = "MyApp.Assets.";
private int idx = 0;
protected StackLayout _mainLayout;
protected StackLayout _buttonStack;
protected Image _btnPrevI;
protected Label _displayName;
protected Image _btnNestI;
protected Image _image;
protected List<Image> _Images;
public ImageSetPage()
{
this._Images = getImages();
var prevI_Tap = new TapGestureRecognizer();
prevI_Tap.Tapped += (s, e) =>
{
onClick("pvi");
};
var nextI_Tap = new TapGestureRecognizer();
nextI_Tap.Tapped += (s, e) =>
{
onClick("nti");
};
/// begin layout
base.Title = "set of Images";
this._mainLayout = new StackLayout()
{
Orientation = StackOrientation.Vertical,
BackgroundColor = Color.Black,
Padding = new Thickness(0, 10, 0, 0)
};
this._btnPrevI = new Image()
{
Aspect = Aspect.AspectFill,
Source = ImageSource.FromResource(directory+"prevbtn.png")
};
_btnPrevI.GestureRecognizers.Add(prevI_Tap);
this._displayName = new Label()
{
Style = Device.Styles.SubtitleStyle,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
TextColor = Color.White,
};
this._btnNextI = new Image()
{
Aspect = Aspect.AspectFill,
Source = ImageSource.FromResource(directory + "nextbtn.png")
};
_btnNextI.GestureRecognizers.Add(nextI_Tap);
this._buttonStack.Children.Add(_btnPrevI);
this._buttonStack.Children.Add(_displayName);
this._buttonStack.Children.Add(_btnNextI);
this._mainLayout.Children.Add(_buttonStack);
FillImage(idx);
this._mainLayout.Children.Add(this._image);
this.Content = this._mainLayout;
}
private void FillImage(int i)
{
this._displayName.Text = "Image n# " + FillWithZeroes(i);
// [EDIT 1] cemented these lines ...
// this._image = null;
// mi = _images[i];
// this._image = mi;
// [EDIT 2] the new try
string f = directory + "imgs.img0" + FillWithZeroes(i) + ".png";
this._image = new Image() {
VerticalOptions = LayoutOptions.Center,
Soruce = ImageSource.FromResource(f)
};
// In this way the image show and don't change when click
// this Fking* code is a big S_OF_THE_B*
// The Xamarin and the C# is brothers of this FKing* code
}
private void onClick(string v)
{
string vw = v;
if (vw.Equals("pvi")) idx--;
if (vw.Equals("nti")) idx++;
if (idx <= 0) idx = 29;
if (idx >= 29) idx = 0;
FillImage(idx);
vw = "";
}
private string FillWithZeroes(int v)
{
string s = v.ToString();
string r = "";
if (s.Length == 1) { r = "0" + s; } else { r = s; }
return r;
}
// to fill a list of Images with files in a PCL folder
private List<Image> getImages()
{
string directory = "MyApp.Assets.";
List<Image> imgCards = new List<Image>();
int c = 0;
for (c = 0; c < 30;c++) {
string f = directory + "imgs.img0" + FillWithZeroes(c) + ".png";
Image img = new Image();
img.Source = ImageSource.FromResource(f);
imgCards.Add(img);
}
return imgCards;
}
// ...
}
but the image don't change, i.e. change, like I see in debug, but don't show in the Layout when I click in the buttons.
Maybe I'm doing it wrong.
Can someone here help me?
thanks in advance

Inserting image in PPTX using OpenXML does not work

I am trying to generate a PowerPoint file containing a image using OpenXML. Unfortunately it does not work. The image is not being displayed. I've checked the file generated with the OpenXML productivity tool and I respectively unzipped the file contents. The file itself contains the image in /ppt/media/image.png and it should be displayed in the second slide.
Here's my code:
private void InsertSlide(string chartString, int position, string title, string text = "")
{
if (m_presentation == null || title == null || m_presentation.PresentationPart == null)
return;
var slide = new Slide(new CommonSlideData(new ShapeTree()));
var nonVisualProperties =
slide.CommonSlideData.ShapeTree.AppendChild(new NonVisualGroupShapeProperties());
nonVisualProperties.NonVisualDrawingProperties = new NonVisualDrawingProperties { Id = 1, Name = "" };
nonVisualProperties.NonVisualGroupShapeDrawingProperties = new NonVisualGroupShapeDrawingProperties();
nonVisualProperties.ApplicationNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
slide.CommonSlideData.ShapeTree.AppendChild(new GroupShapeProperties());
var slidePart = m_presentation.PresentationPart.AddNewPart<SlidePart>();
var imagePart = slidePart.AddImagePart(ImagePartType.Png, "irgendeinscheiss");
//var imageStream = new MemoryStream(Convert.FromBase64String(chartString));
using (var imageStream = new FileStream(#"C:\Users\DA\Desktop\Charts\1_Chart2_01.png", FileMode.Open))
{
imageStream.Position = 0;
imagePart.FeedData(imageStream);
}
slide.Save(slidePart);
var slideIdList = m_presentation.PresentationPart.Presentation.SlideIdList;
uint maxSlideId = 1;
SlideId prevSlideId = null;
foreach (SlideId slideId in slideIdList.ChildElements)
{
if (slideId.Id > maxSlideId)
maxSlideId = slideId.Id;
position--;
if (position == 0)
prevSlideId = slideId;
}
maxSlideId++;
SlidePart lastSlidePart;
if (prevSlideId != null)
lastSlidePart = (SlidePart)m_presentation.PresentationPart.GetPartById(prevSlideId.RelationshipId);
else
lastSlidePart = (SlidePart)m_presentation.PresentationPart.GetPartById(((SlideId)(slideIdList.ChildElements[0])).RelationshipId);
if (lastSlidePart.SlideLayoutPart != null)
slidePart.AddPart(lastSlidePart.SlideLayoutPart);
var newSlideId = slideIdList.InsertAfter(new SlideId(), prevSlideId);
newSlideId.Id = maxSlideId;
newSlideId.RelationshipId = m_presentation.PresentationPart.GetIdOfPart(slidePart);
m_presentation.PresentationPart.Presentation.Save();
}
Am I missing something? Maybe the relationships? After looking up 232243 thousand different examples, I am still stuck at this point. Thank you!
I think you need to add the image into the slide.CommonSlideData
public Slide InsertSlide(PresentationPart presentationPart, string layoutName)
{
UInt32 slideId = 256U;
// Get the Slide Id collection of the presentation document
var slideIdList = presentationPart.Presentation.SlideIdList;
if (slideIdList == null)
{
throw new NullReferenceException("The number of slide is empty, please select a ppt with a slide at least again");
}
slideId += Convert.ToUInt32(slideIdList.Count());
// Creates an Slide instance and adds its children.
Slide slide = new Slide(new CommonSlideData(new ShapeTree()));
SlidePart slidePart = presentationPart.AddNewPart<SlidePart>();
slide.Save(slidePart);
// Get SlideMasterPart and SlideLayoutPart from the existing Presentation Part
SlideMasterPart slideMasterPart = presentationPart.SlideMasterParts.First();
SlideLayoutPart slideLayoutPart = slideMasterPart.SlideLayoutParts.SingleOrDefault
(sl => sl.SlideLayout.CommonSlideData.Name.Value.Equals(layoutName, StringComparison.OrdinalIgnoreCase));
if (slideLayoutPart == null)
{
throw new Exception("The slide layout " + layoutName + " is not found");
}
slidePart.AddPart<SlideLayoutPart>(slideLayoutPart);
slidePart.Slide.CommonSlideData = (CommonSlideData)slideMasterPart.SlideLayoutParts.SingleOrDefault(
sl => sl.SlideLayout.CommonSlideData.Name.Value.Equals(layoutName)).SlideLayout.CommonSlideData.Clone();
// Create SlideId instance and Set property
SlideId newSlideId = presentationPart.Presentation.SlideIdList.AppendChild<SlideId>(new SlideId());
newSlideId.Id = slideId;
newSlideId.RelationshipId = presentationPart.GetIdOfPart(slidePart);
return GetSlideByRelationShipId(presentationPart, newSlideId.RelationshipId);
}
/// <summary>
/// Get Slide By RelationShip ID
/// </summary>
/// <param name="presentationPart">Presentation Part</param>
/// <param name="relationshipId">Relationship ID</param>
/// <returns>Slide Object</returns>
private static Slide GetSlideByRelationShipId(PresentationPart presentationPart, StringValue relationshipId)
{
// Get Slide object by Relationship ID
SlidePart slidePart = presentationPart.GetPartById(relationshipId) as SlidePart;
if (slidePart != null)
{
return slidePart.Slide;
}
else
{
return null;
}
}
Public void InsertImageInLastSlide(Slide slide, string imagePath, string imageExt)
{
// Creates an Picture instance and adds its children.
P.Picture picture = new P.Picture();
string embedId = string.Empty;
embedId = "rId" + (slide.Elements().Count() + 915).ToString();
P.NonVisualPictureProperties nonVisualPictureProperties = new P.NonVisualPictureProperties(
new P.NonVisualDrawingProperties() { Id = (UInt32Value)4U, Name = "Picture 5" },
new P.NonVisualPictureDrawingProperties(new A.PictureLocks() { NoChangeAspect = true }),
new ApplicationNonVisualDrawingProperties());
P.BlipFill blipFill = new P.BlipFill();
Blip blip = new Blip() { Embed = embedId };
// Creates an BlipExtensionList instance and adds its children
BlipExtensionList blipExtensionList = new BlipExtensionList();
BlipExtension blipExtension = new BlipExtension() { Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}" };
UseLocalDpi useLocalDpi = new UseLocalDpi() { Val = false };
useLocalDpi.AddNamespaceDeclaration("a14",
"http://schemas.microsoft.com/office/drawing/2010/main");
blipExtension.Append(useLocalDpi);
blipExtensionList.Append(blipExtension);
blip.Append(blipExtensionList);
Stretch stretch = new Stretch();
FillRectangle fillRectangle = new FillRectangle();
stretch.Append(fillRectangle);
blipFill.Append(blip);
blipFill.Append(stretch);
// Creates an ShapeProperties instance and adds its children.
P.ShapeProperties shapeProperties = new P.ShapeProperties();
A.Transform2D transform2D = new A.Transform2D();
A.Offset offset = new A.Offset() { X = 457200L, Y = 1524000L };
A.Extents extents = new A.Extents() { Cx = 8229600L, Cy = 5029200L };
transform2D.Append(offset);
transform2D.Append(extents);
A.PresetGeometry presetGeometry = new A.PresetGeometry() { Preset = A.ShapeTypeValues.Rectangle };
A.AdjustValueList adjustValueList = new A.AdjustValueList();
presetGeometry.Append(adjustValueList);
shapeProperties.Append(transform2D);
shapeProperties.Append(presetGeometry);
picture.Append(nonVisualPictureProperties);
picture.Append(blipFill);
picture.Append(shapeProperties);
slide.CommonSlideData.ShapeTree.AppendChild(picture);
// Generates content of imagePart.
ImagePart imagePart = slide.SlidePart.AddNewPart<ImagePart>(imageExt, embedId);
FileStream fileStream = new FileStream(imagePath, FileMode.Open);
imagePart.FeedData(fileStream);
fileStream.Close();
}
Source Code

Add table to powerpoint slide using Open XML

I got the code for the Table in the powerpoint using the code generator, but I am not able to add the table to an existing powerpoint document.
I tried adding another table to the intended slide and doing the following:
Table table = slidePart.Slide.Descendants<Table>().First();
table.RemoveAllChildren();
Table createdTable = CreateTable();
foreach (OpenXmlElement childElement in createdTable.ChildElements)
{
table.AppendChild(childElement.CloneNode(true));
}
But that didn't work.
I am out of ideas on this issue.
My original target is to add a table with dynamic number of columns and fixed number of row to my presentation.
I know its been very long since this question is posted, but just in case if some one needs a working code to create table in pptx.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using A = DocumentFormat.OpenXml.Drawing;
using System.IO;
namespace ANF.Slides.TestEngine
{
class Program
{
static int index = 1;
static void Main(string[] args)
{
Console.WriteLine("Preparing Presentation");
PopulateData();
// GeneratedClass cls=new GeneratedClass();
//cls.CreatePackage(#"E:\output.pptx");
Console.WriteLine("Completed Presentation");
Console.ReadLine();
}
private static void PopulateData()
{
var overflow = false;
const int pageBorder = 3000000;
var db = new AdventureWorksEntities();
var products = db.Products;//.Take(5);
const string outputFile = #"E:\openxml\output.pptx";
File.Copy(#"E:\OpenXml\Template.pptx", outputFile, true);
using (var myPres = PresentationDocument.Open(outputFile, true))
{
var presPart = myPres.PresentationPart;
var slideIdList = presPart.Presentation.SlideIdList;
var list = slideIdList.ChildElements
.Cast<SlideId>()
.Select(x => presPart.GetPartById(x.RelationshipId))
.Cast<SlidePart>();
var tableSlidePart = (SlidePart)list.Last();
var current = tableSlidePart;
long totalHeight = 0;
foreach (var product in products)
{
if (overflow)
{
var newTablePart = CloneSlidePart(presPart, tableSlidePart);
current = newTablePart;
overflow = false;
totalHeight = 0;
}
var tbl = current.Slide.Descendants<A.Table>().First();
var tr = new A.TableRow();
tr.Height = 200000;
tr.Append(CreateTextCell(product.Name));
tr.Append(CreateTextCell(product.ProductNumber));
tr.Append(CreateTextCell(product.Size));
tr.Append(CreateTextCell(String.Format("{0:00}", product.ListPrice)));
tr.Append(CreateTextCell(product.SellStartDate.ToShortDateString()));
tbl.Append(tr);
totalHeight += tr.Height;
if (totalHeight > pageBorder)
overflow = true;
}
}
}
static SlidePart CloneSlidePart(PresentationPart presentationPart, SlidePart slideTemplate)
{
//Create a new slide part in the presentation
SlidePart newSlidePart = presentationPart.AddNewPart<SlidePart>("newSlide" + index);
index++;
//Add the slide template content into the new slide
newSlidePart.FeedData(slideTemplate.GetStream(FileMode.Open));
//make sure the new slide references the proper slide layout
newSlidePart.AddPart(slideTemplate.SlideLayoutPart);
//Get the list of slide ids
SlideIdList slideIdList = presentationPart.Presentation.SlideIdList;
//Figure out where to add the next slide (find max slide)
uint maxSlideId = 1;
SlideId prevSlideId = null;
foreach (SlideId slideId in slideIdList.ChildElements)
{
if (slideId.Id > maxSlideId)
{
maxSlideId = slideId.Id;
prevSlideId = slideId;
}
}
maxSlideId++;
//Add new slide at the end of the deck
SlideId newSlideId = slideIdList.InsertAfter(new SlideId(), prevSlideId);
//Make sure id and relid is set appropriately
newSlideId.Id = maxSlideId;
newSlideId.RelationshipId = presentationPart.GetIdOfPart(newSlidePart);
return newSlidePart;
}
private static A.TableCell CreateTextCell(string text)
{
var textCol = new string[2];
if (!string.IsNullOrEmpty(text))
{
if (text.Length > 25)
{
textCol[0] = text.Substring(0, 25);
textCol[1] = text.Substring(26);
}
else
{
textCol[0] = text;
}
}
else
{
textCol[0] = string.Empty;
}
A.TableCell tableCell3 = new A.TableCell();
A.TextBody textBody3 = new A.TextBody();
A.BodyProperties bodyProperties3 = new A.BodyProperties();
A.ListStyle listStyle3 = new A.ListStyle();
textBody3.Append(bodyProperties3);
textBody3.Append(listStyle3);
var nonNull = textCol.Where(t => !string.IsNullOrEmpty(t)).ToList();
foreach (var textVal in nonNull)
{
//if (!string.IsNullOrEmpty(textVal))
//{
A.Paragraph paragraph3 = new A.Paragraph();
A.Run run2 = new A.Run();
A.RunProperties runProperties2 = new A.RunProperties() { Language = "en-US", Dirty = false, SmartTagClean = false };
A.Text text2 = new A.Text();
text2.Text = textVal;
run2.Append(runProperties2);
run2.Append(text2);
paragraph3.Append(run2);
textBody3.Append(paragraph3);
//}
}
A.TableCellProperties tableCellProperties3 = new A.TableCellProperties();
tableCell3.Append(textBody3);
tableCell3.Append(tableCellProperties3);
//var tc = new A.TableCell(
// new A.TextBody(
// new A.BodyProperties(),
// new A.Paragraph(
// new A.Run(
// new A.Text(text)))),
// new A.TableCellProperties());
//return tc;
return tableCell3;
}
}
}

Resources