У меня есть панель, заполненная множеством элементов управления для пользователей.К ним относятся текстовые поля, флажки, радиокнопки и т. Д. Это длинная форма для заполнения, поэтому элементы управления находятся на прокручиваемой панели.Что мне нужно, это сохранить всю панель в формате PDF.Я думаю, что PDFsharp - хорошая библиотека, позволяющая сохранять любой текст или изображение в виде файла PDF, но я не хочу писать код для каждого элемента управления внутри панели.Однажды я написал класс для создания PDF-файла из объекта Control.Он перебирает все внутренние элементы управления (и их внутренние элементы управления до тех пор, пока не останется никакого внутреннего элемента управления) данного элемента управления и записывает их свойство Text (да / нет для проверяемых элементов управления) в pdf, используя их свойства Location и Size.Я не мог найти его сейчас, но помню, что у него были проблемы с некоторыми элементами управления DevExpress, которые я использую, поэтому я не стал писать его снова. (Редактировать: мне пришлось, вы можете найти его ниже.) Я думаю, было бы неплохо сделать снимок экрана и сохранить это изображение в формате pdf, но я не мог найти, как этого добиться. Этот вопрос кажется, но ответа на этот вопрос нет удовлетворительного.
Итак, скриншот или нет, я открыт для любых советов.Там должно быть много случаев, когда пользователи должны заполнять длинные формы и иметь возможность сохранить его в формате PDF.Опять же, любые советы или обходные пути будут оценены.(Я думаю о создании формы с использованием html, отображении ее в элементе управления WebBrowser и использовании html to pdf библиотеки, но я действительно предпочитаю использовать мою существующую форму)
Большое спасибо.
Редактировать: Мне пришлось написать что-то итерирующее внутренние элементы управления контейнерного элемента управления (например, панели) и записать каждый внутренний элемент управления в pdf, используя их свойства Location, Size и Font, хотя я не рекомендую использоватьэто (по крайней мере, как есть) из-за них:
- Он устанавливает размер страницы в соответствии с размером элемента управления и использует только одну (обычно огромную) страницу PDF.Вы можете добавить логику, чтобы разделить ее на страницы, если вам нужно.(Я этого не сделал, но, думаю, вам, вероятно, понадобится ваш PDF-файл, более дружественный к принтеру).
- Метод Cheeso (использующий FlowDocument) является гораздо более «законным» способом для такой задачи, как эта.Я предпочитаю использовать это, но у меня не было выбора в этом случае.
Я использовал PDFsharp в этом коде.Вы можете найти его в это hompage или это страница CodePlex .
PdfReport class:
private PdfDocument Document;
public Control Control { get; private set; }
public PdfReport(Control control) { Control = control; }
public PdfDocument CreatePdf(PdfDocument document = null)
{
Document = document != null ? document : new PdfDocument();
PdfPage page = Document.AddPage();
page.Height = Control.Height;
page.Width = Control.Width;
XGraphics gfx = XGraphics.FromPdfPage(page);
foreach (PdfItem item in CreatePdf(new Point(0, 0), Control.Controls))
{
XStringFormat format = item.IsContainer ? XStringFormats.TopLeft : item.TextAlign == ContentAlignment.BottomCenter ? XStringFormats.BottomCenter : item.TextAlign == ContentAlignment.TopLeft ? XStringFormats.TopLeft : item.TextAlign == ContentAlignment.TopCenter ? XStringFormats.TopCenter : XStringFormats.Center;
gfx.DrawString(item.Text, item.Font, item.Brush, new XRect(item.Location, item.Size), format);
}
return Document;
}
private IEnumerable<PdfItem> CreatePdf(Point location, Control.ControlCollection controls)
{
List<PdfItem> items = new List<PdfItem>();
foreach (Control control in controls)
{
if (control.Controls.Count > 0)
items.AddRange(CreatePdf(control.Location, control.Controls));
items.Add(new PdfItem(control, location));
}
return items;
}
public void SaveAsPdf(string path, bool open = false)
{
CreatePdf().Save(path);
if (open)
Process.Start(path);
}
PdfItem класс:
public string Text { get; set; }
public Point Location { get; set; }
public Size Size { get; set; }
public Font Font { get; set; }
public bool IsContainer { get; set; }
public ContentAlignment TextAlign { get; set; }
public Color ForeColor { get; set; }
public XBrush Brush { get { return new SolidBrush(ForeColor); } }
public PdfItem() { }
public PdfItem(string text, Point location, Font font, Color foreColor, Size size, bool isContainer = false, ContentAlignment alignment = ContentAlignment.MiddleCenter)
{
Text = text;
Location = location;
Size = size;
Font = new Font(font.FontFamily, font.Size, font.Style, GraphicsUnit.World);
TextAlign = alignment;
ForeColor = foreColor;
IsContainer = isContainer;
}
public PdfItem(string text, Point location, Size size)
: this(text, location, new Font("Calibri", 12), Color.Black, size) { }
public PdfItem(Control control, Point parentLocation)
: this(control.Text, control.Location, control.Font, control.ForeColor, control.Size, control.Controls.Count > 0)
{
Location = new Point(Location.X + parentLocation.X, Location.Y + parentLocation.Y);
IEnumerable<PropertyInfo> properties = control.GetType().GetProperties();
if (properties.FirstOrDefault(p => p.Name == "TextAlign" && p.PropertyType == typeof(ContentAlignment)) != null)
TextAlign = (control as dynamic).TextAlign;
if (properties.FirstOrDefault(p => p.Name == "Checked" && p.PropertyType == typeof(bool)) != null)
{
string title = control.Text != null && control.Text.Length > 0 ? string.Format("{0}: ", control.Text) : string.Empty;
Text = string.Format("{0}{1}", title, (control as dynamic).Checked ? "Yes" : "No");
}
}