Posts
166
Comments
255
Trackbacks
1
agosto 2008 Entries
[OT] "Siamo" un paese civile...

Quando leggo queste notizie non so che pensare. Ho solo tanta rabbia. Viaggio tutti i giorni, per lavoro e per studio, come altre migliaia di persone. Non ho mai fatto neanche un graffio su un treno, perchè so che la situazione è già quella che, so che domani tornerò a viaggiare, so che non è questo il modo di vivere in un paese ritenuto "civile". Vorrei tanto sapere, qual'è lo scopo di queste persone nella vita, cosa ci trovano di così divertente nello "spaccare tutto". Mi dispiace tanto per quelle persone di Napoli i cui sacrifici vengono infagati da queste "persone" (se così possono essere definite). Scusate lo sfogo, ma a volte....

posted @ domenica 31 agosto 2008 18.22 | Feedback (14)
[OT] Povera mucca...

Scusate, ma queste foto mi hanno strappato più di un sorriso...

posted @ domenica 31 agosto 2008 13.01 | Feedback (0)
WPF: XmlDataProvider

Supponiamo di avere un file XML molto semplice, del tipo:

1 <?xml version="1.0" encoding="utf-8" ?> 2 <books> 3 <book id="1"> 4 <title>Introducing To Microsoft LINQ</title> 5 <isbn>43554354523</isbn> 6 </book> 7 <book id="2"> 8 <title>Pro WPF Windows Presentation Foundation in dot NET 3.0</title> 9 <isbn>232132142</isbn> 10 </book> 11 <book id="3"> 12 <title>Foundations of F#</title> 13 <isbn>772337271</isbn> 14 </book> 15 <book id="4"> 16 <title>Algorithms In Bioinformatics</title> 17 <isbn>12345678</isbn> 18 </book> 19 </books>

Vogliamo mostrare il contenuto del documento XML in un controllo WPF ListView o ListBox. Per effettuare il binding con i dati XML, WPF mette a disposizione degli sviluppatori la classe XmlDataProvider, la quale permette d'impostare in modo  rapido e semplice  l'uso di elementi XML come binding source per i controlli delle nostre applicazioni. Trattando nell'esempio un'applicazione WPF Windows Form, nel dizionario delle risorse della Window, aggiungiamo un'istanza della classe XmlDataProvider, specificando la chiave (key) d'identificazione all'interno della collezione, il Source, ovvero il percorso del file XML contenente i dati e l'espressione XPath da utilizzare per il recupero dei nodi interessati.

1 <Window.Resources> 2 <XmlDataProvider x:Key="BooksProvider" Source="Data.xml" XPath="./books/book" /> 3 </Window.Resources>

Per visualizzare i dati in un ListView, nel codice XAML possiamo scrivere:

1 <ListView Margin="12,45,12,117" Name="listView1" DataContext="{StaticResource BooksProvider}" ItemsSource="{Binding}" 2 SelectionChanged="listView1_SelectionChanged" MouseDoubleClick="listView1_MouseDoubleClick"> 3 <ListView.View > 4 <GridView> 5 <GridViewColumn Header="ID" Width="50" DisplayMemberBinding="{Binding XPath=@id}" ></GridViewColumn> 6 <GridViewColumn Header="Title" Width="250" DisplayMemberBinding="{Binding XPath=title}"></GridViewColumn> 7 <GridViewColumn Header="ISBN" Width="150" DisplayMemberBinding="{Binding XPath=isbn}"> 8 </GridViewColumn> 9 </GridView> 10 </ListView.View> 11 </ListView>

Notiamo come la proprietà DataContext del ListView sia impostata sull'istanza del XmlDataProvider dichiarata nelle risorse,e per il binding, invece di utilizzare la proprietà Path, andiamo ad utilizzare la proprietà XPath, anteponendo in caso di attributi, il carattere @.

Se invece di utilizzare un controllo ListView, volessimo presentare i dati utilizzando un ListBox, il codice XAML da scrivere potrebbe essere simile al seguente:

1 <ListBox Margin="12,0,12,25" Name="listBox1" DataContext="{StaticResource BooksProvider}" 2 ItemsSource="{Binding}" Height="76" VerticalAlignment="Bottom"> 3 <ListBox.ItemTemplate> 4 <DataTemplate > 5 <StackPanel Orientation="Horizontal"> 6 <TextBlock Text="{Binding XPath=@id}"> - 7 <TextBlock Text="{Binding XPath=title}"></TextBlock> 8 </TextBlock> 9 </StackPanel> 10 </DataTemplate> 11 </ListBox.ItemTemplate> 12 </ListBox>

