Maak een Wallview voor afbeeldingen met Silverlight Code

Welkom bij het tweede deel van het maken van een op iTunes geïnspireerde Wallview. In dit deel gaan we de hele code in C # schrijven voor de twee UserControls die we met Expression Blend hebben gemaakt in de vorige tutorial.


Eindresultaat voorbeeld

Kijk nog eens naar de videodemo van het eindresultaat waar we naartoe zullen werken (of bekijk de webgebaseerde demo hierboven):


Stap 1: Open het project

Open Visual Studio en klik op "Bestand"> "Openen"> "Project / Oplossing" in de menubalk.

Blader vervolgens naar het project dat we in het eerste deel van deze tutorial hebben gemaakt. We noemden het "WallviewApp".


Stap 2: Open de C # -documenten

Aan de rechterkant van Visual Studio bevindt zich standaard de Solution Explorer. Hier kunt u elk bestand van het project bekijken. Ga je gang en open de twee * .cs-bestanden "image.xaml.cs" en "wallview-img.xaml.cs" van de twee UserControls die we in de vorige zelfstudie in Blend hebben gemaakt, evenals de "MainPage.xaml.cs" die automatisch werd verstrekt.

Nadat je deze drie bestanden hebt geopend, kun je zien dat alle drie de klassen vrij leeg zijn.


Stap 3: image Class Declare Variables

Laten we beginnen met het coderen van de afbeeldingklasse. Zorg ervoor dat u momenteel het bestand "image.xaml.cs" bewerkt en voeg de volgende verklaringen toe recht boven de constructor "public image ()":

 openbare bool geselecteerd; privé dubbele defaultSize; privé wallview_img wallview; private SolidColorBrush-kleurDefault, colorSelected;

Stap 4: image Class Schrijf de Constructor

Nu gaan we de constructor programmeren die twee parameters heeft: een BitmapImage en een String. Verder worden de vorige gedeclareerde variabelen geïnitialiseerd, worden de parameters van de constructor toegewezen aan de bron van de "img" en de tekst van het "imgName" Textblock. We registreren ook een eventhandler voor de gebeurtenis MouseLeftButtonDown van de "img":

 public image (BitmapImage src, String-naam) // Vereist om variabelen te initialiseren InitializeComponent (); selected = false; defaultSize = 200; colorDefault = new SolidColorBrush (Color.FromArgb (0x00, 0x76, 0xA2, 0xF9)); colorSelected = new SolidColorBrush (Color.FromArgb (0xFF, 0x76, 0xA2, 0xF9)); this.img.Bron = src; this.imgName.TextAlignment = TextAlignment.Center; this.imgName.Text = naam; this.imgDate.TextAlignment = TextAlignment.Center; this.img.MouseLeftButtonDown + = nieuwe MouseButtonEventHandler (image_MouseLeftButtonDown); 

De parameter BitmapImage is onderstreept met een rode kleur omdat Visual Studio de naamruimte niet kan vinden. Om dat te corrigeren, klik je op het woord BitmapImage en een kleine blauwe rechthoek zou onder de letter B moeten verschijnen:

Wanneer u met uw muis over de kleine rechthoek beweegt, verschijnt een vervolgkeuzemenu. Klik op het item "Using System.Windows.Media.Imaging;":

Nu weet Visual Studio die naamruimte en de rode onderstreping verdwijnt.


Stap 5: image Class Code Enkele methoden

Vlak na de constructor gaan we een aantal methoden schrijven die we later nodig zullen hebben. De methoden zijn vrij zelfbeschrijvend van hun methode namen. image_MouseLeftButtonDown is de gebeurtenishandler van de MouseLeftButtonDown gebeurtenis van de "img" die we hebben geregistreerd in de constructor. Het bepaalt in feite wat er gebeurt als u op de afbeelding klikt, afhankelijk van de status (of deze al is geselecteerd of niet):

 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 (object afzender, System.Windows.Input.MouseButtonEventArgs e) wallview.imageSelected = true; if (wallview.ctrlPressed == true) if (selected == true) unselectImage (); else selectImage ();  else wallview.unselectAllImages (); selecteer foto();  e.Handled = true; 

Nu zijn we klaar met de beeldklasse.

Maak je geen zorgen over de rode onderstreepte delen in je code. Deze variabelen en methoden bestaan ​​nog niet en daarom kent Visual Studio ze niet, maar dat gaan we binnenkort veranderen.


Stap 6: wallview-img Class Declare Variables

