I have a question regarding event handlers (Register-ObjectEvent). Here's my code:
Import-Module "$PSScriptRoot\Lib\Ookii.Dialogs.Winforms.dll"
$OKButton = [Ookii.Dialogs.WinForms.TaskDialogButton]("Ok")
$NOButton = [Ookii.Dialogs.WinForms.TaskDialogButton]("No")
$CancelButton = [Ookii.Dialogs.WinForms.TaskDialogButton]("Cancel")
$HelpButton = [Ookii.Dialogs.WinForms.TaskDialogButton]("Help")
$OokieTaskDialog = New-Object Ookii.Dialogs.WinForms.TaskDialog
$OokieTaskDialog.Buttons.Add($OKButton)
$OokieTaskDialog.Buttons.Add($NOButton)
$OokieTaskDialog.Buttons.Add($CancelButton)
$OokieTaskDialog.Buttons.Add($HelpButton)
$OokieTaskDialog.MainInstruction = "Main Instruction"
$OokieTaskDialog.Content = "Eiusmod cupidatat amet officia ut cillum anim proident. Aliqua aliqua ullamco reprehenderit velit est eiusmod et aute."
$OokieTaskDialog.ExpandedInformation = "Wozarlov, Marvin Houston, (870) 487-7980"
$OokieTaskDialog.Footer = "This is the footer text More Info"
$OokieTaskDialog.FooterIcon = [Ookii.Dialogs.WinForms.TaskDialogIcon]::Information
$OokieTaskDialog.EnableHyperlinks = $true
Register-ObjectEvent -InputObject $OokieTaskDialog -EventName HyperlinkClicked -Action { Write-Host "Link Clicked" }
$OokieTaskDialog.WindowTitle = "Window Title"
$OokieTaskDialog.Width = 300
$OokieTaskDialog.AllowDialogCancellation = $true
$OokieTaskDialog.MainIcon = [Ookii.Dialogs.WinForms.TaskDialogIcon]::Warning
$Result = $OokieTaskDialog.ShowDialog((New-Object System.Windows.Forms.Form -Property #{TopMost = $true}))
$Result
Specifically: Register-ObjectEvent -InputObject $OokieTaskDialog -EventName HyperlinkClicked -Action { Write-Host "Link Clicked" }
The event handler works, but it only displays the results ("Link Clicked") AFTER the dialog has closed. How do I get an event handler to respond immediately when the trigger conditions have been met?
For instance, if I click the hyperlink in the footer 10 times, and then click the OK button, the console prints "Link Clicked" 10 times.
I want to print "Link Clicked" immediately when the hyperlink is clicked.
How can I register an event that fires immediately? What am I doing wrong?
ShowDialog run on the same thread than the listener created through Register-ObjectEvent. It won't process anything until the dialog is closed.
To have a script block directly handle a .NET event, call the object's Add-Event() method.
$OokieTaskDialog.Add_HyperlinkClicked({ Write-Host "Link Clicked" })
Additional references:
This mklement0 excellent answer: How to add an Event Action handler in Powershell
Excerpt
C# offers syntactic sugar in the form of operators += and -= for
attaching and detaching event-handler delegates, which look like
assignments, but are in reality translated to add_() and
remove_() method calls.
PowerShell offers no such syntactic sugar for attaching/removing event
handlers, so the methods must be called directly.
This very complete answer by iRon: Powershell: Job Event Action with Form not executed
Excerpt:
Even if there are
multiple threads setup, there are two different 'listeners' in one
thread. When your script is ready to receive form events (using
ShowDialog or DoEvents) it can’t listen to .NET events at the same
time. And visa versa
Both of these answers provide a lot more insights and references links themselves.
I am new to SAP UI5.
Here my task is to convert javascript code to xml view. Here javascript is like:
var sHtmlText = '<strong>Aliquam erat volutpat.</strong><br>Vivamus vitae felis nec lacus ultricies dapibus condimentum quis felis.';
sHtmlText += 'Some link goes here:<embed data-index=\"0\">';
var oLink2 = new sap.ui.commons.Link("l2", {
text : "Click me",
href : "http://scn.sap.com/welcome",
title : "SAP Community Network",
target : "_blank"
});
var oFTV2 = new sap.ui.commons.FormattedTextView("otv2");
//set the text with placeholders inside
oFTV2.setHtmlText(sHtmlText);
//add the desired control to the FormattedTextView
oFTV2.addControl(oLink2);
var oCallout = new sap.ui.commons.Callout({
content : oFTV2
});
// create a sample form with two fields and assign a callout to each of them
var oLayout = new sap.ui.commons.layout.MatrixLayout({
layoutFixed : false
});
var oTextField, oLabel;
oLayout.createRow(
oLabel = new sap.ui.commons.Label({text:"First name:", labelFor:"firstname1"}),
oTextField = new sap.ui.commons.TextField("firstname1", {required:true, value:"John"})
);
oTextField.setTooltip(oCallout);
// display it
oLayout.placeAt("sample2");
While running the above code i am getting the text field with a label and input hover popup.
Now my task is to convert the above js view to XML View. I am getting confused.
Please suggest me the exact procedure (generalized manner) for converting the above JS view to XML view.
A quick (and dirty) way is to simply run your application, and when in the view you want to convert to XML, open the SAPUI5 Diagnostics screen (Ctrl-Alt-Shift S), show the Control Tree panel, select the topmost UIArea element, click the 'Export' tab on the right and click the 'Export to XML' button :)
First you need to add name space for your sap.ui.Commons xmlns:com="sap.ui.Commons" in your xml view
then write code like this
for more reference please check xml view developer guide
and example here Example
click on Expample in Master side then select on Detail Side and do show code
I write my own Eclipse-Plugin and get an errorlog from a server.
This log includes linenumbers. I want to mark this lines with another backround color if you click on the Error in my View. My Problem i can only mark text in my editor with CHAR_START and CHAR_END but i dont know how many characters are in each line. The line number is totally ignorer And how can i delete this markers in my code? In my example the first 10 characters are marked irrespective of the line I set
IEditorPart editorPart = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage()
.getActiveEditor();
if (editorPart != null) {
FileEditorInput input = (FileEditorInput) editorPart
.getEditorInput();
IFile file = input.getFile();
IMarker marker = null;
try {
marker = file.createMarker("de.fhduesseldorf.medien.mi.codecheck.marker");
marker.setAttribute(IMarker.LINE_NUMBER, 4);
marker.setAttribute(IMarker.CHAR_START, 0);
marker.setAttribute(IMarker.CHAR_END, 10);
} catch (CoreException e) {
e.printStackTrace();
}
}
You have to get the text content being edited and manually count characters (including new line chars) in each line until you get to the line in question. That's the only way to determine the character offsets of a given line or lines.
I would like to open an existing pdf, add some text and then output as content disposition using itext sharp. I have the following code. Where it falls down it is that i want to output as memory stream but need to filestream to open the original file.
Here's what i have. Obviously defining PdfWriter twice won't work.
public static void Create(string path)
{
var Response = HttpContext.Current.Response;
Response.Clear();
Response.ContentType = "application/pdf";
System.IO.MemoryStream m = new System.IO.MemoryStream();
Document document = new Document();
PdfWriter wri = PdfWriter.GetInstance(document, new FileStream(path, FileMode.Create));
PdfWriter.GetInstance(document, m);
document.Open();
document.Add(new Paragraph(DateTime.Now.ToString()));
document.NewPage();
document.Add(new Paragraph("Hello World"));
document.Close();
Response.OutputStream.Write(m.GetBuffer(), 0, m.GetBuffer().Length);
Response.OutputStream.Flush();
Response.OutputStream.Close();
Response.End();
}
You've got a couple of problems that I'll try to walk you through.
First, the Document object is only for working with new PDFs, not modifying existing ones. Basically the Document object is a bunch of wrapper classes that abstract away the underlying parts of the PDF spec and allow you to work with higher level things like paragraphs and reflowable content. These abstractions turn what you think of "paragraphs" into raw commands that write the paragraph one line at a time with no relationship between lines. When working with an existing document there's no safe way to say how to reflow text so these abstractions aren't used.
Instead you want to use the PdfStamper object. When working with this object you have two choices for how to work with potentially overlapping content, either your new text gets written on top of existing content or your text gets written below it. The two methods GetOverContent() or GetUnderContent() of an instantiated PdfStamper object will return a PdfContentByte object that you can then write text with.
There's two main ways to write text, either manually or through a ColumnText object. If you've done HTML you can think of the ColumnText object as using a big fixed-position single row, single column <TABLE>. The advantage of the ColumnText is that you can use the higher level abstractions such as Paragraph.
Below is a full working C# 2010 WinForms app targeting iTextSharp 5.1.2.0 that show off the above. See the code comments for any questions. It should be pretty easy to convert this to ASP.Net.
using System;
using System.IO;
using System.Windows.Forms;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
string existingFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file1.pdf");
string newFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file2.pdf");
using (FileStream fs = new FileStream(existingFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (Document doc = new Document(PageSize.LETTER)) {
using (PdfWriter writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
doc.Add(new Paragraph("This is a test"));
doc.Close();
}
}
}
//Bind a PdfReader to our first document
PdfReader reader = new PdfReader(existingFile);
//Create a new stream for our output file (this could be a MemoryStream, too)
using (FileStream fs = new FileStream(newFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
//Use a PdfStamper to bind our source file with our output file
using (PdfStamper stamper = new PdfStamper(reader, fs)) {
//In case of conflict we want our new text to be written "on top" of any existing content
//Get the "Over" state for page 1
PdfContentByte cb = stamper.GetOverContent(1);
//Begin text command
cb.BeginText();
//Set the font information
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1250, false), 16f);
//Position the cursor for drawing
cb.MoveText(50, 50);
//Write some text
cb.ShowText("This was added manually");
//End text command
cb.EndText();
//Create a new ColumnText object to write to
ColumnText ct = new ColumnText(cb);
//Create a single column who's lower left corner is at 100x100 and upper right is at 500x200
ct.SetSimpleColumn(100,100,500,200);
//Add a higher level object
ct.AddElement(new Paragraph("This was added using ColumnText"));
//Flush the text buffer
ct.Go();
}
}
this.Close();
}
}
}
As to your second problem about the FileStream vs MemoryStream, if you look at the method signature for almost every (actually all as far as I know) method within iTextSharp you'll see that they all take a Stream object and not just a FileStream object. Any time you see this, even outside of iTextSharp, this means that you can pass in any subclass of Stream which includes the MemoryStream object, everything else stays the same.
The code below is a slightly modified version of the one above. I've removed most of the comments to make it shorter. The main change is that we're using a MemoryStream instead of a FileStream. Also, when we're done with the PDF when need to close the PdfStamper object before accessing the raw binary data. (The using statment will do this for us automatically later but it also closes the stream so we need to manually do it here.)
One other thing, never, ever use the GetBuffer() method of the MemoryStream. It sounds like what you want (and I have mistakenly used it, too) but instead you want to use ToArray(). GetBuffer() includes uninitialized bytes which usually produces corrupt PDFs. Also, instead of writing to the HTTP Response stream I'm saving the bytes to array first. From a debugging perspective this allows me to finish all of my iTextSharp and System.IO code and make sure that it is correct, then do whatever I want with the raw byte array. In my case I don't have a web server handy so I'm writing them to disk but you could just as easily call Response.BinaryWrite(bytes)
string existingFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file1.pdf");
string newFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file2.pdf");
PdfReader reader = new PdfReader(existingFile);
byte[] bytes;
using(MemoryStream ms = new MemoryStream()){
using (PdfStamper stamper = new PdfStamper(reader, ms)) {
PdfContentByte cb = stamper.GetOverContent(1);
ColumnText ct = new ColumnText(cb);
ct.SetSimpleColumn(100,100,500,200);
ct.AddElement(new Paragraph("This was added using ColumnText"));
ct.Go();
//Flush the PdfStamper's buffer
stamper.Close();
//Get the raw bytes of the PDF
bytes = ms.ToArray();
}
}
//Do whatever you want with the bytes
//Below I'm writing them to disk but you could also write them to the output buffer, too
using (FileStream fs = new FileStream(newFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
fs.Write(bytes, 0, bytes.Length);
}
The second part of your question title says:
"outputting as content disposition"
If that's what you really want you can do this:
Response.AddHeader("Content-Disposition", "attachment; filename=DESIRED-FILENAME.pdf");
Using a MemoryStream is unnecessary, since Response.OutputStream is available. Your example code is calling NewPage() and not trying to add the text to an existing page of your PDF, so here's one way to do what you asked:
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=itextTest.pdf");
PdfReader reader = new PdfReader(readerPath);
// store the extra text on the last (new) page
ColumnText ct = new ColumnText(null);
ct.AddElement(new Paragraph("Text on a new page"));
int numberOfPages = reader.NumberOfPages;
int newPage = numberOfPages + 1;
// get all pages from PDF "template" so we can copy them below
reader.SelectPages(string.Format("1-{0}", numberOfPages));
float marginOffset = 36f;
/*
* we use the selected pages above with a PdfStamper to copy the original.
* and no we don't need a MemoryStream...
*/
using (PdfStamper stamper = new PdfStamper(reader, Response.OutputStream)) {
// use the same page size as the __last__ template page
Rectangle rectangle = reader.GetPageSize(numberOfPages);
// add a new __blank__ page
stamper.InsertPage(newPage, rectangle);
// allows us to write content to the (new/added) page
ct.Canvas = stamper.GetOverContent(newPage);
// add text at an __absolute__ position
ct.SetSimpleColumn(
marginOffset, marginOffset,
rectangle.Right - marginOffset, rectangle.Top - marginOffset
);
ct.Go();
}
I think you've already figured out that the Document / PdfWriter combination doesn't work in this situation :) That's the standard method for creating a new PDF document.
Sorry for the earlier lengthy post. Here is my concise (!) description.
I bind a collection view to a combobox as a itemsSource and also bind its selectedvalue with a property from my view model. I must keep IsSynchronizedWithCurrentItem="False".
I change the source list ofr the view and then refresh the view. The changed (added, removed, edited) items appear correctly in the item list of the combo. But problem is with the selected item. When I change its property which is also the displaymember path of the combo, the changed property value does not reflect back on the selecton box of the combo. If you open the combo dropdown it appears correctly on the item list but not on the selection box.
Now if I change the combobox tag to Listbox in my XAML (keeping all attributes as it is) then when selected item's displaymember property value is updated, the changes reflect back on the selected item of the list box .
Why this issue?
Just FYI:
My View Model has properties EmployeeCollectionView and SelectedEmployeeId which are bound to combo as ItemsSource and SelectedValue resp. This VM implements the INotifyPropertyChanged interface.
My core employee class (list of which is the source for the EmployeeCollectionView) is simply a Model class without INotifyPropertyChanged.
DisplayMemberPath is "Name" property of employee Model class. I change this by some means and expect the combo selection box to update the value.
I tried refreshing ther SelectedEmployeeId by setting it 0 (where it correctly selects the dummy "-- Select All --" employee entry from itemsSource) and old selected value back. But no use. The old value takes me back to the old label. Items collection has latest entry though.
When I make combobox's IsEditable=True before the view's refresh and after refresh I make IsEditable=False then the things work out correctly!
But this is a patch and is unnecessary.
Thx
Vinit Sankhe
Your points #2 and #3 are why this isn't working. When the ComboBox has an item selected, it displays in the box the Employee.Name property. You state in #2 that Employee does not implement INotifyPropertyChanged and in #3 you are changing Name and expecting it to update in the ComboBox. But the ComboBox has no idea that the property changed so its displayed value will not change.
I've put together a very simple example that will demonstrate. If you comment out the PropertyChanged event you'll notice that clicking the button no longer has an effect on the UI.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight">
<StackPanel>
<ComboBox ItemsSource="{Binding}" DisplayMemberPath="Name" SelectedIndex="0" Width="150" Height="25" />
<Button Content="Change" Width="75" Height="25" Click="button_Click"/>
</StackPanel>
</Window>
And the code behind...
public partial class MainWindow : Window
{
private ObservableCollection<Thing> things;
private Queue<string> words;
public MainWindow()
{
// some dummy data
string text = "Lorem ipsum dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat sed diam voluptua";
words = new Queue<string>(text.Split(' '));
things = new ObservableCollection<Thing>();
things.Add(new Thing { Name = words.Dequeue() });
things.Add(new Thing { Name = words.Dequeue() });
things.Add(new Thing { Name = words.Dequeue() });
DataContext = things;
InitializeComponent();
}
private void button_Click(object sender, System.Windows.RoutedEventArgs e)
{
things[0].Name = words.Dequeue();
}
}