Lag et Wallview for bilder med Silverlight Kode

Velkommen til den andre delen av å skape et iTunes-inspirert Wallview. I denne delen skal vi skrive hele koden i C # for de to UserControls som vi opprettet med Expression Blend i den forrige opplæringen.


Endelig resultatforhåndsvisning

Ta en titt på videodemoen til sluttresultatet vi skal jobbe for (eller bare sjekk ut den webbaserte demoen ovenfor):


Trinn 1: Åpne prosjektet

Åpne Visual Studio og klikk på "File"> "Open"> "Project / Solution" i menylinjen.

Deretter blar du til prosjektet vi opprettet i første del av denne opplæringen. Vi kalte det "WallviewApp".


Trinn 2: Åpne C # -dokumenter

På høyre side av Visual Studio er Solution Explorer som standard. Her kan du se alle filer fra prosjektet. Gå videre og åpne de to * .cs-filene "image.xaml.cs" og "wallview-img.xaml.cs" fra de to UserControls vi opprettet i den forrige opplæringen i Blend, samt "MainPage.xaml.cs" som ble levert automatisk.

Når du har åpnet disse tre filene, kan du se at alle tre klassene er ganske tomme.


Trinn 3: bilde klasse erklære variabler

La oss starte med å kode bildeklassen. Pass på at du for tiden redigerer filen "image.xaml.cs" og legger til følgende erklæringer rett over konstruktøren "offentlig bilde ()":

 offentlig bool valgt; privat dobbelt standardstørrelse; privat wallview_img wallview; privat SolidColorBrush colorDefault, colorSelected;

Trinn 4: Bildeklasse Skriv konstruktøren

Nå skal vi programmere konstruktøren som har to parametere: en BitmapImage og en String. Videre initialiseres de forrige deklarerte variablene, parametrene fra konstruktøren er tilordnet kilde til "img" og teksten til "imgName" Tekstblock. Vi registrerer også en eventhandler for MouseLeftButtonDown hendelsen av "img":

 offentlig bilde (BitmapImage src, String navn) // Kreves å initialisere variabler InitializeComponent (); valgt = false; defaultSize = 200; colorDefault = ny SolidColorBrush (Color.FromArgb (0x00, 0x76, 0xA2, 0xF9)); colorSelected = ny SolidColorBrush (Color.FromArgb (0xFF, 0x76, 0xA2, 0xF9)); this.img.Source = src; this.imgName.TextAlignment = TextAlignment.Center; this.imgName.Text = navn; this.imgDate.TextAlignment = TextAlignment.Center; this.img.MouseLeftButtonDown + = ny MouseButtonEventHandler (image_MouseLeftButtonDown); 

Parameteren BitmapImage er understreket med en rød farge fordi Visual Studio ikke finner navneområdet. For å fikse det klikker du bare på ordet BitmapImage og et lite blått rektangel skal vises under bokstaven B:

Når du beveger musen over det lille rektangel, vises en rullegardinmeny. Klikk på oppføringen "Bruke System.Windows.Media.Imaging;":

Nå visste Visual Studio at navneområdet, og den røde understreken forsvinner.


Trinn 5: Bilde Klassekode Noen Metoder

Like etter konstruktøren skal vi skrive et par metoder som vi trenger senere. Metodene er ganske selvbeskrivende fra metodens navn. image_MouseLeftButtonDown er hendelseshåndterer av MouseLeftButtonDown hendelse av "img" som vi registrerte i konstruktøren. Det kontrollerer i utgangspunktet hva som skjer når du klikker på bildet, avhengig av status (om det allerede er valgt eller ikke):

 Offentlig tomt settWallview (wallview_img wv) wallview = wv;  offentlig ugyldig endringSize (dobbel nyhetssending) 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;  privat tomt image_MouseLeftButtonDown (objekt sender, System.Windows.Input.MouseButtonEventArgs e) wallview.imageSelected = true; hvis (wallview.ctrlPressed == true) hvis (valgt == sann) unselectImage (); ellers selectImage ();  ellers wallview.unselectAllImages (); selectImage ();  e.Handled = true; 

Nå er vi ferdige med bildeklassen.

Ikke bekymre deg for de røde understrekkede delene i koden din. Disse variablene og metodene eksisterer ikke ennå, og derfor kjenner Visual Studio dem ikke, men vi kommer til å endre det snart.


Trinn 6: wallview-img Klasse erklære variabler

