Crear un Wallview para imágenes con Silverlight Código

Bienvenido a la segunda parte de la creación de un Wallview inspirado en iTunes. En esta parte, vamos a escribir el código completo en C # para los dos UserControls que creamos con Expression Blend en el tutorial anterior..


Vista previa del resultado final

Eche un vistazo a la demostración en video del resultado final en el que trabajaremos (o simplemente consulte la demostración en línea más arriba):


Paso 1: Abre el proyecto

Abra Visual Studio y haga clic en "Archivo"> ​​"Abrir"> "Proyecto / Solución" en la barra de menú.

Luego busque el proyecto que creamos en la primera parte de este tutorial. Lo llamamos "WallviewApp".


Paso 2: Abra los documentos de C #

En el lado derecho de Visual Studio se encuentra el Explorador de soluciones de forma predeterminada. Aquí puedes ver todos los archivos del proyecto. Continúe y abra los dos archivos * .cs "image.xaml.cs" y "wallview-img.xaml.cs" de los dos UserControls que creamos en el tutorial anterior en Blend, así como el "MainPage.xaml.cs" que se proporcionó automáticamente.

Una vez que haya abierto estos tres archivos, podrá ver que las tres clases están bastante vacías..


Paso 3: Imagen de clase Declarar variables

Vamos a empezar con la codificación de la clase de imagen. Asegúrese de que está editando el archivo "image.xaml.cs" y agregue las siguientes declaraciones justo encima del constructor "public image ()":

 bool pública seleccionada; privado doble defaultSize; privado wallview_img wallview; privado SolidColorBrush colorDefault, colorSelected;

Paso 4: clase de imagen Escribe el constructor

Ahora vamos a programar el constructor que tiene dos parámetros: un BitmapImage y un String. Además, las variables declaradas anteriores se inicializan, los parámetros del constructor se asignan a la fuente del "img" y al texto del bloque de texto "imgName". También registramos un controlador de eventos para el evento MouseLeftButtonDown del "img":

 imagen pública (BitmapImage src, nombre de la cadena) // Necesario para inicializar las variables InitializeComponent (); seleccionado = 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 = nombre; this.imgDate.TextAlignment = TextAlignment.Center; this.img.MouseLeftButtonDown + = new MouseButtonEventHandler (image_MouseLeftButtonDown); 

El parámetro BitmapImage está subrayado con un color rojo porque Visual Studio no puede encontrar el espacio de nombres. Para corregirlo, simplemente haga clic en la palabra Imagen de mapa de bits y aparecerá un pequeño rectángulo azul debajo de la letra B:

Cuando mueva el mouse sobre el rectángulo pequeño, aparecerá un menú desplegable. Haga clic en la entrada "Utilizando System.Windows.Media.Imaging;":

Ahora Visual Studio sabe ese espacio de nombres, y el subrayado rojo desaparecerá..


Paso 5: código de clase de imagen Algunos métodos

