itextsharp: detecting if text / images are not fitting on page - vb.net

i am generating a report in vb.net using itextsharp. sometimes the entire report does not fit on one page and i need to know when itextsharp is adding a page to the document. is there a way to detect this?

As long as you're implementing the PdfPageEvent interface, you just need to override the public void onEndPage(PdfWriter writer, Document document) method, which is called right before a new page is started.
Edit: here's some code explaining the procedure, without knowing what you want to do if a new page is created by iTextSharp, this is the most I can give you:
Public Class YourReport
Implements PdfPageEvent
'Your report code
Public Overrides Sub onEndPage(ByVal writer as PdfWriter,
ByVal doc as Document)
'if you get here, a new page was created by iTextSharp
'so do what you need to do.
End Sub
End Class

Related

How do I make a property of a custom control open a file dialog?

I have a custom control with a property that holds the name (full path) to a file location that exists on the target computer.
The exact path will vary according to type of target pc and is typically set right after I add the custom control to my Form, while I am still in design mode of my project, so that when my application runs, it picks up the filename from the property.
It would be convenient if the property opened a file dialog to let me browse to the location (similar to how dialogs are opened when browsing for image and color properties), but this doesn't seem to be possible in visual basic.
After googling for days I have found a couple of articles that touch the subject for other programming languages (see example snippet below) but I haven't been able to work out how to make it work for visual basic.
Here is a snippet I found that mentions the use of an editor, which may be a clue to get started.
[Editor(typeof(FileSelectorTypeEditor), typeof(UITypeEditor))]
public string Filename
{
get { return _filename; }
set { _filename = value; }
}
Hope someone out there can lead me in the right way.
FileSelectorTypeEditor is probably a custom class derived from either FileNameEditor or FolderNameEditor.
You can implement both, using the standard class or extend the default with your own, as you have seen in those C# sources you have found.
Here I'm using a specialized FileNameEditor class, named (with some lack of imagination) SpecializedFileNameEditor and the standard FolderNameEditor assigning the UITypeEditor to two properties of a class.
► The ImagePath property editor is the SpecializedFileNameEditor object, which uses an OpenFileDialog, where a filter is pre-selected. It also overrides the EditValue method, to set the current value, if any, of an associated property (here, ImagePath) as the InitialDirectory of the OpenFileDialog.
► The ImageFolder property editor is a standard FolderNameEditor, which opens a FolderBrowserDialog.
I'm also attaching an ExpandableObjectConverter type converter, so you can present the two properties as an expandable property selector in a PropertyGrid.
You can see an example here:
How to bind child Controls of a User Control to a Public Property
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.IO
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
<TypeConverter(GetType(ExpandableObjectConverter))>
Public Class ImagePickerClass
Public Sub New()
' Initialize [...]
End Sub
<Editor(GetType(SpecializedFileNameEditor), GetType(UITypeEditor))>
Public Property ImagePath As String
<Editor(GetType(FolderNameEditor), GetType(UITypeEditor))>
Public Property ImageFolder As String
Public Class SpecializedFileNameEditor
Inherits FileNameEditor
Private currentValue As String = String.Empty
Public Overrides Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As Object) As Object
If TypeOf value Is String Then
currentValue = DirectCast(value, String)
End If
Return MyBase.EditValue(context, provider, value)
End Function
Protected Overrides Sub InitializeDialog(ofd As OpenFileDialog)
MyBase.InitializeDialog(ofd)
If Not currentValue.Equals(String.Empty) Then
ofd.InitialDirectory = Path.GetDirectoryName(currentValue)
End If
ofd.Filter = "PNG Images (*.png)|*.png"
End Sub
End Class
End Class

Windows 10 Universal App VB.NET Passing data between pages

I have found that navigation between pages in VB.NET is called like this:
Frame.Navigate(GetType(MainPage))
and from what I have read, you can pass a parameter like this:
Frame.Navigate(GetType(MainPage), "Parameter Here!!")
The problem is, I cannot get it through to the other page. Finding many examples in C# I see it might be using one of the below methods. Although, none of these seem to be recognised in VS2015
Protected Overrides Sub LoadState(navigationParameter As Object, pageState As Dictionary(Of String, Object))
Protected Overrides Sub onNavigateTo(**Params**)
^^ They both state "...does not have an override a sub in a base class"
How to I receive the parameter in the newly presented page? is it a different method entirely?
After digging into the Page class which all pages inherit from It seems overriding the "onNavigateTo" Sub is key in this operation. From here you can access its argument and pass through successfully.
Unfortunaly, even Microsoft doesn't provide VB.NET Documentation for this. Here is my code:
In the First page
Frame.Navigate(GetType(BlankPage1), "Hello")
In the Second Page
Public NotInheritable Class BlankPage1
Inherits Page
Public thestring As String
Protected Overrides Sub onNavigatedTo(e As NavigationEventArgs)
thestring = e.Parameter
End Sub
This works successfully. I hope this helps people in the future