Omdat we klaar zijn met de afbeeldingsklasse, opent u het document "wallview-img.xaml.cs". Schrijf eerst de verklaringen van variabelen recht boven de constructor "public wallview_img ()":

 openbare lijst ImageList; privélijst panellid; public bool ctrlPressed, imageSelected; private double defaultSize, changeSize;

Net als voorheen met de BitmapImage Visual Studio kent de namespace niet van Lijst. Om dit op te lossen, klikt u zoals eerder op een van de lijsten en vervolgens op de blauwe rechthoek en selecteert u 'using System.Collections.Generic;' uit het menu:


Stap 7: wallview-img Class Code de Constructor

Voeg de volgende code toe die de eerder gedeclareerde variabelen initialiseert, sommige gebeurtenissen registreert en de knoppen in de navigatiebalk uitschakelt:

 public wallview_img () // Vereist om variabelen te initialiseren InitializeComponent (); ctrlPressed = false; imageSelected = false; imageList = nieuwe lijst(); panelList = new List(); defaultSize = 200; changeSize = 1; // registratie van alle gebeurtenissen MouseLeftButtonUp + = nieuwe MouseButtonEventHandler (wallviewMouseLeftButtonUp); SizeChanged + = new SizeChangedEventHandler (resizeScrollViewer); KeyDown + = nieuwe KeyEventHandler (keyDownEvent); KeyUp + = nieuwe KeyEventHandler (keyUpEvent); this.slider.ValueChanged + = nieuwe RoutedProperty ChangedEventHandler(SliderValueChanged); // knoppen die we nog niet nodig hebben this.btnAllAlbums.IsEnabled = false; this.btnCurrentAlbum.IsEnabled = false; this.btnNext.IsEnabled = false; this.btnPrev.IsEnabled = false; 

Stap 8: wallview-img Class Write the Methods

Voeg de volgende methoden toe onder de constructor. De opmerking voor elke methode legt uit wat de methode doet:

 // voegt een afbeelding toe aan de imagelist en roept resizeimages () aan die het in principe toevoegt aan de laatste stackpanel openbare ongeldige addImage (afbeelding img) img.imgName.Width = 200; img.setWallview (deze); imageList.Add (img); resizeImages ();  // wist de gehele getekende inhoud, elk paneel, elke albumlijst en elke panellid public clear clear () imageList.Clear (); foreach (StackPanel x in panelList) x.Children.Clear ();  this.content.Children.Clear (); panelList.Clear ();  // berekent hoeveel stackpanels = rijen nodig zijn public void updatePanels () if (imageList.Count> 0) foreach (StackPanel sp in panelList) sp.Children.Clear (); panelList.Clear (); dubbele 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; dubbele ratio = gridWidth / (double) imageSize; int ratioInt = Convert.ToInt32 (ratio); 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(); 

Stap 9: wallview-img Klasse Eventhandlers

In deze stap schrijven we de benodigde gebeurtenishandlers voor de gebeurtenissen die we eerder in de constructor hebben geregistreerd:

 // eventhandler voor wanneer de schuifregelaar wordt gewijzigd private void sliderValueChanged (object afzender, System.Windows.RoutedPropertyChangedEventArgs e) changeImageSize (this.slider.Value);  // eventhandler die wordt aangeroepen wanneer de Windows-wijziging privé-ongeldigheid wijzigt resizeScrollViewer (object afzender, System.Windows.SizeChangedEventArgs e) resizeImages ();  // eventhandler die de selectie van alle afbeeldingen ongedaan maakt als u niet op een afbeelding klikt die leeg is wallviewMouseLeftButtonUp (object afzender, MouseButtonEventArgs e) if (! imageSelected) unselectAllImages (); else imageSelected = false;  // eventhandler voor het indrukken van toetsen private void keyDownEvent (object afzender, System.Windows.Input.KeyEventArgs e) if (e.Key == Key.Ctrl) ctrlPressed = true; else if (e.Key == Key.A) if (ctrlPressed) selectAllImages ();  // eventhandler voor het vrijgeven van sleutels private void keyUpEvent (object afzender, System.Windows.Input.KeyEventArgs e) if (e.Key == Key.Ctrl) ctrlPressed = false; 

Nu zijn we klaar met de wallview-img klasse. Laten we doorgaan met het maken van een webservice die we nodig zullen hebben voor de Hoofdpagina klasse.


Stap 10: Maak een webservice

De webservice die we gaan schrijven, levert ons in principe de beelden van een bepaalde map. Om een ​​webservice te maken klikt u met de rechtermuisknop op "WallviewApp.Web" in de Solution Explorer aan de rechterkant van Visual Studio en selecteert u "Toevoegen"> "Nieuw item" in het menu:

