Progetto e sviluppo di un'applicazione per dispositivi mobili per la visualizzazione di materiale...

22
1 UNIVERSITÀ DEGLI STUDI DI TRIESTE DIPARTIMENTO DI INGEGNERIA E ARCHITETTURA Corso di laurea triennale in Ingegneria dell'informazione "PROGETTO E SVILUPPO DI UN’APPLICAZIONE PER DISPOSITIVI MOBILI PER LA VISUALIZZAZIONE DI MATERIALE DIDATTICO" Laureando: Relatore: Bassi Paola prof. Fermeglia Maurizio Anno Accademico 2014-2015

Transcript of Progetto e sviluppo di un'applicazione per dispositivi mobili per la visualizzazione di materiale...

1

UNIVERSITÀ DEGLI STUDI DI TRIESTE

DIPARTIMENTO DI INGEGNERIA E

ARCHITETTURA

Corso di laurea triennale

in

Ingegneria dell'informazione

"PROGETTO E SVILUPPO DI UN’APPLICAZIONE

PER DISPOSITIVI MOBILI PER LA

VISUALIZZAZIONE DI MATERIALE DIDATTICO"

Laureando: Relatore:

Bassi Paola prof. Fermeglia Maurizio

Anno Accademico 2014-2015

2

INDICE

Introduzione.....................................................................................................3

CAPITOLO 1: I DATI.......................................................................................3

• Scelta del database e FileTable……………………………………..3

• Creazione del database………………………………………………4

• Funzioni associate al database……………………………………...6

CAPITOLO 2: WEB SERVICE……………………………………………………...8

• Generalità………………………………………………………………8

• Tecnologia WCF……………………………………………………….8

CAPITOLO 3: APPLICAZIONE WINDOWS PHONE.......................................11

• Mainpage……………………………………………………………....11

• FlatList…………..……………………………………………………...13

• Searchpage ……………….……………………………….................17

• JumpList ……………………………………………………................18

Conclusione.......................................................................................................22

3

Introduzione

L’obiettivo di questa tesi consiste nell’analizzare le tecniche di sviluppo di applicazioni mobile e

delle tecnologie utilizzate per l'importazione dei dati in esse.

Nello specifico, questa applicazione consentirà all'utente di visualizzare e consultare, attraverso il

proprio dispositivo, i files presenti in un database.

Capitolo 1: I DATI

Scelta del database e FileTable

Per questo progetto si è deciso di costruire un database, in ambiente SQL Server 2014 express

with Advanced Services, che supporta le tecnologie Filestream e Filetable.

La caratteristica FileTable si basa sulla tecnologia Filestream e fornisce supporto per lo spazio dei

nomi dei file di Windows e la compatibilità con le applicazioni di Windows ai dati dei file archiviati in

SQL Server. FileTable consente l'integrazione degli elementi di archiviazione e gestione dei dati da

parte di un'applicazione e fornisce servizi di SQL Server integrati, incluse la ricerca full-text, su dati

e metadati non strutturati.

In altre parole, è possibile archiviare file e documenti in speciali tabelle denominate FileTable in

SQL Server, ma accedere a tali file e documenti da applicazioni di Windows come se questi

fossero archiviati nel file system, senza apportare alcuna modifica alle applicazioni del client.

In SQL Server viene fornita una speciale tabella di file, denominata anche FileTable, per

applicazioni che richiedono archiviazione di file e directory nel database, con compatibilità con le

API Windows e accesso non transazionale. Il termine FileTable indica una tabella utente specifica

con uno schema predefinito per l'archiviazione di dati FILESTREAM, nonché informazioni sulla

gerarchia di file e directory e attributi di file.

Una tabella FileTable offre le funzionalità seguenti:

• Una tabella FileTable rappresenta una gerarchia di directory e file.In tale tabella sono

archiviati i dati correlati a tutti i nodi nella gerarchia, sia per le directory sia per i file inclusi

in tali nodi. Questa gerarchia inizia da una directory radice specificata durante la creazione

della tabella FileTable.

• Ogni riga in una tabella FileTable rappresenta un file o una directory.

• Ogni riga contiene i seguenti elementi.Per ulteriori informazioni sullo schema di una tabella

FileTable, vedere Schema delle tabelle FileTable.