Siden vi er ferdige med bildeklassen, åpner du "wallview-img.xaml.cs" -dokumentet. Først skriv deklarasjoner av variabler rett over konstruktøren "public wallview_img ()":

 offentlig liste imageList; privat liste panellist; offentlig bool ctrlPressed, imageSelected; privat dobbel standardSize, changeSize;

Akkurat som før med BitmapImage Visual Studio vet ikke navneområdet for Liste. For å fikse dette, klikker du som en gang på en av lister, deretter på det blå rektangelet og velger "ved hjelp av System.Collections.Generic;" fra menyen:


Trinn 7: wallview-img Class Code the Constructor

Legg til følgende kode som initialiserer de tidligere deklarerte variablene, registrerer noen hendelser og deaktiverer knappene i navigeringsfeltet:

 offentlig wallview_img () // Kreves for å initialisere variabler InitializeComponent (); ctrlPressed = false; imageSelected = false; imageList = ny liste(); panelList = ny liste(); defaultSize = 200; changeSize = 1; // registrere alle hendelsene MouseLeftButtonUp + = ny MouseButtonEventHandler (wallviewMouseLeftButtonUp); SizeChanged + = ny SizeChangedEventHandler (resizeScrollViewer); KeyDown + = ny KeyEventHandler (keyDownEvent); KeyUp + = ny KeyEventHandler (keyUpEvent); this.slider.ValueChanged + = new RoutedPropertyChangedEventHandler(SliderValueChanged); // knapper vi ikke trenger ennå this.btnAllAlbums.IsEnabled = false; this.btnCurrentAlbum.IsEnabled = false; this.btnNext.IsEnabled = false; this.btnPrev.IsEnabled = false; 

Trinn 8: wallview-img Class Skriv metodene

Legg til følgende metoder under konstruktøren. Kommentaren før hver metode forklarer hva metoden gjør:

 // legger til et bilde i bildelisten og kaller resizeimages () som i utgangspunktet legger det til siste stabelpanel public void addImage (image img) img.imgName.Width = 200; img.setWallview (this); imageList.Add (img); resizeImages ();  // sletter hele tegnet innhold, hvert panel, albumliste og panellist public void clearLists () imageList.Clear (); foreach (StackPanel x i panelList) x.Children.Clear ();  this.content.Children.Clear (); panelList.Clear ();  // beregner hvor mange stackpaneler = rader er nødvendig offentlig tomt oppdateringPaneler () hvis (imageList.Count> 0) foreach (StackPanel sp i panellisten) sp.Children.Clear (); panelList.Clear (); double gridWidth = 0; hvis (this.content.ActualWidth == 0) gridWidth = 800; ellers 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; dobbeltforhold = gridvidde / (dobbelt) imageSize; int ratioInt = Convert.ToInt32 (forhold); hvis (ratioInt - ratio> 0) ratioInt - = 1; int newImageMargin = ((gridWidthInt - ratioInt * imageWidth) / ratioInt) / 2; dobbelt panelAmountDouble = (dobbelt) imageAmount / ratioInt; int panelAmountInt = (int) panelAmountDouble; if (panelAmountDouble - panelAmountInt> 0) panelAmountInt ++; hvis (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(); 

Trinn 9: Wallview-img Class Eventhandlers

I dette trinnet skriver vi de nødvendige hendelseshandlerne for hendelsene vi registrerte i konstruktøren tidligere:

 // eventhandler for når skyvekontrollen blir endret privat tomrom sliderValueChanged (objekt sender, System.Windows.RoutedPropertyChangedEventArgs e) changeImageSize (this.slider.Value);  // eventhandler som blir kalt når windowsize endrer private void resizeScrollViewer (objekt sender, System.Windows.SizeChangedEventArgs e) resizeImages ();  // eventhandler som fjerner alle bilder når du ikke klikker på et bilde, ugyldig wallviewMouseLeftButtonUp (objekt avsender, MouseButtonEventArgs e) hvis (! imageSelected) unselectAllImages (); ellers imageSelected = false;  // eventhandler for å trykke tastene private void keyDownEvent (objekt sender, System.Windows.Input.KeyEventArgs e) if (e.Key == Key.Ctrl) ctrlPressed = true; ellers hvis (e.Key == Key.A) hvis (ctrlPressed) selectAllImages ();  // eventhandler for utgivelse av nøkler private void keyUpEvent (objekt sender, System.Windows.Input.KeyEventArgs e) if (e.Key == Key.Ctrl) ctrlPressed = false; 