Selecteer in de pop-up "Silverlight-enabled WCF Service Visual C #" en voer "WCF.svc" in voor een naam en klik vervolgens op "Toevoegen":

Zoals je ziet, hebben we een andere klasse met de naam WCF verkregen met een eigen codedocument, "WCF.svc.cs".


Stap 11: WCF Class Code Twee methoden

Voeg de volgende twee methoden toe in de WCF-klasse direct onder de regel met de tekst '// Voeg hier meer bewerkingen toe en markeer ze met [OperationContract]":

 // methode voor het ophalen van alle bestandsnamen in een map [OperationContract] public string [] getFileNames (String dir) try String tmp = HttpContext.Current.Request.MapPath (dir); return Directory.GetFiles (@tmp, "* .jpg");  catch (Uitzondering) return null;  // methode die de datum van creatie van een bestand of map [OperationContract] publiceert String string getFileDates (Stringbestand, int i) return i.ToString () + "-" + File.GetLastWriteTime (bestand) .ToString ( ); 

Los de ontbrekende namespaces op zoals we eerder hebben gedaan door te klikken op de betreffende namen, vervolgens op de blauwe rechthoek en op "import ..." of door deze twee regels handmatig aan de bovenkant van het document toe te voegen:

 met behulp van System.Web; met behulp van System.IO;

Stap 12: Servicereferentie deel 1

Om de webservice te kunnen gebruiken, moeten we een servicereferentie toevoegen aan het hoofdproject. Voordat we dit met succes kunnen doen, moeten we het project één keer bouwen. Klik daarom op "Build" in het menu helemaal bovenaan Visual Studio en daarna op "Build WallviewApp":


Stap 13: Servicereferentie deel 2

Nadat de build is voltooid, klikt u met de rechtermuisknop op "WallviewApp" aan de rechterkant in de Solution Explorer en kiest u "Service-referentie toevoegen" in het menu:


Stap 14: Servicereferentie Deel 3

In de komende pop-up klikt u op de knop "Ontdekken" en voert u "WCFRef" in het veld Naamruimte in en klikt u vervolgens op "OK":

Als u het project niet hebt gemaakt voordat u een servicereferentie probeerde toe te voegen, kreeg u de volgende foutmelding:


Stap 15: MainPage Class geeft variabelen weer

Open het bestand "MainPage.xaml.cs" en voeg de volgende regels code toe boven de constructor "public MainPage ()":

 privé WCFRef.WCFClient client; private string imagedir = "/ image /"; openbare wallview_img wvi; private int amountImages;

Stap 16: MainPage Class Programeer de Constructor

De constructeur van de Hoofdpagina het lijkt op dit. We initialiseren de verklaringen van de vorige stap, registreren eventhandlers van de webservice en voegen de wallview_img genaamd "wvi" naar de rooster "LayoutRoot" van de Hoofdpagina:

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

Stap 17: Codeer de Eventhandlers voor de Webservice

Voeg de volgende twee eventhandlers en de methode onder de constructor van de MainPage toe.

De "client_getFileNamesCompleted ()"krijgt een array van strings die worden geretourneerd door de webservice. De array wordt geconverteerd naar afzonderlijke strings waaruit de bestandsnaam wordt geëxtraheerd.

De ... gebruiken localhost adres, de poort, de afbeeldingsdirectory en de bestandsnaam, we bouwen een Uri genaamd "src". Dat Uri wordt gebruikt om een ​​nieuw te maken Bitmap afbeelding "bmi" wat nodig is om een ​​nieuwe afbeelding "tmp" te maken. De afbeelding "tmp" wordt dan toegevoegd aan de wallview_img "WMI".

Daarna wordt de methode die de aanmaakdatum van een bestand retourneert samen met een tellernummer opgeroepen. Wat die methode ook oplevert, wordt verwerkt door de handler "client_getFileDatesCompleted ()". Aangezien een tekenreeks in het formaat > 2-18.02.2009 12:32:23 is terug van de webservice, we moeten het tellergetal aan het begin en de datum in het midden afsplitsen.