Justo después del constructor, vamos a escribir un par de métodos que necesitaremos más adelante. Los métodos son bastante autodescriptivos a partir de sus nombres de métodos.. image_MouseLeftButtonDown es el controlador de eventos de la MouseLeftButtonDown evento del "img" que registramos en el constructor. Básicamente controla lo que sucede cuando haces clic en la imagen, dependiendo de su estado (ya esté seleccionado o no):

 public void setWallview (wallview_img wv) wallview = wv;  public void changeSize (doble 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 (objeto remitente, System.Windows.Input.MouseButtonEventArgs e) wallview.imageSelected = true; if (wallview.ctrlPressed == true) if (selected == true) unselectImage (); else selectImage ();  else wallview.unselectAllImages (); seleccionar imagen();  e.Handled = true; 

Ahora hemos terminado con la clase de imagen..

No se preocupe por las partes subrayadas en rojo en su código. Estas variables y métodos aún no existen y es por eso que Visual Studio no los conoce pero vamos a cambiar eso pronto.


Paso 6: Wallview-img Clase Declarar variables

Una vez que hayamos terminado con la clase de imagen, abra el documento "wallview-img.xaml.cs". Al principio, escriba las declaraciones de variables justo encima del constructor "public wallview_img ()":

 Lista pública imageList; Lista privada panelList; public bool ctrlPressed, imageSelected; privado doble defaultSize, changeSize;

Al igual que antes con BitmapImage, Visual Studio no conoce el espacio de nombres de Lista. Para solucionar esto, como antes, haga clic en una de las listas, luego en el rectángulo azul y seleccione "usando System.Collections.Generic;" desde el menú:


Paso 7: wallview-img Class Code the Constructor

Agregue el siguiente código que inicializa las variables declaradas anteriormente, registra algunos eventos y desactiva los botones en la barra de navegación:

 public wallview_img () // Necesario para inicializar las variables InitializeComponent (); ctrlPressed = falso; imageSelected = false; imageList = nueva lista(); panelList = nueva lista(); defaultSize = 200; changeSize = 1; // registrar todos los eventos MouseLeftButtonUp + = new MouseButtonEventHandler (wallviewMouseLeftButtonUp); SizeChanged + = new SizeChangedEventHandler (resizeScrollViewer); KeyDown + = new KeyEventHandler (keyDownEvent); KeyUp + = new KeyEventHandler (keyUpEvent); this.slider.ValueChanged + = new RoutedPropertyChangedEventHandler(sliderValueChanged); // botones que no necesitamos todavía this.btnAllAlbums.IsEnabled = false; this.btnCurrentAlbum.IsEnabled = false; this.btnNext.IsEnabled = false; this.btnPrev.IsEnabled = false; 

Paso 8: Clase de wallview-img Escribe los métodos

Agregue los siguientes métodos debajo del constructor. El comentario antes de cada método explica qué está haciendo el método:

 // agrega una imagen a la lista de imágenes y llama a resizeimages () que básicamente la agrega al último panel de pila public addidage (img de imagen) img.imgName.Width = 200; img.setWallview (esto); imageList.Add (img); resizeImages ();  // borra todo el contenido dibujado, cada panel, lista de álbumes y panelista public void clearLists () imageList.Clear (); foreach (StackPanel x en panelList) x.Children.Clear ();  this.content.Children.Clear (); panelList.Clear ();  // calcula cuántos stackpanels = row se necesitan public void updatePanels () if (imageList.Count> 0) foreach (StackPanel sp en panelList) sp.Children.Clear (); panelList.Clear (); doble rejilla ancho = 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; doble proporción = gridWidth / (double) imageSize; int ratioInt = Convert.ToInt32 (ratio); if (ratioInt - ratio> 0) ratioInt - = 1; int newImageMargin = ((gridWidthInt - ratioInt * imageWidth) / ratioInt) / 2; doble panelAmountDouble = (double) imageAmount / ratioInt; int panelAmountInt = (int) panelAmountDouble; if (panelAmountDouble - panelAmountInt> 0) panelAmountInt ++; si (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(); 

Paso 9: wallview-img Class Eventhandlers

En este paso, escribimos los controladores de eventos necesarios para los eventos que registramos anteriormente en el constructor:

 // eventhandler para cuando se cambia el control deslizante void privado sliderValueChanged (objeto remitente, System.Windows.RoutedPropertyChangedEventArgs e) changeImageSize (this.slider.Value);  // eventhandler al que se llama cuando el tamaño de la ventana cambia el vacío privado resizeScrollViewer (objeto remitente, System.Windows.SizeChangedEventArgs e) resizeImages ();  // eventhandler que deselecciona todas las imágenes cuando no hace clic en una imagen void wallviewMouseLeftButtonUp (objeto remitente, MouseButtonEventArgs e) if (! (! imageSelected) unselectAllImages (); else imageSelected = false;  // eventhandler para presionar las teclas private void keyDownEvent (objeto emisor, System.Windows.Input.KeyEventArgs e) if (e.Key == Key.Ctrl) ctrlPressed = true; else if (e.Key == Key.A) if (ctrlPressed) selectAllImages ();  // eventhandler para liberar claves private void keyUpEvent (objeto remitente, System.Windows.Input.KeyEventArgs e) if (e.Key == Key.Ctrl) ctrlPressed = false; 

Ahora hemos terminado con el wallview-img clase. Continuemos con la creación de un servicio web que necesitaremos para el Pagina principal clase.


Paso 10: Crear un servicio web

El servicio web que vamos a escribir básicamente nos proporciona las imágenes de una carpeta determinada. Para crear un servicio web, haga clic con el botón derecho en "WallviewApp.Web" en el Explorador de soluciones en el lado derecho de Visual Studio y seleccione "Agregar"> "Nuevo elemento" en el menú:

Desde la ventana emergente, seleccione "WCF Service Visual C #" habilitado para Silverlight e ingrese "WCF.svc" para un nombre, luego haga clic en "Agregar":

Como puede ver, obtuvimos otra clase llamada WCF con su propio documento de código, "WCF.svc.cs".


Paso 11: Código de clase WCF dos métodos

Agregue los siguientes dos métodos en la clase WCF justo debajo de la línea que dice "// Agregue más operaciones aquí y márquelas con [OperationContract]":

 // método para obtener todos los nombres de archivo dentro de una carpeta [OperationContract] public string [] getFileNames (String dir) try String tmp = HttpContext.Current.Request.MapPath (dir); return Directory.GetFiles (@tmp, "* .jpg");  catch (Exception) return null;  // método que devuelve la fecha de creación de un archivo o carpeta [OperationContract] public String getFileDates (String file, int i) return i.ToString () + "-" + File.GetLastWriteTime (file) .ToString ( ); 

Corrija los espacios de nombres faltantes como hicimos anteriormente haciendo clic en los nombres afectados, luego en el rectángulo azul y en "importar ..." o agregando estas dos líneas manualmente en la parte superior del documento:

 utilizando System.Web; utilizando System.IO;

Paso 12: Referencia de servicio Parte 1

Para poder utilizar el servicio web necesitamos agregar una referencia de servicio al proyecto principal. Antes de que podamos hacer esto con éxito, tenemos que construir el proyecto una vez. Por lo tanto, haga clic en "Crear" en el menú en la parte superior de Visual Studio y luego en "Crear WallviewApp":


Paso 13: Referencia de servicio Parte 2

Una vez que la compilación sea exitosa, haga clic con el botón derecho en "WallviewApp" en el lado derecho en el Explorador de soluciones y elija "Agregar referencia de servicio" en el menú:


Paso 14: Referencia de servicio Parte 3

En la próxima ventana emergente, haga clic en el botón "Descubrir" e ingrese "WCFRef" en el campo Espacio de nombres, luego haga clic en "Aceptar":

Sin compilar el proyecto antes de intentar agregar una referencia de servicio, habría recibido este mensaje de error:


Paso 15: Clase MainPage Declare Variables

Abra el archivo "MainPage.xaml.cs" y agregue las siguientes líneas de código sobre el constructor "Página principal pública ()":

 cliente privado WCFRef.WCFClient; cadena privada imagedir = "/ image /"; public wallview_img wvi; Imágenes de int privado;

Paso 16: MainPage Class Program the Constructor

El constructor de la Pagina principal Se ve como esto. Inicializamos las declaraciones del paso anterior, registramos los manejadores de eventos del servicio web y agregamos el wallview_img llamado "wvi" al Cuadrícula "LayoutRoot" del Pagina principal:

 mainPage () InitializeComponent () pública; amountImages = 0; cliente = nuevo 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); 