Nel caso in cui volessimo associare del codice sull'evento Double-Click del ListView per ottenere informazioni sul nodo correttamente selezionato, come suggerito da Giuseppe Lippolis, possiamo scrivere nel codice XAML:

1 <ListView Margin="12,45,12,117" Name="listView1" DataContext="{StaticResource BooksProvider}" ItemsSource="{Binding}" ListViewItem.MouseDoubleClick="Item_MouseDoubleClick"> 2 .... 3 </ListView >

Nel code-behind:

1 private void Item_MouseDoubleClick(object sender, MouseButtonEventArgs e) 2 { 3 ListView lsv = (ListView)e.Source; 4 XmlElement book = (XmlElement)lsv.SelectedItem; 5 string message = String.Format("Double Click: {0} - {1} - {2}", 6 book.GetAttribute("id"), book["title"].InnerText, 7 book["isbn"].InnerText); 8 MessageBox.Show(message); 9 }

Technorati Tag: ,
posted @ domenica 31 agosto 2008 11.43 | Feedback (2)
WPF + LINQ + CollectionViewSource = Rss Reader

Questo post è nato con uno scopo diverso da quello dell'implementazione di un Rss Reader, dato che, è sufficiente cercare su internet per trovarne di belli e pronti, ma per enfatizzare alcune proprietà molto interessanti dei controlli WPF, come  la possibilità di eseguire il raggruppamento dei dati nei controlli ListBox o ListView. Piccola parentesi: per chi volesse conoscere in dettaglio le specifiche RSS 2.0 le può trovare qui. Iniziamo sviluppando un set di classi come riassunto dal seguente Class Diagram:

image

Nel resto dell'esempio saranno prese in considerazione solo istanze di tipo Rss e RssItem. Generalmente, senza considerare gli elementi opzionali, la struttura xml di un documento RSS è il seguente:

1 <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" ... 2 <channel> 3 <title>Il blog di Pietro Libro</title> 4 <link>http://blogs.ugidotnet.org/PietroLibroBlog/Default.aspx</link> 5 <description /> 6 <language>it-IT</language> 7 <copyright>Pietro Libro</copyright> 8 <managingEditor></managingEditor> 9 <generator>Subtext Version 1.9.5.176</generator> 10 ... 11 <item> 12 <title>Adeona, il software &amp;quot;salva&amp;quot; notebook</title> 13 <category>OT</category> 14 <category>Varie ed eventuali</category> 15 <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2008/08/26/93820.aspx</link> 16 <description>...</description> 17 .... 18 </item>

Per leggere un tale documento, utilizziamo un'istanza della classe XDocument, presente nel namespace System.Xml.Linq, contenente metodi che permettono la navigazione dei nodi del documento in maniera molto semplice. Se a questo aggiungiamo la potenza di Linq, veramente c'è poco da dire. Prima di tutto creiamo un'istanza  di XDocument e leggiamo il documento passando direttamente l'uri del fornitore del feed RSS:

1 XDocument xDocument = new XDocument(); 2 xDocument = XDocument.Load(blogUri);

Per recuperare tutti gli elementi item contenuti nel documento, utilizziamo Linq. Per far questo utilizziamo il metodo Descendants passando come parametro la stringa "Item":

1 _items = 2 (from item in xDocument.Descendants("item") 3 select new RssItem 4 { 5 Title = item.Element("title").Value, 6 Description =item.Element ("description").Value, 7 Category = item.Element("category") == null ? "Nessuna Categoria" : item.Element("category").Value , 8 Link = item.Element("link") == null ? "": item.Element("link").Value 9 }).ToList<RssItem>();

 _items è una lista tipizzata di oggetti RssItem.

Per presentare i dati recuperati  utilizziamo una Window WPF. Il nostro obiettivo è mostrare i dati raggruppati per categoria, ovvero ottenere qualcosa del tipo:

image

Per raggiungere il goal,  invece di utilizzare la proprietà ItemSource esposta dal controllo ListBox, utilizziamo un'istanza di oggetto di tipo CollectionViewSource la quale altro non è una che un Proxy della classe CollectionView. Quest'ultima permette di eseguire operazioni di raggruppamento, ordinamento, navigazione e ricerca su di una collezione di dati. Definiamo un'istanza di tipo CollectionViewSource nella collezione Window.Resources della nostra Window WPF:

