Benvenuti alla seconda parte della creazione di un Wallview ispirato a iTunes. In questa parte scriveremo l'intero codice in C # per i due UserControls che abbiamo creato con Expression Blend nel precedente tutorial.
Dai un altro sguardo alla demo video del risultato finale a cui stiamo lavorando (oppure guarda la demo basata sul web qui sopra):
Apri Visual Studio e fai clic su "File"> "Apri"> "Progetto / Soluzione" nella barra dei menu.
Quindi vai al progetto che abbiamo creato nella prima parte di questo tutorial. L'abbiamo chiamato "WallviewApp".
Sul lato destro di Visual Studio è l'Esplora soluzioni per impostazione predefinita. Qui puoi vedere tutti i file del progetto. Vai avanti e apri i due file * .cs "image.xaml.cs" e "wallview-img.xaml.cs" dai due UserControls che abbiamo creato nel precedente tutorial di Blend e da "MainPage.xaml.cs" che è stato fornito automaticamente.
Una volta che hai aperto questi tre file puoi vedere che tutte e tre le classi sono praticamente vuote.
Iniziamo con la codifica della classe dell'immagine. Assicurati di modificare il file "image.xaml.cs" e aggiungi le seguenti dichiarazioni subito sopra il costruttore "public image ()":
bool pubblico selezionato; private double defaultSize; wallview privato wallview_img; private SolidColorBrush colorDefault, colorSelected;
Ora andremo a programmare il costruttore che ha due parametri: un BitmapImage e un String. Inoltre, le precedenti variabili dichiarate vengono inizializzate, i parametri del costruttore sono assegnati alla sorgente di "img" e il testo del blocco di testo "imgName". Registriamo anche un eventhandler per l'evento MouseLeftButtonDown di "img":
immagine pubblica (BitmapImage src, String name) // Richiesto per inizializzare le variabili InitializeComponent (); selezionato = falso; defaultSize = 200; colorDefault = new SolidColorBrush (Color.FromArgb (0x00, 0x76, 0xA2, 0xF9)); colorSelected = new SolidColorBrush (Color.FromArgb (0xFF, 0x76, 0xA2, 0xF9)); this.img.Source = src; this.imgName.TextAlignment = TextAlignment.Center; this.imgName.Text = nome; this.imgDate.TextAlignment = TextAlignment.Center; this.img.MouseLeftButtonDown + = new MouseButtonEventHandler (image_MouseLeftButtonDown);
Il parametro BitmapImage è sottolineato con un colore rosso perché Visual Studio non riesce a trovare lo spazio dei nomi. Per risolvere il problema basta fare clic sulla parola BitmapImage e un piccolo rettangolo blu dovrebbe apparire sotto la lettera B:
Quando sposti il mouse sul piccolo rettangolo apparirà un menu a discesa. Fare clic sulla voce "Utilizzo di System.Windows.Media.Imaging;":
Ora Visual Studio conosce lo spazio dei nomi e la sottolineatura rossa scomparirà.
Subito dopo il costruttore scriveremo un paio di metodi di cui avremo bisogno in seguito. I metodi sono piuttosto auto-descrittivi dai loro nomi di metodi. image_MouseLeftButtonDown
è il gestore di eventi del MouseLeftButtonDown
evento della "img" che abbiamo registrato nel costruttore. In pratica controlla ciò che accade quando fai clic sull'immagine, a seconda del suo stato (se è già selezionato o meno):
public void setWallview (wallview_img wv) wallview = wv; public void changeSize (double newsize) this.imgName.Width = defaultSize * newsize; this.imgSize.Width = defaultSize * newsize; this.imgSize.Height = defaultSize * newsize; public void unselectImage () selected = false; this.imgBorder.BorderBrush = colorDefault; public void selectImage () selected = true; this.imgBorder.BorderBrush = colorSelected; private void image_MouseLeftButtonDown (mittente dell'oggetto, System.Windows.Input.MouseButtonEventArgs e) wallview.imageSelected = true; if (wallview.ctrlPressed == true) if (selected == true) unselectImage (); else selectImage (); else wallview.unselectAllImages (); selectImage (); e.Handled = true;
Ora abbiamo finito con la classe dell'immagine.
Non preoccuparti delle parti sottolineate in rosso nel tuo codice. Queste variabili e metodi non esistono ancora ed è per questo che Visual Studio non li conosce, ma lo cambieremo presto.
Dato che abbiamo finito con la classe immagine, apri il documento "wallview-img.xaml.cs". Inizialmente scrivi le dichiarazioni delle variabili proprio sopra il costruttore "public wallview_img ()":
lista pubblicaimageList; Elenco privato panellist; public bool ctrlPremuto, imageSelected; private double defaultSize, changeSize;
Proprio come prima con BitmapImage Visual Studio non conosce lo spazio dei nomi di Elenco
. Per risolvere questo problema, come prima, fai clic su uno degli elenchi, quindi sul rettangolo blu e seleziona "using System.Collections.Generic;" dal menu:
Aggiungi il seguente codice che inizializza le variabili dichiarate in precedenza, registra alcuni eventi e disabilita i pulsanti nella barra di navigazione:
public wallview_img () // Richiesto per inizializzare le variabili InitializeComponent (); ctrlPressed = false; imageSelected = false; imageList = nuova lista(); panelList = nuova lista (); defaultSize = 200; changeSize = 1; // registrazione di tutti gli eventi MouseLeftButtonUp + = new MouseButtonEventHandler (wallviewMouseLeftButtonUp); SizeChanged + = new SizeChangedEventHandler (resizeScrollViewer); KeyDown + = new KeyEventHandler (keyDownEvent); KeyUp + = new KeyEventHandler (keyUpEvent); this.slider.ValueChanged + = new RoutedPropertyChangedEventHandler (SliderValueChanged); // pulsanti non abbiamo ancora bisogno this.btnAllAlbums.IsEnabled = false; this.btnCurrentAlbum.IsEnabled = false; this.btnNext.IsEnabled = false; this.btnPrev.IsEnabled = false;
Aggiungi i seguenti metodi sotto il costruttore. Il commento prima di ogni metodo spiega cosa sta facendo il metodo:
// aggiunge un'immagine all'istantelista e chiama resizeimages () che in pratica lo aggiunge all'ultimo vuoto stackid addizione (image img) img.imgName.Width = 200; img.setWallview (questo); imageList.Add (img); resizeImages (); // cancella l'intero contenuto disegnato, ogni pannello, lista album e elenco pubblico vuoto clearLists () imageList.Clear (); foreach (StackPanel x in panelList) x.Children.Clear (); this.content.Children.Clear (); panelList.Clear (); // calcola il numero di stackpanel = le righe sono necessarie public void updatePanels () if (imageList.Count> 0) foreach (StackPanel sp in panelList) sp.Children.Clear (); panelList.Clear (); double gridWidth = 0; if (this.content.ActualWidth == 0) gridWidth = 800; else gridWidth = this.content.ActualWidth; int gridWidthInt = Convert.ToInt32 (gridWidth); int imageAmount = imageList.Count; int imageMargin = 10; int imageWidth = Convert.ToInt32 (defaultSize * changeSize); int imageSize = imageWidth + 2 * imageMargin; double ratio = gridWidth / (double) imageSize; int ratioInt = Convert.ToInt32 (rapporto); if (ratioInt - ratio> 0) ratioInt - = 1; int newImageMargin = ((gridWidthInt - ratioInt * imageWidth) / ratioInt) / 2; double panelAmountDouble = (double) imageAmount / ratioInt; int panelAmountInt = (int) panelAmountDouble; if (panelAmountDouble - panelAmountInt> 0) panelAmountInt ++; if (panelAmountInt < 1) panelAmountInt = 1; int x = 0; for (int i = 0; i < panelAmountInt; i++) StackPanel panel = new StackPanel(); panel.Orientation = Orientation.Horizontal; panel.Margin = new Thickness(0, 5, 0, 0); for (int j = 0; j < ratioInt; j++) if (x < imageAmount) imageList[x].Margin = new Thickness(newImageMargin, 0, newImageMargin, 10); imageList[x].changeSize(changeSize); imageList[x].setWallview(this); panel.Children.Add(imageList[x]); x++; panelList.Add(panel); //selects all images, gets called when ctrl + a is pressed public void selectAllImages() foreach (image i in imageList) i.selectImage(); //unselects all iamges public void unselectAllImages() foreach (image i in imageList) i.unselectImage(); //gets called when the slider value changes private void resizeImages() updatePanels(); this.content.Children.Clear(); foreach (StackPanel sp in panelList) this.content.Children.Add(sp); //method gets called by the slidervaluechanged event public void changeImageSize(double newsize) changeSize = newsize; resizeImages();
In questo passaggio scriviamo i gestori di eventi necessari per gli eventi che abbiamo registrato nel costruttore in precedenza:
// eventhandler per quando il cursore viene modificato privato void sliderValueChanged (mittente dell'oggetto, System.Windows.RoutedPropertyChangedEventArgse) changeImageSize (this.slider.Value); // gestore di eventi che viene chiamato quando il windowsize cambia private void resizeScrollViewer (mittente dell'oggetto, System.Windows.SizeChangedEventArgs e) resizeImages (); // gestore di eventi che deseleziona tutte le immagini quando non si fa clic su un'immagine void wallviewMouseLeftButtonUp (mittente dell'oggetto, MouseButtonEventArgs e) if (! imageSelected) unselectAllImages (); else imageSelected = false; // gestore di eventi per la pressione di chiavi private void keyDownEvent (mittente dell'oggetto, System.Windows.Input.KeyEventArgs e) if (e.Key == Key.Ctrl) ctrlPressed = true; else if (e.Key == Key.A) if (ctrlPressed) selectAllImages (); // gestore di eventi per il rilascio di chiavi private void keyUpEvent (mittente dell'oggetto, System.Windows.Input.KeyEventArgs e) if (e.Key == Key.Ctrl) ctrlPressed = false;
Ora abbiamo finito con wallview-img
classe. Continuiamo con la creazione di un servizio web di cui avremo bisogno per il Pagina principale
classe.
Il servizio web che stiamo per scrivere ci fornisce fondamentalmente le immagini da una determinata cartella. Per creare un servizio web, fai clic con il pulsante destro del mouse su "WallviewApp.Web" in Esplora soluzioni sul lato destro di Visual Studio e seleziona "Aggiungi"> "Nuovo elemento" dal menu:
Dal popup seleziona "Visual C # di servizio Silverlight abilitato per Silverlight" e inserisci "WCF.svc" per un nome, quindi fai clic su "Aggiungi":
Come puoi vedere, abbiamo ottenuto un'altra classe chiamata WCF con un proprio documento di codice, "WCF.svc.cs".
Aggiungi i seguenti due metodi nella classe WCF proprio sotto la riga che dice "// Aggiungi più operazioni qui e contrassegnale con [OperationContract]
":
// metodo per ottenere tutti i nomi dei file all'interno di una cartella [OperationContract] public string [] getFileNames (String dir) try String tmp = HttpContext.Current.Request.MapPath (dir); return Directory.GetFiles (@tmp, "* .jpg"); catch (Exception) return null; // metodo che restituisce la data di creazione di un file o una cartella [OperationContract] public String getFileDates (String file, int i) return i.ToString () + "-" + File.GetLastWriteTime (file) .ToString ( );
Risolvi gli spazi dei nomi mancanti come fatto in precedenza facendo clic sui nomi interessati, quindi sul rettangolo blu e su "import ..." o aggiungendo manualmente queste due righe nella parte superiore del documento:
usando System.Web; using System.IO;
Per poter utilizzare il servizio web è necessario aggiungere un riferimento al servizio al progetto principale. Prima di poterlo fare con successo, dobbiamo costruire il progetto una volta. Quindi fai clic su "Build" dal menu nella parte superiore di Visual Studio e, successivamente, su "Build WallviewApp":
Al termine della creazione, fai clic con il pulsante destro del mouse su "WallviewApp" sul lato destro in Esplora soluzioni e seleziona "Aggiungi riferimento servizio" dal menu:
Nel prossimo popup fai clic sul pulsante "Scopri" e inserisci "WCFRef" nel campo Namespace, quindi fai clic su "OK":
Senza costruire il progetto prima di provare ad aggiungere un riferimento al servizio, avresti ricevuto questo messaggio di errore:
Aprire il file "MainPage.xaml.cs" e aggiungere le seguenti righe di codice sopra il costruttore "public MainPage ()
":
client WCFRef.WCFClient privato; private string imagedir = "/ image /"; public wallview_img wvi; private int amountImages;
Il costruttore del Pagina principale
Somiglia a questo. Inizializziamo le dichiarazioni del passaggio precedente, registriamo gli eventenerator del webservice e aggiungiamo il wallview_img
di nome "WVI
" al Griglia
"LayoutRoot
"del Pagina principale
:
public MainPage () InitializeComponent (); amountImages = 0; client = new WallviewApp.WCFRef.WCFClient (); client.getFileNamesCompleted + = new EventHandler(Client_getFileNamesCompleted); client.getFileNamesAsync (imagedir); client.getFileDatesCompleted + = new EventHandler (Client_getFileDatesCompleted); wvi = new wallview_img (); this.LayoutRoot.Children.Add (WVI);
Aggiungi i seguenti due gestori di eventi e il metodo sotto il costruttore di MainPage.
Il "client_getFileNamesCompleted ()
"ottiene una serie di stringhe che vengono restituite dal servizio Web. L'array viene convertito in stringhe separate da cui viene estratto il nome del file.
Usando il localhost
indirizzo, porta, directory immagine e nome file, noi costruiamo a Uri
chiamato "src". Quello Uri
è usato per creare un nuovo BitmapImage
"bmi" che è necessario per creare una nuova immagine "tmp". L'immagine "tmp" viene quindi aggiunta al wallview_img
"Wmi".
Successivamente, il metodo che restituisce la data di creazione di un file viene chiamato insieme a un numero di contatore. Qualsiasi cosa restituisca il metodo viene elaborato dal gestore "client_getFileDatesCompleted ()". Dal momento che una stringa nel formato > 2-18.02.2009 12:32:23 viene restituito dal servizio web, dobbiamo dividere il numero del contatore all'inizio e la data nel mezzo.
Quando questa procedura è completata, appare la data finale > 18.02.2009 ed è assegnato al
TextBlock
"imgDate" dell'immagine corrispondente.
// gestore di eventi per ottenere i nomi file dalla cartella private void client_getFileNamesCompleted (mittente dell'oggetto, WallviewApp.WCFRef.getFileNamesCompletedEventArgs e) if (e.Result! = null) foreach (stringa s in e.Result) int pos = s.LastIndexOf ( "\\"); string filename = s.Substring (pos + 1); int port = Application.Current.Host.Source.Port; Uri src = new Uri ("http: // localhost:" + port + imagedir + filename); BitmapImage bmi = new BitmapImage (src); immagine tmp = nuova immagine (bmi, nome file); this.wvi.addImage (TMP); amountImages ++; getFileDate (s, amountImages - 1); else MessageBox.Show ("restituito null nei file completati"); // metodo che chiama il servizio web asynch con una stringa filepath e un numero in modo che possiamo riassociare la stringa data restituita a una determinata immagine di nuovo privato getFileDate (String s, int i) this.client.getFileDatesAsync (s, i ); // gestore di eventi per ottenere il file privato privato client_getFileDatesCompleted (mittente dell'oggetto, WallviewApp.WCFRef.getFileDatesCompletedEventArgs e) if (e.Result! = null) String dt = e.Result; int number = Convert.ToInt32 (dt.Remove (dt.LastIndexOf ("-"))); String date = dt.Remove (dt.LastIndexOf ("")); se (numero < 10) date = date.Remove(0, 2); else if (number < 100) date = date.Remove(0, 3); else date = date.Remove(0, 4); this.wvi.imageList[number].imgDate.Text = date; else MessageBox.Show("returned null in dates completed");
Come negli altri file sorgenti, non è possibile trovare lo spazio dei nomi "BitmapImage". Per riparare questo fare clic sul rettangolo blu e importarlo dopo aver cliccato nel testo di BitmapImage
, oppure aggiungi manualmente la seguente riga all'inizio del documento:
using System.Windows.Media.Imaging;
Vai avanti ed esegui il progetto per vedere se tutto funziona. Puoi farlo premendo "F5" sulla tastiera, facendo clic sul pulsante con la tipica icona "Gioca" sotto il menu in alto nella barra delle icone, o selezionando la voce "Avvia debug" all'interno del "Debug" sottomenu dal menu nella parte superiore di Visual Studio:
Il tuo browser si apre e riceverai questo messaggio di errore:
Qual è il problema?
Abbiamo detto al webservice di controllare la cartella "http: // localhost: port / image /" per i file * .jpg e ovviamente né quella cartella né alcuna immagine in quella cartella esistono ancora.
Passare alla directory del progetto con Windows Explorer. Per me è il seguente percorso:
Apri la cartella "WallviewApp.Web" e crea una nuova cartella chiamata "immagine" al suo interno.
Ora apri la cartella "immagine" e incolla alcune immagini * .jpg.
Una volta che hai inserito un paio di immagini all'interno della cartella immagine, premi Aggiorna nel browser (se è ancora aperto) o semplicemente esegui nuovamente il progetto premendo il tasto "F5" in Visual Studio. Di conseguenza dovresti vedere il nostro Wallview finale:
È possibile influenzare la dimensione delle immagini visualizzate con il cursore nella barra di navigazione.
Per ora abbiamo finito con questo tutorial e spero che vi sia piaciuto e abbia imparato qualcosa.
Il tempo totale approssimativo che ho impiegato per sviluppare questo da zero era di circa 20 ore. La wallview per gli album che puoi vedere nel video qui sotto mi ha richiesto circa 15 ore e altre 10 ore per combinare entrambi i tipi di wallview.
Potresti chiederti quale sia il punto di essere in grado di selezionare una o più immagini. In questo momento la funzionalità è inutile ma potrei immaginare di aggiungere la possibilità di avviare una presentazione o creare una playlist dalle immagini selezionate, ad esempio. E se ti stai chiedendo perché abbiamo aggiunto i pulsanti "Tutti gli album", "Album corrente", "<" and ">"nella barra di navigazione ma non li ho mai usati ...
La mia intenzione è quella di sviluppare un altro tutorial che generi automaticamente album di foto basati sui nomi di file delle immagini. Ovviamente il tutorial estenderà il progetto dal tutorial che hai appena completato qui. Mi piacerebbe sicuramente farlo se è popolare tra il pubblico. Per avere un'idea di come apparirà la wallview per le immagini che abbiamo appena creato in combinazione con una wallview per gli album fotografici, dai un'occhiata al seguente video:
Per eventuali commenti, suggerimenti o dubbi, si prega di lasciare una nota nella sezione commenti. Grazie per aver letto!