• Una colonna file_stream per dati del flusso e un identificatore stream_id (GUID)(la colonna

file_stream è NULL per una directory).

• Entrambe le colonne path_locator e parent_path_locator per la rappresentazione e la

gestione della gerarchia di file e directory.

4

• 10 attributi di file, quali data di creazione e data di modifica, utili con le API di I/O dei file.

• Una colonna Type che supporta la ricerca full-text e la ricerca semantica su file e

documenti.

• Una tabella FileTable applica determinati vincoli e trigger definiti dal sistema per gestire la

semantica degli spazi dei nomi dei file.

Quando il database è configurato per l'accesso non transazionale, la gerarchia di file e directory

rappresentata nella tabella FileTable viene esposta sotto la condivisione di FILESTREAM

configurata per l'istanza di SQL Server.In questo modo, viene fornito l'accesso al file system per

applicazioni Windows.

Creazione del database

Come già detto in precedenza, l'obiettivo è di creare un archivio di documenti e a questo scopo si

utilizza una FileTable.

La prima cosa da fare è abilitare Filestream, e lo si può fare dalle impostazioni del motore

database. Il passo successivo è la creazione del database abilitato ai Filestream, e l'attivazione

dell'accesso non transazionale a livello di database.

A tal proposito si esegue una query che modifica i diritti d’accesso a questo e ai futuri database

settandolo a FULL (le altre possibilità sono OFF e READ ONLY) e crea il database:

GO -- Enable Filestream EXEC sp_configure filestream_access_level, 2 RECONFIGURE GO CREATE DATABASE FileTableDB ON PRIMARY ( NAME = FileStreamArchive, FILENAME ='C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\DataArchive.mdf'), FILEGROUP [FS1] CONTAINS FILESTREAM ( NAME = Archive, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\FileStreamArchive') LOG ON ( NAME = LogArchive, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\LogArchive.ldf') WITH FILESTREAM ( NON_TRANSACTED_ACCESS = FULL, DIRECTORY_NAME = 'FileTable' ) GO

A questo punto si deve lanciare un'altra query che crea la tabella (FileTable) che contiene le

colonne che identificano i file.

5

-- Create FileTable Table USE FileTableDB GO CREATE TABLE CartellaFile AS FileTable WITH( FileTable_Directory = 'CartellaFile', FileTable_Collate_Filename = database_default, FILETABLE_STREAMID_UNIQUE_CONSTRAINT_NAME=UQ_stream_id); GO

A questo punto avremo creato la base di dati per il nostro progetto. Si tenga presente che la

popolazione della FileTable avviene come una qualsiasi altra tabella di Windows, cioè con le solite

funzioni di COPIA/TAGLIA e INCOLLA.

L'ambiente di sviluppo dell'applicazione mobile non supporta alcuni campi della FileTable, nello

specifico il campo path_locator, che è quello che indica la collocazione del file. Per questo viene

creata una tabella "di appoggio" (dbo.DatiApp) utilizzata dall'applicazione per accedere ai dati. In

questo caso, la tabella è una semplice tabella nelle quali vengono copiate alcune delle colonne

della FileTable. Volendo, si potrebbero copiare tutti i campi ad esclusione di quelli non consentiti,

ma sarebbe uno spreco di risorse perché poi non verrebbero utilizzati.

Per la creazione di quest'ultime, si lancia una query:

USE FileTableDB

GO

CREATE TABLE DatiApp (

Nome nvarchar(255) NOT NULL,

Formato nvarchar(255) NOT NULL,

Indirizzo nvarchar(500) NOT NULL,

);

GO

6

Funzioni associate al database

Per la popolazione di queste tabelle si utilizzeranno dei Trigger che verranno illustrati nel prossimo

paragrafo.

SQL Server, offre le funzionalità necessarie alla creazione di query più o meno complesse su tipi di

dati carattere che possono includere parole o intere frasi: SQL Full-Text Search (SQL FTS).

Si tratta di un componente in grado di effettuare interrogazioni veloci ed efficienti su indicizzazioni

di testi, ovvero query che si basano su termini chiave, parti di testo o semplici parole.

Possiamo ottenere i massimi benefici da questa tecnica soprattutto in presenza di grandi moli di