1 <CollectionViewSource x:Key="cvs"> 2 <CollectionViewSource.GroupDescriptions> 3 <PropertyGroupDescription PropertyName="Category"/> 4 </CollectionViewSource.GroupDescriptions> 5 </CollectionViewSource>

Così facendo, aggiungiamo alla collezione GroupDescriptions un oggetto di tipo GroupDescription che descrive il criterio in base al quale i  dati devono essere raggruppati nella vista, nello specifico in base al valore della proprietà Category.

Tramite codice XAML, andiamo a descrivere come devono essere visualizzati i nostri Gruppi:

1 <Style x:Key="CustomGroupStyle" TargetType="{x:Type GroupItem}"> 2 <Setter Property="Margin" Value="0,0,0,5"/> 3 <Setter Property="Template"> 4 <Setter.Value> 5 <ControlTemplate TargetType="{x:Type GroupItem}"> 6 <Expander IsExpanded="False" BorderBrush="#FFA4B97F" BorderThickness="0,0,0,1"> 7 <Expander.Header> 8 <DockPanel> 9 <TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/> 10 <TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount, 11 Converter={StaticResource CustomConverter}, 12 ConverterParameter=' - Numero di post ({0}) '}"/> 13 </DockPanel> 14 </Expander.Header> 15 <Expander.Content> 16 <ItemsPresenter /> 17 </Expander.Content> 18 </Expander> 19 </ControlTemplate> 20 </Setter.Value> 21 </Setter> 22 </Style>

E gli elementi in essi contenuti:

1 <DataTemplate x:Key="ItemTemplate"> 2 <StackPanel> 3 <TextBlock Text="{Binding Path=Title}"></TextBlock> 4 <TextBlock> 5 <Hyperlink NavigateUri="{Binding Path=Link}" Click="Hyperlink_Click">Visualizza</Hyperlink> 6 </TextBlock> 7 </StackPanel> 8 </DataTemplate>

Non resta che definire il controllo ListBox:

1 <ListBox Name="lstBox" ItemTemplate="{StaticResource ItemTemplate}" Margin="12,41,12,12"> 2 <ListBox.GroupStyle> 3 <GroupStyle ContainerStyle="{StaticResource CustomGroupStyle}"/> 4 </ListBox.GroupStyle> 5 </ListBox>

Utilizzando un controllo Button per recuperare il contenuto del documento RSS, scriviamo il seguente codice C#:

1 LinqRss.Rss rss = new LinqRss.Rss(); 2 if (rss.Load("http://blogs.ugidotnet.org/PietroLibroBlog/Rss.aspx")) 3 { 4 CollectionViewSource collectionViewSource = this.FindResource("cvs") as CollectionViewSource ; 5 collectionViewSource.Source = rss.Items; 6 lstBox.ItemsSource = collectionViewSource.View; 7 }

In sintesi, recuperata l'istanza di CollectionViewSource contenuta nelle risorse della nostra Window WPF,  impostiamo la proprietà Source dell'oggetto CollectionViewSource utilizzando la collezione Items esposta dall'istanza Rss. Non resta che impostare la proprietà ItemSource del controllo ListBox con la proprietà View esposta da CollectionViewSource. Osservazione: i GroupItem sono costituiti da controlli Expander. Nell'ItemTemplate è presente anche un HyperLink che permette la navigazione verso il post d'interesse.

Codice C# e XAML

Technorati Tag:
posted @ mercoledì 27 agosto 2008 13.30 | Feedback (9)
Adeona, il software "salva" notebook

Se avete paura che qualcuno rubi il vostro notebook, non vi resta che installare questo software. E' in versione beta e ha molti punti deboli. ma l'idea è interessante.

posted @ martedì 26 agosto 2008 7.34 | Feedback (2)
[OT] Ferrari

E' tanto che non postavo a riguardo di un gran premio di Formula 1. Problemi di affidabilità per la Ferrari (rottura del motore per Raikkonen), e in questa fase del mondiale non è l'ideale.

Classifica finale del GP d'Europa:

1° Massa (Ferrari),  2° Hamilton (McLaren), 3° Kubica (Bmw Sauber)

Prossimo appuntamento: GP del Belgio, domenica 7 settembre

Technorati Tag:
posted @ domenica 24 agosto 2008 13.43 | Feedback (7)
ConvertAll<>

Supponiamo di avere una situazione schematizzata dal seguente Class Diagram:

image

Supponiamo di avere un unico metodo Add che aggiunge oggetti di tipo Person ad una lista tipizzata denominata People, come nel caso seguente:

1 2 List<Person> _people = new List<Person>(); 3 4 private void Add(Person p) 5 { 6 _people.Add(p); 7 }