Nå er vi ferdige med wallview-img klasse. La oss fortsette med å skape en webservice som vi trenger for Hovedside klasse.


Trinn 10: Lag en webservice

Den webservice som vi skal skrive, gir oss i utgangspunktet bildene fra en bestemt mappe. For å opprette en webservice høyreklikker du på "WallviewApp.Web" i Solution Explorer på høyre side av Visual Studio, og velg "Add"> "New Item" fra menyen:

Fra popup-vinduet velg "Silverlight-aktivert WCF Service Visual C #" og skriv inn "WCF.svc" for et navn, og klikk deretter "Legg til":

Som du kan se fikk vi en annen klasse som heter WCF med eget kodedokument, "WCF.svc.cs".


Trinn 11: WCF Klasse Kode To Metoder

Legg til følgende to metoder i WCF-klassen rett under linjen som sier "// Legg til flere operasjoner her og merk dem med [OperationContract]":

 // metode for å få alle filnavnene i en mappe [OperationContract] offentlig streng [] getFileNames (String dir) prøv String tmp = HttpContext.Current.Request.MapPath (dir); returner Directory.GetFiles (@tmp, "* .jpg");  fangst (unntak) return null;  // metode som returnerer datoen for opprettelsen av en fil eller mappe [OperationContract] offentlig String getFileDates (Stringfil, int i) return i.ToString () + "-" + File.GetLastWriteTime (fil) .ToString ); 

Løs de manglende navneområdene som vi gjorde tidligere ved å klikke på de berørte navnene, deretter på det blå rektangelet og på "importer ..." eller ved å legge disse to linjene manuelt øverst i dokumentet:

 bruker System.Web; bruker System.IO;

Trinn 12: Service Referanse Del 1

For å kunne bruke webservice må vi legge til et servicereferanse til hovedprosjektet. Før vi kan gjøre dette, må vi bygge prosjektet en gang. Klikk derfor på "Bygg" fra menyen øverst i Visual Studio og deretter på "Build WallviewApp":


Trinn 13: Service Referanse Del 2

Etter at bygningen lykkes, høyreklikker du på "WallviewApp" på høyre side i Solution Explorer og velger "Add Service Reference" fra menyen:


Trinn 14: Service Referanse Del 3

I kommende popup klikker du på knappen "Discover" og skriver inn "WCFRef" i feltet Namespace, og klikker deretter "OK":

Uten å bygge prosjektet før du prøver å legge til et servicereferanse, har du fått denne feilmeldingen:


Trinn 15: MainPage Class Erklære variabler

Åpne filen "MainPage.xaml.cs" og legg til følgende linjer med kode over konstruktøren "offentlig MainPage ()":

 privat WCFRef.WCFClient klient; privat streng imagedir = "/ image /"; offentlig wallview_img wvi; private int amountImages;

Trinn 16: MainPage Class Programmer Konstruktøren

Konstruktøren av Hovedside ser slik ut. Vi initialiserer deklarasjonene fra forrige trinn, registrerer webserviceens eventhandlers og legger til wallview_img kalt "wvi" til Nett "LayoutRoot" av Hovedside:

 offentlig MainPage () InitializeComponent (); amountImages = 0; klient = ny WallviewApp.WCFRef.WCFClient (); client.getFileNamesCompleted + = new EventHandler(Client_getFileNamesCompleted); client.getFileNamesAsync (imagedir); client.getFileDatesCompleted + = ny EventHandler(Client_getFileDatesCompleted); wvi = ny wallview_img (); this.LayoutRoot.Children.Add (wvi); 

Trinn 17: Kode Eventhandlers for Webservice

Legg til følgende to eventhandlers og metoden under konstruktøren til hovedsiden.

"client_getFileNamesCompleted ()"får en rekke strenger som blir returnert av webservice. Arrayet konverteres til separate strenger hvor filnavnet er hentet ut.

Bruker lokal vert adresse, porten, bildekatalogen og filnavnet, bygger vi en Uri kalt "src". At Uri brukes til å opprette en ny BitmapImage "bmi" som trengs for å lage et nytt bilde "tmp". Bildet "tmp" blir så lagt til wallview_img "WMI".

Etterpå blir metoden som returnerer opprettelsesdatoen til en fil, kalt sammen med et tellernummer. Uansett hvilken metode som returneres blir behandlet av handleren "client_getFileDatesCompleted ()". Siden en streng i formatet > 2-18.02.2009 12:32:23 returneres fra webservice, vi må dele opp talltallet i begynnelsen og datoen i midten.