informazioni di tipo non strutturato, come possono essere testi o interi documenti (come nel nostro

caso.)

Per rendere disponibile e quindi utilizzare questa funzionalità bisogna:

• abilitare la ricerca per il database (sp_fulltext_database)

• creare il catalogo (sp_fulltext_catalog)

• marcare la tabella per l'indicizzazione fulltext (sp_fulltext_table)

• aggiungere le colonne che si vogliono indicizzare (sp_fulltext_column)

• attivare l'indice (sp_fulltext_table)

• popolare l'indice (sp_fulltext_catalog)

Per attivare questa caratteristica e aggiungere le varie funzionalità si utilizza il wizard fornito da

SQL Management Studio:

Affinchè l'applicazione mobile possa eseguire tutte le funzioni desiderate (oltre a quella

sopracitata), è necessario ricorrere all'uso di Trigger e Stored Procedure associate al database di

cui sopra.

Una stored procedure è un gruppo di istruzioni Transact-SQL compilate una volta sola, ma

eseguibili più volte. Dato che le istruzioni Transact-SQL non devono essere ricompilate, in fase di

esecuzione della stored procedure si ottiene un miglioramento delle prestazioni.

7

Un trigger è una stored procedure speciale che non viene chiamata direttamente dall'utente. In

fase di creazione, un trigger viene definito per l'attivazione in corrsispondenza dell'esecuzione di

uno specifico tipo di modifica dei dati in una determinata tabella o colonna.

La prima funzione necessaria viene creata per mantenere aggiornata la tabella di appoggio

(dbo.DatiApp). Si crea un TRIGGER che copia le colonne Nome, Formato e Indirizzo (dalla

FileTable) e mantiene aggiornata la tabella in caso di modifiche dei file della FileTable.

Visual studio non supporta il contenuto del campo che indica l'indirizzo locale del file della

FileTable, per questo motivo bisogna utilizzare all’interno del TRIGGER le funzioni fornite per le

FileTable, affinchè dai campi disponibili, venga ricostruita la stringa che indica l'indirizzo, e venga

inserita nel campo indirizzo di dbo.DatiApp.

In altre parole si trova il percorso completo di un file al runtime mediante l'utilizzo combinato delle

funzioni FileTableRootPath (Transact-SQL) e GetFileNamespacePath (Transact-SQL).Per

impostazione predefinita, la funzione GetFileNamespacePath restituisce il percorso relativo del file

all'interno del percorso radice per il database.

Avremo quindi una stringa del tipo C:\\Paola\sqlexpress\Home\prova.txt.

CREATE TRIGGER CopiaFile ON dbo.DatiApp

INSTEAD OF INSERT

AS

BEGIN

INSERT dbo.DatiApp(Nome, Formato, Indirizzo)

SELECT name, file_type, FileTableRootPath()+file_stream.GetFileNamespacePath()

FROM dbo.CartellaFile

END

Un'altra funzione ci deve consentire di utilizzare la ricerca full text. In questo caso verrà creata una

STORED PROCEDURE che verrà invocata dall’applicazione mobile, alla pressione di un bottone.

CREATE PROCEDURE FindFullText -- Add the parameters for the stored procedure here @parola nvarchar(50) AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; -- Insert statements for procedure here SELECT name FROM dbo.CartellaFile WHERE CONTAINS (file_stream, @parola) END GO

8

Capitolo 2: WEB SERVICE

Generalità

Un Web service è un componente applicativo. Possiamo definirlo come un sistema software in

grado di mettersi al servizio di un applicazione comunicando su di una medesima rete tramite il

protocollo HTTP. Un Web service consente quindi alle applicazioni che vi si collegano di usufruire

delle funzioni che mette a disposizione, che spaziano da una semplice richiesta di informazioni ad

un complicato processo commerciale.

Un Web Service può essere sfruttato contemporaneamente per più operazioni, essendo condiviso

in rete e disponibile a tutti.

L'idea fondamentale che sta alla base dei Web services è l'integrazione come servizio. Il concetto

rappresenta un set definito di tecnologie basate sugli standard industriali, che lavorano insieme per

facilitare l'interoperabilità tra sistemi eterogenei, che siano all'interno della stessa azienda, o

risiedano da qualche parte su Internet. Con i Web services si possono abilitare applicazioni al