Utilizziamo il seguente codice per popolare la collezione People :

1 Employee e = null; 2 e = new Employee(); 3 e.Age = 21; 4 e.Name = "Peter"; 5 e.Surname = "Book"; 6 e.Office = "Piazzale Kennedy 21"; 7 8 Add(e); 9 10 e = new Employee(); 11 e.Age = 23; 12 e.Name = "Anna"; 13 e.Surname = "Rossi"; 14 e.Office = "Via Ammiraglio Cagni 36"; 15 16 Add(e); 17 18 e = new Employee(); 19 e.Age = 35; 20 e.Name = "Mario"; 21 e.Surname = "Rossi"; 22 e.Office = "Via Duca degli Abruzzi"; 23 24 Add(e);

Se volessimo convertire la nostra lista tipizzata di oggetti Person in una lista tipizzata di oggetti Employee:

1 List<Employee> employees = new List<Employee>();

possiamo seguire due strade, la prima è utilizzare un ciclo foreach:

1 foreach (Person p in _people) 2 employees.Add((Employee)p);

La seconda  è quella di utilizzare il metodo generico ConvertAll<> che esegue la conversione di un Array di un tipo, Person in questo caso, in un Array di un'altro tipo,Employee, utilizzando un Converter, ovvero un metodo che esegue la conversione di un tipo in un altro. In soldoni (righe di codice :-) ):

Il Converter

1 private Employee PersonEmployeeeConverter(Person p) 2 { 3 if (p.GetType() == typeof(Employee)) 4 return (Employee)p; 5 else 6 return null; 7 }

Il codice di conversione:

1 employees = _people.ConvertAll<Employee>(new Converter<Person, Employee>(PersonEmployeeeConverter));

Osservazioni: ConvertAll<> e il concetto di Converter sono stati introdotti con il .Net Framework 2.0

Technorati Tag:
posted @ domenica 24 agosto 2008 13.32 | Feedback (2)
.NET Framework Tools

Il .Net Framework mette a disposizione degli sviluppatori un numero veramente grande di tool. Questo è un piccolo promemoria per alcuni di questi.

Storeadm.exe- Isolated Storage Tool

Con il .Net Framework 2.0 è stato introdotto il concetto di Isolated Storage. Un utile strumento per leggere o rimuovere tutti gli stores esistenti per un determinato utente è Storeadm.exe. Digitando Storeadm.exe su linea di comando senza specificare nulla, sono visualizzate le opzioni e la sintassi del tool (stesso risutlato può essere ottenuto digitando storeadm /? o storeadm /help).  Se volessimo ad esempio visualizzare tutti gli stores  sarebbe  sufficiente scrivere:

Storeadm.exe /list

Maggiori dettagli su Storeadm

 

Xsd.exe -XML Schema Definition Tool

Penso che questo tool sia stato utilizzato almeno una volta nella propria vita (professionale) da uno sviluppatore .Net: è  fondamentale per la generazione di schemi XML, di  classi a partire da file XDR, XML e per la generazione di XSD  dai tipi contenuti in un assembly. Le operazioni che possono essere eseguite  sono:

  • XDR->XSD: Generazione di uno schema XML (XSD) a partire da un  XML-Data Reduced schema (XDR)
  • XML->XSD: Generazione di uno schema XML (XSD) a partire da un file XML
  • XSD->DataSet: Generazione di un dataset a partire da uno file XSD.
  • XSD->Classi: Generazione di classi nei linguaggi VB.NET, C# (default), JS o VJS (J#), a partire da un file XSD. Le classi possono essere utilizzate da un Systemt.XML.Serialization.XMLSerializer per leggere e scrivere codice XML secondo lo schema dato
  • Classi->XSD: Generazione a partire da uno o più tipi in un assembly del corrispondente  XML schema.

Maggiori dettagli su Xsd.exe

 

Sn.Exe  - Strong Name Tool

Anche in questo caso penso che uno sviluppatore .Net abbia utilizzato questo tool almeno una volta. In particolare, permette di firmare un assembly con uno strong name (nome sicuro), assicurando che il nome assegnato all'assembly sia univoco. In particolare uno strong name  soddisfa i seguenti requisiti:

  • Univocità dei nomi perchè basati su coppie di chiavi univoche. Nessun'altro può generare lo stesso nome per un assembly diverso.
  • Garanzia sul fatto che nessun'altro può produrre una versione successiva del proprio assembly. Questo garantisce agli utenti che utilizzano una nuova versionie dell'assembly che quest'ultima è stata prodotta dalla stessa fonte del precedente
  • Controllo d'integrità garantendo che il contenuto dell'assembly non sia stato modifcato successivamente alla sua creazione.