Når denne prosedyren er fullført, ser sluttdato ut > 18.02.2009 og er tildelt til Textblock "imgDate" av det tilsvarende bildet.

 // event handler for å få filnavnene fra mappen privat void client_getFileNamesCompleted (objekt sender, WallviewApp.WCFRef.getFileNamesCompletedEventArgs e) if (e.Result! = null) foreach (streng s i e.Result) int pos = s.LastIndexOf ( "\\"); streng filnavn = s.Substring (pos + 1); int port = Application.Current.Host.Source.Port; Uri src = ny Uri ("http: // localhost:" + port + image + filnavn); BitmapImage bmi = ny BitmapImage (src); bilde tmp = nytt bilde (bmi, filnavn); this.wvi.addImage (TMP); amountImages ++; getFileDate (s, amountImages - 1);  else MessageBox.Show ("returnerte null i filer som er fullført");  // metode som kaller webservice asynk med en filsporstreng og et tall slik at vi kan anrope datoen for returnert dato til et bestemt bilde igjen privat void getFileDate (String s, int i) this.client.getFileDatesAsync (s, jeg );  // hendelseshåndterer for å få filedates private void client_getFileDatesCompleted (objekt sender, 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 ("")); hvis (nummer < 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");  

Som i andre kildefiler kan ikke navneområdet "BitmapImage" hittes. For å reparere dette klikker du på det blå rektangelet og importerer det etter at du klikket på teksten til BitmapImage, eller legg til følgende linje øverst i dokumentet manuelt:

 bruker System.Windows.Media.Imaging;

Trinn 18: Kjør prosjektet

Gå videre og utfør prosjektet for å se om alt fungerer. Du kan gjøre dette ved å trykke på "F5" på tastaturet, ved å klikke på knappen med et typisk "Spill" -ikon under menyen øverst på ikonlinjen, eller ved å velge oppføringen "Start debugging" i "Debug" undermeny fra menyen øverst i Visual Studio:

Nettleseren din åpnes, og du får denne feilmeldingen:

Hva er problemet?

Vi fortalte webservice å sjekke mappen "http: // localhost: port / image /" for * .jpg-filer og åpenbart ikke den mappen eller noen bilder i den mappen ennå.


Trinn 19: Klargjør bildemappen

Naviger til prosjektkatalogen med Windows Utforsker. For meg er det følgende sti:

Åpne mappen "WallviewApp.Web" og opprett en ny mappe som heter "image" innsiden av den.

Åpne nå mappen "image" og lim inn noen * .jpg-bilder i den.


Trinn 20: Kjør prosjektet igjen

Når du har lagt inn et par bilder i bildemappen, trykker du på oppdateringen i webleseren din (hvis den fortsatt er åpen) eller bare kjør prosjektet igjen ved å trykke på "F5" -tasten i Visual Studio. Som et resultat bør du se vår endelige Wallview:

Du kan påvirke størrelsen på de viste bildene med glidebryteren i navigeringsfeltet.


Konklusjon

Vi er ferdige for nå med denne opplæringen, og jeg håper du likte det og lærte noe også.

Den omtrentlige totale tiden det tok meg å utvikle dette fra bunnen av, var omtrent 20 timer. Wallview for album som du kan se i videoen nedenfor tok meg ca 15 timer og ytterligere 10 timer å kombinere begge wallview typer.

Du kan spørre deg selv hva poenget med å kunne velge ett eller flere bilder er. For øyeblikket er funksjonaliteten ubrukelig, men jeg kan tenke meg å legge til muligheten til å starte en lysbildefremvisning eller opprette en spilleliste fra de valgte bildene for eksempel. Og hvis du lurer på hvorfor vi la til knappene "All Albums", "Current Album", "<" and ">"i navigeringslinjen, men aldri brukt dem ...

Jeg har til hensikt å utvikle en annen opplæring som automatisk genererer fotoalbum basert på filnavnene til bildene. Selvfølgelig vil opplæringen utvide prosjektet fra opplæringen du nettopp har fullført her. Jeg vil definitivt gjerne gjøre det hvis det er populært blant publikum. For å få et inntrykk av hva wallview for bilder som vi nettopp opprettet ville se ut i kombinasjon med en wallview for fotoalbum, ta en titt på følgende video:

For eventuelle kommentarer, forslag eller bekymringer, vennligst la et notat i kommentarseksjonen. Takk for at du leste!