Web, per farle comunicare con altre applicazioni che sono state a loro volta abilitate agli standard

dei Web services.

Tecnologia WCF

Windows Comunication Foundation mette assieme tutte queste tecnologie fornendo un modello

unificato di programmazione (e relativa API) per la realizzazione di applicazioni interoperabili, il

tutto basato su standard condivisi il che permette lo scambio di informazioni anche tra piattaforme

tra loro non eterogenee. In particolare WCF è stato strutturato in modo tale da offrire supporto per

tutti gli standard WS-*, cioè per tutte quelle nuove specifiche che sono nate dopo l’avvento dei

Web Service, che hanno come fine comune quello di favorire l’interoperabilità tra piattaforme

diverse tra loro. Infine, come abbiamo già detto, questo nuovo modello unificato di

programmazione è stato basato sulle linee guida delle architetture SOA. Una delle novità

interessanti di WCF sta nel fatto che possiamo creare un semplice servizio ed esporlo tramite IIS

come Web Service (utilizzando quindi il protocollo HTTP) oppure, modificando le informazioni di

configurazione del servizio stesso, renderlo utilizzabile attraverso il protocollo TCP/IP.

Nel caso specifico la prima cosa da fare però sarà creare un "ASP.NET empty website template"

che ci permetterà di creare il modello dei dati.

Il passo successivo appunto, è creare il modello dei dati. Visual Studio permette di aggiungere un

"ADO.NET Entity Model", che ci consente di scegliere se importare i dati da un database( come

nel nostro caso). A questo punto, basta creare una connessione col motore database, scegliere il

database e di conseguenza le tabelle e le stored proceudre desiderate.

9

Nel nostro caso, importeremo la tabella dbo.DatiApp e la stored procedure findfulltext. Alla

creazione del modello, Visual studio definirà una classe che gestisce questi elementi, creando nel

caso della stored procedure un metodo ad hoc.

public partial class FileTableEntities : DbContext

{

public FileTableEntities()

: base("name=FileTableEntities")

{

}

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

throw new UnintentionalCodeFirstException();

}

public DbSet<DatiApp> DatiApps { get; set; }

public virtual int FindFullText(string parola)

{

var parolaParameter = parola != null ?

new ObjectParameter("parola", parola) :

new ObjectParameter("parola", typeof(string));

return

((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("FindFullText",

parolaParameter);

}

}

}

10

A questo punto, verrà creato, un servizio WCF (con estensione .svc) con il compito di restituire i

file interrogando il databse. L’applicazione host per il nostro servizio sarà o IIS oppure il Web

server integrato di Visual Studio.

Si aggiunge quindi al progetto, un nuovo elemento "Silverlight-enable WCF Service".Notiamo che,

una volta aggiunto al proprio progetto di sviluppo un elemento di qeusto tipo, l’IDE creerà un file

con estensione .svc (il servizio vero e proprio).

Sarà ora necessario scrivere il codice per il web service che interroga il database e restituisce tutti

gli oggetti all'interno della tabella importata nel modello dei dati.

Il metodo principale di questo codice “scorre” i dati della tabella che ho importato e crea una lista di

oggetti di tipo DatiApp (List<DatiApp>). Il nome FileTableEntities può essere ambiguo, ma è stato

definito durante la creazione del WCF e sta ad indicare le entità della tabella dbo.DatiApp e non

della FileTable vera e propria.

namespace Querying_database

{

[ServiceContract(Namespace = "")]

[AspNetCompatibilityRequirements(RequirementsMode =

AspNetCompatibilityRequirementsMode.Allowed)]

public class ServiceApp

{

[OperationContract]

public List<DatiApp> GetAllDati()

{

using (FileTableEntities entities = new FileTableEntities())

{

var allDatiApps = from x in entities.DatiApps

select x;

return allDatiApps.ToList();

}

}

}

}

Una volta completata questa parte di configurazione, il servizio è così pronto all’uso. Per vederlo in

azione, basta aprire il browser.

11

Il WCF va salvato all'interno dello stesso progetto dove verrà creata l'applicazione mobile (che

vedremo nel dettaglio nel prossimo capitolo) alla quale verrà aggiunta una referenza al servizio.

Capitolo 3: APPLICAZIONE WINDOWS PHONE