Questo tool espone numerose opzioni. Vale la pena guardare anche i vari esempi di utilizzo presenti nella documentazione MSDN.

Maggiori dettagli su Sn.exe

 

SignTool.Exe - File Signing Tool

Questo tool permette di aggiungere una firma digitale ad un file, verificare una firma già presente o aggiungere un Time Stamp. Per questo tool è richiesta l'installazione della versione ridistribuibile di CAPICOM 2.0. Anche in questo caso le opzioni offerte sono numerose scondo del tipo di operazione da eseguire.

 Maggiori dettagli su SignTool.exe

 

Caspol.exe - Code Access Security Policy Tool

Questo tool permete all'utente e agli amministratori di modificare le policy di sicurezza a livello machine, user ed enterprise. L'intersezione dell'insieme delle autorizzazioni forniti da questi tre criteri è l'insieme di autorizzazioni che sono fornite ad un assembly. Strutturalmente, ogni criterio ha una gerarchia di gruppi di codice, dove ognuno di questi rappresenta una condizione di appartenenza che determina quale codice appartiene a tale gruppo. A ogni gruppo è associato un insieme di autorizzazioni che specifica a runtime quali autorizzazioni sono concesse al codice che soddisfa la condizione di appartenenza. Queste poche righe non possono assolutamente esaurire il significato e l'utilità di questo importante strumento, ma è necessaria una più attenta lettura. 

Maggiori dettagli su Caspol.exe

 

Permview.exe - Permission View Tool

Questo strumento permette di visualizzare le autorizzazioni minime, facoltative, rifiutate e richeste da un assembly. Questo tool può essere utilizzato anche per visualizzare la protezione dichiarativa di un assembly. Permview.exe è disponibile nelle versioni 1.0 e 1.1 del .Net Framework. Nella versione .Net 2.0 e superiori è presente il tool PermCalc.exe.

Maggiori Dettagli su PermView.exe

Maggiori Dettagli su PermCalc.exe

posted @ venerdì 22 agosto 2008 8.03 | Feedback (0)
[OT] Olimpiadi...

Se volete seguire in diretta le finali di Pechino 2008: Yalp!

Technorati Tag:
posted @ mercoledì 20 agosto 2008 12.19 | Feedback (0)
The database principal...and cannot be dropped

Promemoria. Questo link presenta una possibile soluzione nel caso in cui, lavorando con SQL Server 2005, si presenti il seguente messaggio d'errore:

The database principal owns a schema in the database, and cannot be dropped. (Microsoft SQL Server, Error: 15138).

posted @ lunedì 18 agosto 2008 13.29 | Feedback (0)
EventLog

Piccolo post derivato da una risposta su un forum. Un semplice modo per dotare una nostra applicazione di un log degli eventi, è utilizzare la classe EventLog che il .Net Framework mette a disposizione. MSDN suggerisce, nel caso in cui si debba usare il log per poche operazioni di utilizzare i metodi statici della classe EventLog, altrimenti conviene registrare un log degli eventi personalizzato e utilizzare un'istanza della classe EventLog. Quando detto si traduce in poche righe di codice:

1 if (!EventLog.SourceExists("MyEventLog", ".")) 2 EventLog.CreateEventSource("MyEventLog", "CustomApplication"); 3 4 _demoLog = new EventLog("CustomApplication", ".", "MyEventLog");

Per aggiungere una nuova entry al log è sufficiente utilizzare il metodo WriteEntry:

1 _demoLog.WriteEntry("Evento click eseguito", EventLogEntryType.SuccessAudit);

Se ad esempio, volessimo visualizzare le entries del nostro  log in un controllo ListBox è sufficiente eseguire un ciclo for each sulla collezione Entries esposta dall'istanza di EventLog:

1 string entryMessage =""; 2 foreach (EventLogEntry entry in _demoLog.Entries ){ 3 entryMessage = string.Format ("{0} {1} {2}", 4 entry.EntryType.ToString (),entry.MachineName , 5 entry.Message ); 6 7 listBox1.Items.Add (entryMessage ); 8 }

Per cancellare le entries, utilizziamo il metodo Clear() dell'istanza:

1 _demoLog.Clear();

Nel caso in cui invece volessimo eliminare l'Event Log registrato, è sufficiente utilizzare il metodo statico Delete() :

1 EventLog.Delete("MyEventLog")