Paso 17: Codificar los Eventhandlers para el servicio web

Agregue los siguientes dos manejadores de eventos y el método debajo del constructor de MainPage.

Los "client_getFileNamesCompleted ()"obtiene una matriz de cadenas que el servicio web devuelve. La matriz se convierte en cadenas separadas de las que se extrae el nombre de archivo.

Utilizando la localhost dirección, el puerto, el directorio de imágenes y el nombre de archivo, construimos un Uri llamado "src". Ese Uri se utiliza para crear un nuevo Imagen de mapa de bits "bmi" que se necesita para crear una nueva imagen "tmp". La imagen "tmp" se agrega a la wallview_img "wmi".

Posteriormente, el método que devuelve la fecha de creación de un archivo se llama junto con un número de contador. Cualquiera que sea el método que devuelve, es procesado por el controlador "client_getFileDatesCompleted ()". Desde una cadena en el formato > 2-18.02.2009 12:32:23 es devuelto desde el servicio web, tenemos que dividir el número de contador al principio y la fecha en el medio.

Cuando este procedimiento se completa, la fecha final parece > 18.02.2009 y está asignado a la Bloque de texto "imgDate" de la imagen correspondiente.

 // controlador de eventos para obtener los nombres de archivo de la carpeta privada void client_getFileNamesCompleted (objeto remitente, WallviewApp.WCFRef.getFileNamesCompletedEventArgs e) if (e.Result! = null) foreach (string s in e.Result) int pos = s.LastIndexOf ("\\"); cadena nombre_archivo = s.Suststring (pos + 1); int port = Application.Current.Host.Source.Port; Uri src = new Uri ("http: // localhost:" + port + imagedir + filename); BitmapImage bmi = new BitmapImage (src); imagen tmp = nueva imagen (bmi, nombre de archivo); this.wvi.addImage (tmp); amountImages ++; getFileDate (s, amountImages - 1);  else else MessageBox.Show ("devolvió nulo en archivos completados");  // método que llama al servicio web asynch con una cadena de ruta de archivo y un número para que podamos evaluar la cadena de fecha devuelta a una imagen determinada de nuevo privada void getFileDate (String s, int i) this.client.getFileDatesAsync (s, i );  // controlador de eventos para obtener los archivos privados anulados client_getFileDatesCompleted (objeto remitente, WallviewApp.WCFRef.getFileDatesCompletedEventArgs e) if (e.Result! = null) String dt = e.Result; número int = Convert.ToInt32 (dt.Remove (dt.LastIndexOf ("-"))); Fecha de cadena = dt.Remove (dt.LastIndexOf ("")); si < 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");  