Per questo progetto si è deciso di partire da un applicazione "blank" e all'interno creare varie

pagine che ci consentano di esaurire le nostre richieste. Ogni pagina è formata da una parte di

interfaccia, in formato .xaml e una parte di funzioni associate all'interfaccia, in formato .cs.

Main page

Nella main page sono stati inseriti semplicemente il titolo e tre bottoni che ci consentono di

scegliere a quali pagine essere indirizzati.

Avremo quindi una situazione di questo genere:

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">

<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"

Margin="12,0"/>

<TextBlock Text="Materiale didattico" Margin="9,-7,0,0" Style="{StaticResource

PhoneTextTitle1Style}" FontSize="55"/>

</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="2" Margin="12,0,12,0">

<Grid.RowDefinitions>

12

<RowDefinition Height="*"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<HyperlinkButton Content="FlatList" NavigateUri="/FlatList.xaml" Grid.Row="0"/>

<HyperlinkButton Content="JumpList" NavigateUri="/JumpList.xaml"

Grid.Row="1" />

<HyperlinkButton Content="SearchPage" NavigateUri="/SearchPage.xaml"

Grid.Row="2"/>

</Grid>

Come si può vedere nel codice evidenziato, l'evento legato ai due bottoni, porta l'utente a navigare

su altre pagine, che andranno create e definite di seguito.

Nella parte della pagina che riguardara le funzioni (in C#),per quanto riguarda la mainpage, non

serve definire nulla perchè il costruttore che inizializza gli elementi della pagina, viene creato

automaticamente.

A scopo didattico si è deciso di creare 2 pagine che sostanzialmente producono risultati simili.

Per quanto riguarda la "FlatList" è una semplice lista nella quale vengono elencati tutti i file

presenti nella filetable. La seconda lista, "JumpList", è più funzionale e in questa, oltre ad indicare

la lista dei file disponibili, verranno aggiunte altre funzioni che vedremo nel paragrafo dedicato.

13

FlatList

All'interno di questo paragrafo vedremo come importare i dati nella pagina e creare la lista prima

citata, oltre che definire l’interfaccia.

All'interno del progetto precedentemente creato, abbiamo aggiunto il webservice creato nel

capitolo precedente. Questo passo è molto semplice perchè al momento di creazione del

riferimento, Visual Studio ci permette di importare direttamente i servizi che si trovano all'interno

dello stesso progetto.

14

Si nota inoltre, che l'indirizzo fornito alla voce Address, è proprio quello che ci ha permesso di

verificare il funzionamento del WebService come visto nell'ultima parte del capitolo dedicato a

questo argomento (Capitolo 2).

Per poter accedere alle funzioni del webservice va aggiunto un namespace, nelle pagine che lo

chiamano: using LongListSelectorDemo.ServiceAppReference;

Inoltre va definito un codice per chiamare il webservice dall'applicazione e per definire il gestore

degli eventi:

using System;

using System.Windows;

using Microsoft.Phone.Controls;

using LongListSelectorDemo.ServiceAppReference;

namespace LongListSelectorDemo

{

public partial class FlatListDemo : PhoneApplicationPage

{

// Constructor

public FlatListDemo()

{

InitializeComponent();

this.Loaded += new RoutedEventHandler(LongListSelector_Loaded);

}

void LongListSelector_Loaded(object sender, RoutedEventArgs e)

{

ServiceAppClient client = new ServiceAppClient();

client.GetAllDatiCompleted += new

EventHandler<GetAllDatiCompletedEventArgs>(client_GetAllDatiCompleted);

client.GetAllDatiAsync();

}

void client_GetAllDatiCompleted(object sender, GetAllDatiCompletedEventArgs e)

{

if (e.Error == null)

{

//bind the data to the longlistselector

lst.ItemsSource = e.Result;

}

}

}

15

}

A questo punto l'applicazione è pronta ad accedere al database e, nello specifico, nella tabella di

appoggio creata nel primo capitolo. L'output sarà una lista contenente i nomi.

Per definire come dev'essere rappresentata la lista all'utente, ovviamente, bisogna modificare la

parte xml della pagina.

<phone:PhoneApplicationPage

x:Class="LongListSelectorDemo.FlatListDemo"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

FontFamily="{StaticResource PhoneFontFamilyNormal}"

FontSize="{StaticResource PhoneFontSizeNormal}"

Foreground="{StaticResource PhoneForegroundBrush}"

SupportedOrientations="Portrait" Orientation="Portrait"

mc:Ignorable="d"

shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->

<StackPanel Grid.Row="0" Margin="12,17,0,28">

<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock Text="Materiale didattico" Margin="9,-7,0,0" Style="{StaticResource

PhoneTextTitle1Style}"/>