Importante (1): Per creare ed eliminare un event source ( e realtive entries)  è necessario che l'utente abbia i diritti di amministrazione, altrimenti a run-time verrà sollevata l'opportuna eccezione. Magari il log degli eventi potrebbe essere registrato sulla macchina in fase di installazione dell'applicazione, fase in cui ci si aspetta che l'utente che esegue il task sia in posseso degli opportuni diritti di amministrazione

Importante (2): Per utilizzare il sistema di logging è necessario che il sistema operativo che ospita l'applicazione sia Windows 2000, Windows XP, Windows 2003 Server o superiori (Windows 98 e Windows Millennium Edition non supportano l'Event log)

Oltre che da codice, possiamo visualizzare lo stato del nostro log utilizzando l'apposito Event Viewer richiamabile anche da riga di comando: eventvwr.exe

Per l'esempio indicato, su Windows Vista Ultimate, otteniamo:

image

Per approfondimenti, MSDN

posted @ lunedì 18 agosto 2008 13.02 | Feedback (2)
WPF 3.5 SP1: Bindable WebBrowser

Se in una nostra WPF Windows Application abbiamo la necessità di utilizzare il nuovo controllo WebBrowser  per visualizzare del codice HTML, possiamo percorrere due strade, secondo delle nostre esigenze:

1) Il codice HTML deve essere visualizzato (ad esempio) sull'evento click di un controllo button: possiamo utilizzare i metodi NavigateToString(string text) o NavigateToStream(System.IO.Stream stream). Ad esempio, se scriviamo:

1 WebBrowserInstance.NavigateToString("<h2>Prova</h2><p>Ciao</p>");

otteniamo:

image

dove il codice XAML è:

1 <WebBrowser ClipToBounds="True" Name="WebBrowserInstance"></WebBrowser>

2) Se il codice HTML da visualizzare è ottenuto dinamicamente, sembra non essere presente (attualmente) un modo diretto per bindare il codice HTML ad una proprietà del controllo WebBrowser (anche se quest'ultimo è un DependencyObject). Per ovviare al problema possiamo creare un nuovo UserControl contenente un controllo WebBrowser. Il codice XAML dell'UserControl è:

1 <UserControl x:Class="MyNamespace.BindableWebBrowser" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Height="300" Width="300" Loaded="UserControl_Loaded"> 5 <Grid Name="contentGrid"> 6 </Grid> 7 </UserControl> 8

Mentre il codice C# è:

1 namespace MyNamespace 2 { 3 public partial class BindableWebBrowser : UserControl 4 { 5 6 private WebBrowser _wb = null; 7 8 public WebBrowser Wb 9 { 10 get { return _wb; } 11 set { _wb = value; } 12 } 13 14 public BindableWebBrowser() 15 { 16 InitializeComponent(); 17 18 _wb = new WebBrowser(); 19 _wb.Margin = new Thickness(0); 20 contentGrid.Children.Add(_wb); 21 } 22 23 public string HtmlCode 24 { 25 get { return (string)GetValue(TextProperty); } 26 set { SetValue(TextProperty, value); } 27 } 28 29 public static readonly DependencyProperty TextProperty = 30 DependencyProperty.Register("HtmlCode", typeof(string), 31 typeof(BindableWebBrowser), new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(HtmlDocumentChangedCallBack))); 32 33 public static void HtmlDocumentChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args) 34 { 35 BindableWebBrowser bindableWebBrowser = (BindableWebBrowser)property; 36 bindableWebBrowser.Wb.NavigateToString((string)args.NewValue); 37 } 38 39 private void UserControl_Loaded(object sender, RoutedEventArgs e) 40 { 41 } 42 } 43 }

In questo modo in una Window WPF, nel codice XAML, possiamo scrivere:

1 <local:BindableWebBrowser HtmlCode="&lt;h3&gt;Hello World!!!&lt;/h3&gt;" Margin="24.577,60,12,0" Grid.Column="1" Height="65" VerticalAlignment="Top"></local:BindableWebBrowser >

oppure eseguire un binding del controllo in questo modo:

1 <local:BindableWebBrowser HtmlCode="{Binding Path=Description}" ></local:BindableWebBrowser >

Ottenendo, utilizzando il codice del primo caso, quanto segue:

image

Se invece il nostro scopo è semplicemente visualizzare un sito web, allora è sufficiente scrivere nel codice XAML:

1 <WebBrowser Source="http://blogs.ugidotnet.org/" ClipToBounds="True" Name="wbTest"></WebBrowser>

Senza scrivere un nuovo UserControl.