Why can my VB.NET User Control not instantiate an ObjectContext?

I have the following lines of code as a test user control. When the project is built, and I drag this user control onto a form, I get an error dialogue to the effect that EF can't find the connection string for the context. Yet when I use the same variable in a form, all is well. It seems the user control is using a different context within which to look for the connection string than the usual app.config.
Public Class InvoiceWorkOrderSearch
Private _dataHelper As WorkOrderData = New WorkOrderData()
End Class
During Design time?
You can avoid this be only instancing the object if the control is in runtime mode.
The build in property to check for desing time (Me.DesignMode) is poor since it only tells you if you are currently designing the control itself. It returs false if you drop the usercontrol on a form.
You can use this code to check for designtime: http://dotnet-snippets.de/dns/designmode-workaround-windows-forms-SID299.aspx
Public Class InvoiceWorkOrderSearch
Private _dataHelper As WorkOrderData
Public Sub New()
If IsDesignMode(me) = False Then
_dataHelper = New WorkOrderData()
End If
End Sub()
End Class

Turn private variable to public in runtime?

please see image attached.
i want it to be
Public components As System.ComponentModel.lContainer
but every time I edit the form design, it always change back to its original code
Private components As System.ComponentModel.lContainer
You can have a public Property in your class that returns a private member, like yours. This code is generated by form designer and probably you can not change the behavior of this. Even if you could, I wouldn't suggest you to do this.
Public Class MyForm
Public Property Container As System.ComponentModel.IContainer
Get
Return Me.components
End Get
End Property
End Class
Cheers

How to load a class into the current instance within Sub New

Long term lurker, first time poster here.
I have written a class to model an object in vb.net, using vs2008 and framework 2.0. I am serializing the class to an XML file for persistent storage. I do this with a method in the class like this:
Public Sub SaveAs(ByVal filename As String)
Dim writer As New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file As New System.IO.StreamWriter(filename)
writer.Serialize(file, Me)
file.Close()
End Sub
I now want to do a similar thing but reading the class from file to the current instance, like this:
Public Sub New(ByVal filename As String)
Dim reader = New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file = New System.IO.StreamReader(FullPath)
Me = CType(reader.Deserialize(file), MyNamespace.MyClass)
End Sub
However, I cannot assign anything to “Me”. I’ve tried creating a temporary object to hold the file contents then copying each property and field over to the current instance. I iterated over the properties (using Reflection), but this soon gets messy, dealing with ReadOnly collection properties, for example. If I just copy each property manually I will have to remember to modify the procedure whenever I add a property in the future, so that sounds like a recipe for disaster.
I know that I could just use a separate function outside the class but many built-in .NET classes can instantiate themselves from file e.g. Dim bmp As New Bitmap(filename As String) and this seems very intuitive to me.
So can anyone suggest how to load a class into the current instance in the Sub New procedure? Many thanks in advance for any advice.
I'd put a shared load function on the class, that returned the newly de-serialised object.
e.g.
Public Class MyClass
...
Public shared Function Load(ByVal filename As String) as MyClass
Dim reader = New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file = New System.IO.StreamReader(FullPath)
Return CType(reader.Deserialize(file), MyNamespace.MyClass)
End Sub
End Class
...
Dim mine as MyClass = MyClass.Load("MyObject.Xml");
Hope this helps
Alternatively,
Encapsulate the data of your class in an inner, private class.
The properties on your outer visible class delegate to the inner class.
Then Serialising and De-serialising happens on the inner class, you can then have a ctor that takes the file name, de-serialises the inner hidden object, and assigns it to the classes data store.
The "New" method in VB.Net is a constructor for the class. You can't call it for an existing instance, as the whole purpose of the method is to create new instances; it's just not how the language works. Try naming the method something like "ReadFrom" or "LoadFrom" instead.
Additionally, given those methods, I would try to implement them using a Factory Pattern. The ReadFrom method would be marked Shared and return the new instance. I would also make the method more generic. My main ReadFrom() method would accept an open textreader or xmlreader or even just a stream, rather than a file name. I would then have overloads that converts a file name into a stream for reading and calls the main method.
Of course, that assumes I use that pattern in the first place. .Net already has great support for xml serialization built into the platform. Look into the System.Xml.Serialization.XmlSerializer class and associated features.