</StackPanel>

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<phone:LongListSelector x:Name="lst" Width="500" Height="500">

<phone:LongListSelector.ListHeader>

<TextBlock Text="Lista" Style="{StaticResource PhoneTextTitle1Style}"

Foreground="White"/>

</phone:LongListSelector.ListHeader>

<phone:LongListSelector.ItemTemplate>

16

<DataTemplate>

<StackPanel Margin="{StaticResource PhoneMargin}"

Orientation="Horizontal" >

<TextBlock Text="{Binding Nome}"

Margin="12,0,12,0"

Style="{StaticResource PhoneTextLargeStyle}"/>

<TextBlock Text="{Binding Formato}"

Margin="12,0,12,0"

Style="{StaticResource PhoneTextLargeStyle}"/>

</StackPanel>

</DataTemplate>

</phone:LongListSelector.ItemTemplate>

</phone:LongListSelector>

</Grid>

</Grid>

</phone:PhoneApplicationPage>

La parte del codice evidenziata in giallo, è il fulcro della pagina e definisce "da dove" prelevare i

dati. In questo caso infatti "Binding Nome" ci dice di andare a prendere ciò che è contenuto nella

colonna Nome della tabella prima definita.

L'XML data binding costituisce un modo per trasformare le informazioni contenute in un

documento XML in un oggetto (object). Infatti, se andiamo a vedere il codice precedentemente

creato, l'output della pagina sarà una List<DatiApp>, cioè una lista contenente oggetti di tipo

DatiApp. Come tipo di lista, si è utilizzata una LongListSelector con attributo Name=”lst” (come

evidenziato in azzurro). Lo stesso oggetto è richiamato nel codice del gestore eventi, o meglio

nella lst vengono, appunto, aggiunti i dati richiesti

La parte restante di codice XAML definisce la griglia, i vari margini e le dimensioni dei testi, oltre

che i contenuti dei titolo.

17

Search page

La pagina di ricerca è stata creata per gestire la la stored procedure findfulltext.

Vengono aggiunti un bottone e due textbox, il primo come input e il secondo come output.

Il codice che gestisce la pressione del bottone è il seguente:

private void button_Click(object sender, RoutedEventArgs e)

{

string parola = textBox.Text;

FileTableDBEntities a = new FileTableDBEntities();

String list = 0;

int x = a.FindFullText(parola, list);

textBox1.Text = list;

}

e permette di inserire nella seconda textbox il risultato della stored procedure che viene chiamata

tramite il metodo ad essa associato (FindFullText). Questo metodo era stato precedentemente

18

definito durante la creazione del modello dei dati, nello specifico quando sono state importate le

stored procedure.

La parte XAML è molto semplice e rappresenta ciò che è stato indicato precedentemente:

<StackPanel Grid.Row="0" Margin="12,17,0,28">

<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock Text="Search Page" Margin="9,-7,0,0" Style="{StaticResource

PhoneTextTitle1Style}"/>

</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="10,0,14,0">

<TextBox x:Name="textBox" Background="White" HorizontalAlignment="Left"

Height="72" Margin="10,10,-10,0" TextWrapping="Wrap" Text="Inserisci la parola da cercare"

VerticalAlignment="Top" Width="456"/>

<Button x:Name="button" Content="Button" HorizontalAlignment="Left"

Margin="166,99,0,0" VerticalAlignment="Top" RenderTransformOrigin="-4.704,-0.514"

Click="button_Click"/>

<TextBox x:Name="textBox1" Background="Black" HorizontalAlignment="Left"

Height="431" Margin="10,176,-10,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="456"/>

</Grid>

</Grid>

19

JumpList

L'importazione dei dati in questa pagina, avviene come per la FlatList. In questo caso però, viene