L'aspetto grafico dell'UserControl può essere notevolmente migliorato (parliamo di WPF :-)), ma spero che il codice possa ritornare utile.

 

Technorati Tag: ,

 

posted @ domenica 17 agosto 2008 16.16 | Feedback (3)
[OT] Il robot col cervello di ratto...

Potrebbe sembrare uno scherzo, ma non lo è...Gordon è un robot che schiva gli ostacoli, ma ha un cervello biologico. Per chi è interessato, qui l'articolo completo.

posted @ giovedì 14 agosto 2008 8.50 | Feedback (3)
XPath: ricerche "case-insensitive" sui nomi dei nodi

Se ad esempio abbiamo un file XML del tipo (normalmente non dovrebbe accadere :-)) :

1 <?xml version="1.0" encoding="utf-8" ?> 2 <persone> 3 <persona id="1"></persona> 4 <PERSONA id="2"></PERSONA> 5 <perSona id="3"></perSona> 6 </persone>

e tramite XPath vogliamo recuperare tutti i nodi persona figli di persone, dato che le ricerche XPath (e XML) sono case-sensitive, possiamo utilizzare la funzione XPath translate() in questo modo:

1 XmlDocument xmlDocTest = new XmlDocument(); 2 xmlDocTest.Load("esempio.xml"); 3 XmlNodeList list = xmlDocTest.SelectNodes("//persone/*[translate(local-name(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='persona']"); 4 5 foreach (XmlNode nodeItem in list) 6 Console.WriteLine("Nodo " + nodeItem.Attributes["id"].Value);

Dove :

local-name() - restituisce il nome locale di un nodo senza il prefisso di namespace

translate() - Ritorna la sottostringa all'interno del primo argomento sostituendo i caratteri del secondo argomento con quello del terzo.

Se invece di eseguire la conversione in minuscolo, volessimo eseguire la conversione in maiuscolo basterebbe sostituire l'espressione XPath precedente:

1 "//persone/*[translate(local-name(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='persona']"

con la seguente:

1 "//persone/*[translate(local-name(),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')='PERSONA']"

L'utilizzo di una delle due espressioni conduce ovviamente allo stesso risultato.

 

Technorati Tag: ,
posted @ martedì 12 agosto 2008 10.02 | Feedback (0)
Regular Expression

Un interessante sito con regular expression pronte all'uso ed un regex tester on-line.

http://regexlib.com

Technorati Tag:
posted @ sabato 9 agosto 2008 8.34 | Feedback (0)
System.Net.Mail: Modi diversi di inviare un'e-mail

Spesso si leggono nei forum post  di richiesta su come poter inviare e-mail (con e senza allegati) utilizzando le classi che il Framework .Net  mette a disposizione. Spero che questo piccolo post con relativo codice d'esempio possa tornare utile.

Per inviare una semplice mail di testo senza allegati è sufficiente scrivere:

1 //Mail Plain Text - Senza allegato 2 MailMessage mailMessagePlainText = new MailMessage(); 3 mailMessagePlainText.From = new MailAddress("indirizzo.mittente@dominio.it", "Mittente"); 4 mailMessagePlainText.To.Add (new MailAddress ("destinatario@dominio.it","Destinatario")); 5 mailMessagePlainText.Subject ="Plain Text e-mail"; 6 //mailMessage.CC utilizzare se è necessario inviare in copia carbone 7 mailMessagePlainText.Body ="Questa è una bellissima e-mail, soprattutto utile!";

Se invece volessimo inviare un'e-mail in formato HTML con allegato, possiamo scrivere:

1 //Mail Html - con allegato 2 MailMessage mailMessageHTMLWithAttach = new MailMessage (); 3 mailMessageHTMLWithAttach.From = new MailAddress("indirizzo.mittente@dominio.it", "Mittente"); 4 mailMessageHTMLWithAttach.To.Add (new MailAddress ("indirizzo.destinatario@dominio.it","Destinatario")); 5 mailMessageHTMLWithAttach.Subject = "HTML e-mail"; 6 //mailMessage.CC utilizzare se è necessario inviare in copia carbone 7 mailMessageHTMLWithAttach.Body = "<html><body><h1>Hello World</h1><h2>by e-mail</h2></body></html>"; 8 mailMessageHTMLWithAttach.IsBodyHtml = true; 9 ContentType contType = new ContentType ("text/plain"); 10 mailMessageHTMLWithAttach.Attachments.Add (new Attachment ("Allegato.txt", contType )); 11 //oppure 12 //mailMessageHTMLWithAttach.Attachments.Add(new Attachment("Allegato.txt", MediaTypeNames.Text.Plain)); 13 //o semplicemente 14 //mailMessageHTML.Attachments.Add (new Attachment ("Allegato.txt"));

