mercoledì 27 maggio 2015
Avendo a disposizione l'URL di un servizio web specificato tramite WSDL è possibile generarne la classe proxy tramite il comando wsdl.exe.
Aprire (ipotizzando di avere VS2012) il menu seguente:
Programmi\Visual Studio 2012\Visual Studio Tools\Developer Command Prompt for VS2012
Dal prompt posizionarsi nella cartella in cui si vuole generare il file della classe proxy e digitare il comando:
> wsdl.exe /language:VB
Se si usa un url per il WSDL e c'è un proxy per l'accesso a internet, allora:
> wsdl.exe
/proxy: /pd: /pu: /pp: /language:VB
Esempio:
> wsdl.exe https://pteasb.actalis.it/ArubaSignService/ArubaSignService?WSDL /proxy:http://myServer.ACME.local:8080 /pd:ACME /pu:francescogeri /pp:myPassword123
venerdì 26 luglio 2013
Se si apre un form MDI child come maximized si ha un problema nella visualizzazione della sua icona.
Basta creare un progetto con una Form MDI container (IsMdiContainer=True), mettere un Menustrip ed inserire il seguente codice per l’apertura della form figlia Form2:
Private Sub NewToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewToolStripMenuItem.Click
Dim f As New Form2
f.MdiParent = Me
f.WindowState = FormWindowState.Maximized
f.Show()
End Sub
Il risultato sarà:
Anche se in realtà la form Form2 ha una sua icona, per cui il risultato doveva essere:
Per risolvere il problema ho trovato 2 modi (grazie alla stessa fonte):
Primo metodo
Giocare con il SuspendLayout del menustrip:
Private Sub NewToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewToolStripMenuItem.Click
Me.MenuStrip1.SuspendLayout()
Dim f As New Form2
f.MdiParent = Me
f.WindowState = FormWindowState.Maximized
f.Show()
Me.MenuStrip1.Visible = False
Me.MenuStrip1.Visible = True
Me.MenuStrip1.ResumeLayout()
End Sub
Secondo metodo
Inserire nella Load della form figlia la seguente riga di codice:
Me.Icon = New Icon(Me.Icon, Me.Icon.Size)
Per cui, nel mio esempio, avrei:
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Label1.Text = "Sono la form 2 creata alle " & Now.ToString
' Fix del problema icona form figlia
Me.Icon = New Icon(Me.Icon, Me.Icon.Size)
End Sub
giovedì 28 marzo 2013
When you need to process some Office file in your project you can use, for example, the Office automation mechanism. But it need to have Office installed on your machine.
Otherwise, for example, you can choose a third part library.
I think that you can find many libraries over the web, but, for my purposes, in some of the projects I worked on, I used Aspose libraries (home page http://www.aspose.com/).
With those libraries you can easily manipulate Office documents (Word, Excel, PowerPoint, Visio and Project!) without needing to have Office installed on your machine. You can open a navigate a document, or modify it or create a new document and fill it.
For example you can create a document with a table:
' We call this method to start building the table.
builder.StartTable()
builder.InsertCell()
builder.Write("Row 1, Cell 1 Content.")
' Call the following method to end the row and start a new row.
builder.EndRow()
' Signal that we have finished building the table.
builder.EndTable()
Following image is grabbed from Aspose site:
Aspose provides also libraries that allow you to manipulate PDF documents.
Like Office document, you can open, modify or create from the beginning a PDF document.
But you can also easily convert many documents types (Office, Html, Text, images) to the PDF format. The code to convert a document is very simple:
Dim doc As New Aspose.Words.Document(strIn)
doc.Save(strOut, Aspose.Words.SaveFormat.Pdf)
If needed, you can also converto to PDF/A. Other security features are available, like encrypt and decrypt PDF documents or sign it using PKCS#1, PKCS#7 and PKCS#7 detached signature types and with the use of digital certificate. No Adobe Acrobat Automation are required!
Aspose libraries are availables also for OCR and Barcodes.
For example, we worked on barcode recognition. Using Barcode libraries you can recognize barcodes from images or PDF, or writes them into the files. And both 1D and 2D barcodes types are supported (you can see all supported barcodes from this url: http://www.aspose.com/.net/barcode-component/key-features.aspx).
Following code allows you to reads barcodes on a jpg file:
Dim reader As BarCodeReader
reader = New BarCodeReader("C:\SamplePic\EAN13.jpg", BarCodeReadType.EAN13)
Do While reader.Read()
' get symbology type
Console.WriteLine("Symbology Type: " & reader.GetReadType().ToString())
' get code text
Console.WriteLine("CodeText: " & reader.GetCodeText())
Loop
reader.Close()
Other libraries are concerning SharePoint, Cloud and JasperReports.
All this componentes are very useful in many cases, and they are available for .NET and are built using managed code and can be installed and deployed as a single .NET assemblies. If you prefere, the libraries are available also for java, but this feature is off topic for us! :)
You can buy the single developer kit for your needs, or the full license (Aspose.Total).
You can get the OEM licence for unlimited royalty-free distribution, and I think this is a good solution.
The Aspose technical support is very good. You can count on a rich on line documentation with many code examples, dedicated forums with many posts and quick support responses!
venerdì 8 marzo 2013
Dovendo fare in una stessa applicazione molte form di dialogo per l’immissione o visualizzazione di informazioni ho pensato di creare una form base (scheletro) che fosse impostata con le caratteristiche comuni (font, colore di sfodo) e con i pulsanti ok, applica, annulla. A questo punto tutte le form di dialogo ereditano da questa (invece che da System.Windows.Form.Form) e così si trovano automaticamente i pulsanti e tutto il resto.
Per posizionare i pulsanti ho pensato di usare un TableLayoutPanel in modo che ridimensionando le form ereditate i pulsanti si spostino nel punto giusto.
Però mi sono accorto che, in Visual Studio, dal Form editor il controllo TableLayoutPanel ed i suoi children risultano in sola lettura. Sostituendo il TableLayoutPanel con un Panel posso invece editare i controlli in esso contenuti.
Il problema è che, per poter essere editati nel Form editor, i controlli ereditati devono supportare la Visual Inheritance, ed il TableLayoutPanel non la supporta.
La cosa è documentata in questa pagina: Best Practices for the TableLayoutPanel Control.
Ci sono altri controlli che hanno lo stesso problema, come indicato nell’articolo Walkthrough: Demonstrating Visual Inheritance. In particolare sono:
WebBrowser
ToolStrip
ToolStripPanel
TableLayoutPanel
FlowLayoutPanel
DataGridView
venerdì 1 marzo 2013
Quando una Form MDI contiene delle form figlie aperte in modalità Maximized si uno sfarfallio al cambio delle finestra attiva.
Ciò succede quando si attiva la finestra da codice. Per evitare questo fastidioso comportamento si può come al solito ricorrere alle API Windows.
A tal proposito ho preparato un modulo MDIUtil che crea un Extension method per aggiungere alla form MDIParent il metodo MyActivateMdiChild con cui si può richiedere di attivare una form child evitando il flickering.
Il codice del modulo è il seguente:
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Module MDIUtil
#Region " MDI Activate Child "
<System.Security.SuppressUnmanagedCodeSecurity>
<System.Runtime.InteropServices.DllImport("user32.dll", CharSet:=System.Runtime.InteropServices.CharSet.Auto)>
Public Function SendMessage(hWnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
Public Const WM_MDINEXT As Integer = &H224
''' <summary>
''' Attiva la form MDI child specificata eviatando i problemi di flicker/flashing
''' che si avrebbero usando semplicemente il metodo <see cref="Form.Activate">Activate</see>.
''' Vedi post http://www.codeproject.com/Articles/19524/Workaround-for-flicker-flashing-when-programmatica
''' </summary>
''' <param name="form">Form MDI partent</param>
''' <param name="childToActivate">Form MDI child da attivre</param>
<System.Runtime.CompilerServices.Extension>
Public Sub MyActivateMdiChild(form As Form, childToActivate As Form)
If Not childToActivate Is form.ActiveMdiChild Then
Dim mdiClient As MdiClient = GetMDIClient(form)
If mdiClient Is Nothing Then Return
Dim count As Integer = form.MdiChildren.Length
Dim childForm As Control = Nothing
' next or previous MDIChild form
Dim pos As Integer = mdiClient.Controls.IndexOf(childToActivate)
If pos < 0 Then Return 'Throw New InvalidOperationException("MDIChild form not found")
If mdiClient.Controls.Count <= 1 Then
' C'è un solo child, quindi attiva quello in modo classico
childToActivate.Focus()
Return
End If
If pos = 0 Then
childForm = mdiClient.Controls(1)
Else
' get next and activate previous
childForm = mdiClient.Controls(pos - 1)
End If
' get previous and activate next
' flag indicating whether to activate previous or next MDIChild
Dim direction As New IntPtr(If(pos = 0, 1, 0))
' bada bing, bada boom
SendMessage(mdiClient.Handle, WM_MDINEXT, childForm.Handle, direction)
End If
End Sub
Public Function GetMDIClient(form As Form) As MdiClient
For Each c As Control In form.Controls
If TypeOf c Is MdiClient Then
Return DirectCast(c, MdiClient)
End If
Next
Return Nothing 'Throw New InvalidOperationException("No MDIClient")
End Function
#End Region
End Module
A questo punto nella form parent MDI si deve importare il modulo e usare il metodo MyActivateMdiChild al posto di child.Activate() (o Focus()):
Imports itConsult.josh.joshDesigner.MDIUtil
...
Dim child As Form = getTheFormToActivate()
' La seguente istruzione sostisuice l'istruzione: child.Activate()
Me.MyActivateMdiChild(child)
Nei commenti del codice del modulo è indicata anche la fonte da cui ho liberamente preso quel codice, ovvero questo post.
Una Form MDI di default ha un bordo interno (che credo sia di tipo sunken), ovvero del tipo:
Per rimuoverlo si può ricorrere alle API windows.
A tal proposito ho preparato un modulo MDIUtil che crea un Extension method per aggiungere alla form MDIParent il metodo SetBevel con cui si può richiedere di mostrare o non mostrare il bordo.
Il codice del modulo è il seguente:
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Module MDIUtil
#Region " Bordo interno (sunken) "
<DllImport("user32.dll")> _
Private Function GetWindowLong(hWnd As IntPtr, nIndex As Integer) As Integer
End Function
<DllImport("user32.dll")> _
Private Function SetWindowLong(hWnd As IntPtr, nIndex As Integer, dwNewLong As Integer) As Integer
End Function
<DllImport("user32.dll", ExactSpelling:=True)> _
Private Function SetWindowPos(hWnd As IntPtr, hWndInsertAfter As IntPtr, X As Integer, Y As Integer, cx As Integer, cy As Integer, _
uFlags As UInteger) As Integer
End Function
Private Const GWL_EXSTYLE As Integer = -20
Private Const WS_EX_CLIENTEDGE As Integer = &H200
Private Const SWP_NOSIZE As UInteger = &H1
Private Const SWP_NOMOVE As UInteger = &H2
Private Const SWP_NOZORDER As UInteger = &H4
Private Const SWP_NOREDRAW As UInteger = &H8
Private Const SWP_NOACTIVATE As UInteger = &H10
Private Const SWP_FRAMECHANGED As UInteger = &H20
Private Const SWP_SHOWWINDOW As UInteger = &H40
Private Const SWP_HIDEWINDOW As UInteger = &H80
Private Const SWP_NOCOPYBITS As UInteger = &H100
Private Const SWP_NOOWNERZORDER As UInteger = &H200
Private Const SWP_NOSENDCHANGING As UInteger = &H400
''' <summary>
''' Consente di rimuovere il bordo 3D interno della form MDI (sunken).
''' Vedi post: http://stackoverflow.com/questions/7752696/how-to-remove-3d-border-sunken-from-mdiclient-component-in-mdi-parent-form
''' Oppure articolo: http://www.codeproject.com/Articles/8489/Getting-a-quot-Handle-quot-on-the-MDI-Client#Changing%20the%20Border%20Styles:
''' </summary>
''' <param name="form"></param>
''' <param name="show">False per rimuovere il sunken (3D interno), True per mostrarlo</param>
''' <returns></returns>
<System.Runtime.CompilerServices.Extension>
Public Function SetBevel(form As Form, show As Boolean) As Boolean
For Each c As Control In form.Controls
Dim client As MdiClient = TryCast(c, MdiClient)
If client IsNot Nothing Then
Dim windowLong As Integer = GetWindowLong(c.Handle, GWL_EXSTYLE)
If show Then
windowLong = windowLong Or WS_EX_CLIENTEDGE
Else
windowLong = windowLong And Not WS_EX_CLIENTEDGE
End If
SetWindowLong(c.Handle, GWL_EXSTYLE, windowLong)
' Update the non-client area.
SetWindowPos(client.Handle, IntPtr.Zero, 0, 0, 0, 0, _
SWP_NOACTIVATE Or SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOOWNERZORDER Or SWP_FRAMECHANGED)
Return True
End If
Next
Return False
End Function
#End Region
End Module
A questo punto nella form parent MDI si deve importare il modulo e usare il metodo SetBevel nella load, ovvero:
Imports itConsult.josh.joshDesigner.MDIUtil
Private Sub Form_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.SetBevel(False)
End Sub
Nei commenti del codice del modulo sono indicate anche le fonti da cui ho liberamente preso quel codice, ovvero questo post e questo post.
lunedì 25 febbraio 2013
Se definiamo un controllo personalizzato, per esempio un pulsante MyButton, nel quale vogliamo impostare dei valori inziali di una proprietà Browsable ci potrebbe essere utile impostare il DefaultValue tramite attributo (DefaultValueAttribute).
Infatti se non lo facciamo si ha l’inconveniente che l’editor di Visual Studio valorizza esplicitamente nel file .Designer le proprietà che abbiamo inizializzato nel nostro controllo.
Consideriamo l’esempio di un pulsante con un certo Font ed un certo colore:
Imports System.ComponentModel
Public Class MyButton
Inherits Button
Public Sub New()
'Inizializza le proprietà
Dim fontConverter As New FontConverter()
Me.Font = fontConverter.ConvertFromString(Nothing, Globalization.CultureInfo.InvariantCulture, DefaultSerializeFont)
Dim colorConverter As New ColorConverter()
Me.ForeColor = colorConverter.ConvertFromString(Nothing, Globalization.CultureInfo.InvariantCulture, DefaultSerializeForeColor)
' ==========================================
' Per ottenere il valore serializzato della proprietà si può usare il metodo
' ConvertToString di FontConverter, ColorConverter, etc.
' La seguente istruzione produce: serializedSegoeFont = "Segoe UI, 9.75pt"
Dim serializedSegoeFont As String = fontConverter.ConvertToString(Nothing, Globalization.CultureInfo.InvariantCulture, Me.Font)
' ==========================================
' Il seguente codice di esempio stampa il valore del default attribute della proprietà Font
Dim attributes As AttributeCollection = TypeDescriptor.GetProperties(Me)("Font").Attributes
Dim myAttribute As DefaultValueAttribute = CType(attributes(GetType(DefaultValueAttribute)), DefaultValueAttribute)
If myAttribute Is Nothing Then
Console.WriteLine("The default value is not setted")
Else
Console.WriteLine("The default value is: " & myAttribute.Value.ToString())
End If
End Sub
' Serializzazione dei valori da usare per il default
Const DefaultSerializeFont As String = "Segoe UI, 9.75pt"
Const DefaultSerializeForeColor As String = "65, 65, 65"
<DefaultValue(GetType(Color), DefaultSerializeForeColor)>
Public Overrides Property ForeColor As Color
Get
Return MyBase.ForeColor
End Get
Set(value As Color)
MyBase.ForeColor = value
End Set
End Property
<DefaultValue(GetType(Font), DefaultSerializeFont)>
Public Overrides Property Font As Font
Get
Return MyBase.Font
End Get
Set(value As Font)
MyBase.Font = value
End Set
End Property
End Class
In questo modo quando mettiamo un MyButton nella form Visual Studio genere il seguente codice:
Me.MyButton1.Location = New System.Drawing.Point(57, 45)
Me.MyButton1.Name = "MyButton1"
Me.MyButton1.Size = New System.Drawing.Size(183, 56)
Me.MyButton1.TabIndex = 0
Me.MyButton1.Text = "MyButton1"
Me.MyButton1.UseVisualStyleBackColor = True
ovvero non inserisce le 2 righe:
Me.MyButton1.Font = New System.Drawing.Font("Segoe UI", 9.75!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.MyButton1.ForeColor = System.Drawing.Color.FromArgb(CType(CType(65, Byte), Integer), CType(CType(65, Byte), Integer), CType(CType(65, Byte), Integer))
Qual è il problema di quelle 2 righe?
Il problema è che se un giorno decidessimo di cambiare il colore o il font del nostro MyButton e andassimo a modificare la New dell’oggetto ci accorgeremmo che ricompilando i progetti che usavano MyButton questi non si aggiornano. Questo succede perché le 2 righe inserite da visual studio vengono eseguite dopo la new, per cui sovrascrivono i nuovi valori che abbiamo pensato per quelle proprietà.
Impostando invece il DefaultValue informiamo visual studio che quelli sono i valori di default per quelle proprietà e quindi VS non li inserisce esplicitamente se hanno quel valore.
Una alternativa che non fa uso di DefaultValueAttribute è quella di sfruttare i metodi ResetPPP e ShouldSerializePPP, dove PPP è la proprietà (vedi questo post).
Ecco esempio:
Private Shared _defaultFont As New System.Drawing.Font("Segoe UI", 9.7F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 178, False)
Public Overrides Property Font() As System.Drawing.Font
Get
Return (MyBase.Font)
End Get
Set(value As System.Drawing.Font)
If value Is Nothing Then
MyBase.Font = _defaultFont
Else
If value Is System.Windows.Forms.Control.DefaultFont Then
MyBase.Font = _defaultFont
Else
MyBase.Font = value
End If
End If
End Set
End Property
Public Overrides Sub ResetFont()
Font = Nothing
End Sub
Private Function ShouldSerializeFont() As Boolean
Return (Not Font.Equals(_defaultFont))
End Function
venerdì 20 maggio 2011
Riprendo un post trovato in rete per un esempio di come ottenere un postback su un url la cui querystring è stata modificata dinamicamente via codice.
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server"> 1:
2:
3: private String queryString;
4:
5: protected void Page_PreRender(object sender, EventArgs e) {
6: if (!String.IsNullOrEmpty(queryString)) {
7: Button1.PostBackUrl = queryString;
8: }
9: }
10:
11: protected void Page_Load(object sender, EventArgs e) {
12: queryString = "?foo=bar;a=b";
13: }
14:
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Change Response QueryString</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="PostBackWithQueryString" />
</div>
</form>
</body>
</html>
L’esempio è esattamente quello di Ting-hao Yang, autore del post citato.
In SharePoint 2010 è possibile visualizzare una lista o una document library in lingue diverse.
Per ciascuna delle lingue supportate dalla lista si può impostare il nome visualizzato (Title) delle colonne nella lingua corrente.
Per questo motivo se si vuole modificare il Title di un SPField da codice non sono più sufficienti (come in SharePoint 2007) le istruzioni:
myField.Title "My first field"
myField.Update()
Ma è ora necessario gestire le risorse associate al Title.
Confrontando la documentazione sulla proprietà Title di SharePoint 2007 e SharePoint 2010, e quindi arrivando alla pagina di descrizione del metodo SPUserResource.SetValueForUICulture ero arrivato alla conclusione che il nuovo codice fosse il seguente:
newField.TitleResource.SetValueForUICulture(newField.ParentList.ParentWeb.UICulture, "My first field")
newField.Update()
In pratica sto impostando il valore della risorsa per il titolo del campo, relativamente alla cultura di default del sito web (SPWeb.UICulture). In realtà la cosa non funziona correttamente, infatti andando poi sul sito da browser potremmo non trovare la modifica. Dico potremmo, perché in realtà il tutto dipende dalla culture corrente del thread che esegue quel codice: se la culture coincide con quella di default dell’oggetto SPWeb allora funziona, altrimenti no.
In realtà, in definitiva mi sono accorto che dipende fondamentalmente dalla Culture del thread: se questa è la stessa dell’oggetto SPWeb (o direi quella di cui vogliamo impostare il Title) allora posso usare anche lo stesso codice di SharePoinht 2007.
Conclusione, a mio modo di vedere il codice è il seguente:
Dim currentCulture As Globalization.CultureInfo = Threading.Thread.CurrentThread.CurrentUICulture
Threading.Thread.CurrentThread.CurrentUICulture = newField.ParentList.ParentWeb.UICulture
newField.Title = "My first field"
newField.Update()
Threading.Thread.CurrentThread.CurrentUICulture = currentCulture
venerdì 15 ottobre 2010
La GridView ASP.NET di default ha un problema (fra gli altri) legato alla visualizzazione nel caso di nessun elemento presente.
Il problema è che se non ci sono elementi nasconde l’header delle colonne.
Se si vuole che l’header resti si può seguire questo post: http://www.aspitalia.com/script/829/Mostrare-Header-GridView-ASP.NET-2.0-Mancanza-Dati.aspx
In pratica si deve estendere la classe GridView con una classe del tipo:
Public Class MyGridView
Inherits System.Web.UI.WebControls.GridView
Protected Overrides Function CreateRow( _
ByVal rowIndex As Integer, _
ByVal dataSourceIndex As Integer, _
ByVal rowType As System.Web.UI.WebControls.DataControlRowType, _
ByVal rowState As System.Web.UI.WebControls.DataControlRowState) As System.Web.UI.WebControls.GridViewRow
If (rowType = DataControlRowType.EmptyDataRow) Then
Return MyBase.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
Else
Return MyBase.CreateRow(rowIndex, dataSourceIndex, rowType, rowState)
End If
End Function
End Class
La nostra gliglia personalizzata puo’ così essere inserita nella pagina, inserendo ad esempio questa direttiva in testa:
<%@ Register TagPrefix="jvpo" Namespace="TestMyGridView" Assembly="TestMyGridView,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" %>
Quindi va dichiarato il tag EmptyDataTemplate:
<EmptyDataTemplate>Nessun elemento</EmptyDataTemplate>
In realtà il template per il caso di empty data non verrà mai renderizzato, in quanto verrà “sacrificato” per renderizzare l’header.
Però si potrà sostituirlo ad esempo con una label da visualizzare o nascondere a seconda dei casi.