Wanneer deze procedure is voltooid, ziet de einddatum er uit > 18.02.2009 en is toegewezen aan de tekstblok "imgDate" van de overeenkomstige afbeelding.

 // event handler voor het ophalen van de bestandsnamen uit de map private void client_getFileNamesCompleted (object afzender, WallviewApp.WCFRef.getFileNamesCompletedEventArgs e) if (e.Result! = null) foreach (string s in e.Result) int pos = s.LastIndexOf ( "\\"); string bestandsnaam = s. Sublink (pos + 1); int port = Application.Current.Host.Bron.Port; Uri src = nieuwe Uri ("http: // localhost:" + port + imagedir + bestandsnaam); BitmapImage bmi = new BitmapImage (src); afbeelding tmp = nieuwe afbeelding (bmi, bestandsnaam); this.wvi.addImage (TMP); amountImages ++; getFileDate (s, amountImages - 1);  else MessageBox.Show ("return null in bestanden voltooid");  // methode die de webservice asynch oproept met een filepath-string en een cijfer, zodat we de geretourneerde datum-string naar een bepaalde afbeelding opnieuw kunnen retourneren private void getFileDate (String s, int i) this.client.getFileDatesAsync (s, i );  // gebeurtenishandler voor het ophalen van de bestanden privé ongeldig client_getFileDatesCompleted (objectafzender, WallviewApp.WCFRef.getFileDatesCompletedEventArgs e) if (e.Result! = null) String dt = e.Result; int number = Convert.ToInt32 (dt.Remove (dt.LastIndexOf ("-"))); Tekenreeksdatum = dt.Remove (dt.LastIndexOf ("")); als (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");  

Net als in de andere bronbestanden kan de naamruimte "BitmapImage" niet worden gevonden. Om dit te herstellen, klikt u op de blauwe rechthoek en importeert u deze nadat u op de tekst hebt geklikt Bitmap afbeelding, of voeg de volgende regel handmatig toe aan de bovenkant van het document:

 using System.Windows.Media.Imaging;

Stap 18: Start het project

Ga je gang en voer het project uit om te kijken of alles werkt. U kunt dit doen door op "F5" op uw toetsenbord te drukken, door op de knop te klikken met een typisch "Play" -pictogram onder het menu bovenaan op de pictogrambalk of door het item "Start Debugging" in het "Debug" -menu te selecteren submenu uit het menu helemaal bovenaan Visual Studio:

Uw browser wordt geopend en u krijgt de volgende foutmelding:

Wat is het probleem?

We hebben de webservice opdracht gegeven om de map "http: // localhost: port / image /" voor * .jpg-bestanden te controleren en het is duidelijk dat noch die map, noch afbeeldingen in die map bestaan.


Stap 19: bereid de beeldmap voor

Navigeer met uw Windows Explorer naar de projectdirectory. Voor mij is dit het volgende pad:

Open de map "WallviewApp.Web" en maak een nieuwe map met de naam "image" erin.

Open nu de map "image" en plak wat * .jpg-afbeeldingen erin.


Stap 20: Voer het project opnieuw uit

Nadat u een paar afbeeldingen in de afbeeldingsmap hebt geplaatst, drukt u op vernieuwen in uw webbrowser (als deze nog open is) of voert u eenvoudigweg het project opnieuw uit door op de "F5" -toets in Visual Studio te drukken. Als gevolg hiervan zou u onze definitieve Wallview moeten zien:

U kunt de grootte van de weergegeven afbeeldingen beïnvloeden met de schuifregelaar in de navigatiebalk.


Conclusie

We zijn nu klaar met deze tutorial en ik hoop dat je het leuk vond en ook iets hebt geleerd.

De geschatte totale tijd die nodig was om dit vanaf nul te ontwikkelen was ongeveer 20 uur. De wallview voor albums die je hieronder in de video kunt zien, kostte me ongeveer 15 uur en nog eens 10 uur om beide soorten wallviews te combineren.

Je vraagt ​​je misschien af ​​wat het punt is om een ​​of meer afbeeldingen te selecteren. Op dit moment is die functionaliteit nutteloos, maar ik kan me voorstellen dat het toevoegen van de mogelijkheid om een ​​diavoorstelling te starten of een afspeellijst te maken van de geselecteerde afbeeldingen bijvoorbeeld. En als je je afvraagt ​​waarom we de knoppen "Alle albums", "Huidig ​​album", "<" and ">"in de navigatiebalk maar nooit gebruikt ...

Het is mijn bedoeling om een ​​nieuwe zelfstudie te ontwikkelen die automatisch fotoalbums genereert op basis van de bestandsnamen van de afbeeldingen. Natuurlijk verlengt deze zelfstudie het project met de zelfstudie die u zojuist hebt voltooid. Ik zou dat zeker graag doen als het populair is bij het publiek. Om een ​​indruk te krijgen van hoe de wallview voor afbeeldingen die we zojuist hebben gemaakt eruit zou zien in combinatie met een wallview voor fotoalbums, bekijk je de volgende video:

Voor opmerkingen, suggesties of opmerkingen, laat een berichtje achter in het commentaargedeelte. Bedankt voor het lezen!