In questo caso si suppone che il file Allegato.txt si trovi nella stessa directory dell'eseguibile.

Infine se volessimo inviare un'e-mail in formato HTML con allegato, ed un'immagine incorporata nel body HTML, è necessario scrivere qualche riga di codice in più, ma nulla di complicato:

1 //Mail HTML - con immagini incorporate 2 MailMessage mailMessageWithEmbeddedPicture = new MailMessage (); 3 mailMessageWithEmbeddedPicture.From = new MailAddress("indirizzo.mittente@dominio.it", "Mittente"); 4 mailMessageWithEmbeddedPicture.To.Add (new MailAddress ("indirizzo.destinatario@dominio.it","Destinatario")); 5 mailMessageWithEmbeddedPicture.Subject = "HTML e-mail with embedded picture"; 6 7 string htmlBody = "<html><body><h1>Hello World</h1><h2>by e-mail</h2><img src=\"cid:emb1\" /></body></html>"; 8 //Crea un'istanza AlternateView 9 AlternateView altViewHtml = AlternateView.CreateAlternateViewFromString (htmlBody ,null, MediaTypeNames.Text.Html ); 10 //Crea un'istanza LinkedResource 11 LinkedResource embeddedPicture = new LinkedResource("Foto.jpeg", MediaTypeNames.Image.Jpeg); 12 embeddedPicture.ContentId = "emb1"; 13 //Aggiunge l'istanza LinkedResource all'istanza AlternateView 14 altViewHtml.LinkedResources.Add(embeddedPicture); 15 16 //Per i client che non supportano la visualizzazione HTML 17 string warningMessage = "Utilizzare un client di posta che supporta la visualizzazione dei messaggi in HTML"; 18 //Creiamo una nuova istanza di AlternateView 19 AlternateView altViewText = AlternateView.CreateAlternateViewFromString(warningMessage, contType ); 20 21 mailMessageWithEmbeddedPicture.AlternateViews.Add(altViewHtml); 22 mailMessageWithEmbeddedPicture.AlternateViews.Add(altViewText);

In quest'ultimo caso, se si utilizza ad esempio Microsoft Outlook come client di posta elettronica, il risultato sarebbe del tipo:

image

In tutti i tre casi descritti, per inviare il messagio utilizziamo un'istanza della classe System.Net.SmtpClient.

1 SmtpClient smtpClient = new SmtpClient("smtp.dominio.it"); 2

Nel caso in cui il server SMTP richieda l'autenticazione è necessario fornire le credenziali d'accesso mediante istanza della classe System.Net.NetworkCredential. In più se supportata dal server si può  utilizzare SSL:

1 //se è necessario autenticarsi... 2 //smtpClient.Credentials = new System.Net.NetworkCredential("username", "password"); 3 //oppure 4 //smtpClient.Credentials = new System.Net.NetworkCredential("username", "password","dominio"); 5 6 //Se è necessario ed è supportata la cifratura SSL 7 //smtpClient.EnableSsl =true ;

Il codice d'invio (Sincrono) dei messagi di posta è:

1 try 2 { 3 smtpClient.Send(mailMessagePlainText); 4 smtpClient.Send(mailMessageHTMLWithAttach); 5 smtpClient.Send(mailMessageWithEmbeddedPicture); 6 } 7 catch (SmtpException smtpException) 8 { 9 MessageBox.Show(String.Format("SmtpException : {0}", smtpException.Message)); 10 } 11 catch (Exception ex) 12 { 13 MessageBox.Show(string.Format("Exception: {0}", ex.Message)); 14 }

In tutti i casi, per inviare un messagio di posta elettronica utilizzando le classi messe a disposizione dal Framework .Net, utilizziamo un'istanza della classe System.Net.Mail.MailMessage, ed impostando le relative proprietà  possiamo inviare e-mail in formato testo/html con e senza allegati. Interessante è l'utilizzo di istanze delle classe AlternateView per la visualizzazione in diversi formati del messaggio di posta. La proprietà SmtpClient.EnableSsl è stata introdotta con la versione 2.0 del Framework .Net. In allegato al post il progetto d'esempio completo.

Codice: TestMai.zip

 

posted @ mercoledì 6 agosto 2008 13.24 | Feedback (2)
News

View Pietro Libro's profile on LinkedIn

Pietro Libro