importato anche il campo Indirizzo che serve a linkare la posizione del file per poterlo quindi aprire.

La jumplist in realtà è una particolare lista che permette all'utente di "saltare" tra una lettera e

l'altra, in modo da poter scegliere l'iniziale dei nomi dei file che si vogliono cercare. E' scontato dire

che questa lista è molto utile nel caso di grandi quantità di documenti in cui il semplice scroll dello

schermo risulta poco produttivo.

La parte di interfaccia è simile alla FlatList. Verrà soltanto aggiunto un bottone che prelevando

l'indirizzo genera l'apertura del file, se premuto,

<HyperlinkButton Content="Clicca qui per aprire il file" NavigateUri="{Binding Indirizzo}"

TargetName="_blank" Margin="10,60,0,0"/>

e l’interfaccia “a gruppi” che è una proprietà del tipo DataTemplate ed è sufficiente definirla nello XAML.

<DataTemplate x:Key="GroupHeaderTemplate">

<Border Width="72"

Height="72"

HorizontalAlignment="Left"

Background="{StaticResource PhoneAccentBrush}">

<TextBlock Text="{Binding Title}"

FontSize="40"

Padding="6"

VerticalAlignment="Center"

HorizontalAlignment="Center" />

</Border>

</DataTemplate>

Così facendo, è possibile riprodurre l'aspetto della JumpList.

using System.Collections.Generic;

using System.Globalization;

using Microsoft.Phone.Globalization;

namespace LongListSelectorDemo

{

public class AlphaKeyGroup<T> : List<T>

{

public delegate string GetKeyDelegate(T item);

public string Key { get; private set; }

public AlphaKeyGroup(string key)

20

{

Key = key;

}

private static List<AlphaKeyGroup<T>> CreateGroups(SortedLocaleGrouping slg)

{

List<AlphaKeyGroup<T>> list = new List<AlphaKeyGroup<T>>();

foreach (string key in slg.GroupDisplayNames)

{

list.Add(new AlphaKeyGroup<T>(key));

}

return list;

}

public static List<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo

ci, GetKeyDelegate getKey, bool sort)

{

SortedLocaleGrouping slg = new SortedLocaleGrouping(ci);

List<AlphaKeyGroup<T>> list = CreateGroups(slg);

foreach (T item in items)

{

int index = 0;

if (slg.SupportsPhonetics)

{

//check if your database has yomi string for item

//if it does not, then do you want to generate Yomi or ask the user for

this item.

//index = slg.GetGroupIndex(getKey(Yomiof(item)));

}

else

{

index = slg.GetGroupIndex(getKey(item));

}

if (index >= 0 && index < list.Count)

{

list[index].Add(item);

}

}

if (sort)

{

foreach (AlphaKeyGroup<T> group in list)

{

21

group.Sort((c0, c1) => { return ci.CompareInfo.Compare(getKey(c0),

getKey(c1)); });

}

}

return list;

}

}

}

La situazione sarà quindi la seguente. Le caselle in azzurro sono quelle che "contengono" file, nel

senso che esiste almeno un file il quale nome inizia con quella lettera.

Il bottone "Clicca qui per aprire il file" cattura l'indirizzo del file e lo apre. L'applicazione stessa si

occupa di gestire il file in base all'estensione ed attraverso altre applicazioni esterne (es. file .doc

app Office), lo visualizza.

22

Conclusione

Dopo aver studiato ed utilizzato le tecnologie utili a costruire questo progetto, si possono delineare

i vantaggi e gli svantaggi.

Le filetable sono sicuramente uno strumento molto potente che ci permette di accedere a dati non

strutturati in modo molto semplice, e come detto in precedenza sono user friendly perché

permettono di utilizzare le solite funzioni di copia/incolla definite da Windows. Allo stesso tempo

però, con il fatto che alcuni dei campi non sono supportati da Visual Studio, si è dovuto creare una

seconda tabella, che, nel caso di database con grandi quantità di dati, rende lento l’accesso ai dati

che devono “passare” attraverso un trigger quando vengono aggiunti.

Si può concludere che le tecnologie che abbiamo utilizzato, sono sufficienti per gestire quantità di

dati limitati, appartenenti al singolo utente (che si suppone non siano in quantità esagerata).