Como en los otros archivos de origen, el espacio de nombres "BitmapImage" no se puede encontrar. Para repararlo, haga clic en el rectángulo azul e impórtelo después de hacer clic en el texto de Imagen de mapa de bits, o agregue la siguiente línea a la parte superior del documento manualmente:

 utilizando System.Windows.Media.Imaging;

Paso 18: Ejecutar el proyecto

Sigue adelante y ejecuta el proyecto para ver si todo funciona. Puede hacer esto presionando "F5" en su teclado, haciendo clic en el botón con un ícono típico "Play" debajo del menú en la parte superior de la barra de iconos, o seleccionando la entrada "Iniciar depuración" dentro de "Debug" submenú del menú en la parte superior de Visual Studio:

Su navegador se abrirá y recibirá este mensaje de error:

Cuál es el problema?

Le dijimos al servicio web que revisara la carpeta "http: // localhost: port / image /" para los archivos * .jpg y, obviamente, ni esa carpeta ni ninguna imagen en esa carpeta existen todavía..


Paso 19: Preparar la carpeta de imágenes

Navegue hasta el directorio del proyecto con su Explorador de Windows. Para mi es el siguiente camino:

Abra la carpeta "WallviewApp.Web" y cree una nueva carpeta llamada "imagen" dentro de ella.

Ahora abre la carpeta "imagen" y pega algunas imágenes * .jpg en ella.


Paso 20: Ejecutar el proyecto de nuevo

Una vez que haya colocado un par de imágenes dentro de la carpeta de imágenes, presione actualizar dentro de su navegador web (si aún está abierto) o simplemente ejecute el proyecto nuevamente presionando la tecla "F5" en Visual Studio. Como resultado, deberías ver nuestro último Wallview:

Puede influir en el tamaño de las imágenes mostradas con el control deslizante en la barra de navegación.


Conclusión

Ya hemos terminado con este tutorial y espero que lo hayas disfrutado y que hayas aprendido algo..

El tiempo total aproximado que me tomó desarrollar esto desde cero fue de aproximadamente 20 horas. La vista de pared de los álbumes que se pueden ver en el video a continuación me llevó aproximadamente 15 horas y otras 10 horas para combinar ambos tipos de vista de pared..

Podría preguntarse cuál es el punto de poder seleccionar una o más imágenes. En este momento esa funcionalidad es inútil, pero podría imaginar agregar la posibilidad de comenzar una presentación de diapositivas o crear una lista de reproducción a partir de las imágenes seleccionadas, por ejemplo. Y si se está preguntando por qué agregamos los botones "Todos los álbumes", "Álbum actual",<" and ">"en la barra de navegación pero nunca los usé ...

Mi intención es desarrollar otro tutorial que genere automáticamente álbumes de fotos basados ​​en los nombres de archivos de las imágenes. Por supuesto, ese tutorial ampliará el proyecto del tutorial que acaba de completar aquí. Definitivamente me gustaría hacer eso si es popular entre la audiencia. Para obtener una impresión de cómo se vería la vista de pared para las imágenes que acabamos de crear en combinación con una vista de pared para álbumes de fotos, eche un vistazo al siguiente video:

Para cualquier comentario, sugerencia o inquietud, por favor deje una nota en la sección de comentarios. Gracias por leer!