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.
Kijk nog eens naar de videodemo van het eindresultaat waar we naartoe zullen werken (of bekijk de webgebaseerde demo hierboven):
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".
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.
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;
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.
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.
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 lijstImageList; 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:
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;
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();
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.RoutedPropertyChangedEventArgse) 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.
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".
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;
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":
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:
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:
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;
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);
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;
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.
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.
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.
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!