none
Proyecto WPF de películas, directores y actores. No consigo hacerlo funcionar. RRS feed

  • Pregunta

  • Hola a todos,

    estoy aprendiendo WPF y para ello he usado un código de ejemplo de un libro que he comprado. El libro en cuestión proporciona ciertas partes de código, pero no completo.

    El código que intento implementar es para ver las películas, directores y demás. En concreto, las películas de cierto director y los actores que intervienen en la misma.

    No consigo hacerlo funcionar. No consigo enlazar las películas (clase de la entidad Película) que ha hecho un director; ni los actores que tienen una película en cuestión. Supongo que lo que no consigo entender son las colecciones.

    Este es el código XAML:

    <Window x:Class="WPF_EnlaceDatos.EnlaceObjetoNegocio"      
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ejemplo="clr-namespace:WPF_EnlaceDatos"
            Title="Peliculas con varios actores" Height="250" Width="800">
    <!-- Hay que poner en la x:Class 'WPF_EnlaceDatos.EnlaceObjetoNegocio' y en la partial class de c# poner 'EnlaceObjetoNegocio : Window', si no no funciona en enlace a Film. -->
        <Window.Resources>
            <ejemplo:Film x:Key="filmInfiltrados" Titulo="Infiltrados" Genero="Mafia" Oscar="{x:Null}" Calificación="4.7" />
           
            <!--<local:Clientes x:Key="clientes"/>
            <CollectionViewSource x:Key="vistaClientes" Source="{Binding Source={StaticResource clientes},Path=Data}">

            </CollectionViewSource>-->
           
            <ejemplo:Director x:Key="Spielberg" Nombre="Steven Spielberg" Nacionalidad="USA">
               
                <ejemplo:Director.Filmes>
                    <ejemplo:Film Titulo="Jurassik Park" Genero="Aventuras" Oscar="True" Calificación="4" />
                    <ejemplo:Film Titulo="La Lista de Schindler" Genero="Drama" Oscar="True" Calificación="4.5" />
                    <ejemplo:Film Titulo="E.T." Genero="CienciaFicción" Oscar="True" Calificación ="4"></ejemplo:Film>
                    <ejemplo:Film Titulo="Tiburon" Genero="Aventuras" Oscar="False" Calificación="4.2"></ejemplo:Film>
                    <ejemplo:Film Titulo="Color Púrpura" Genero="Drama" Oscar="False" Calificación="4.7"></ejemplo:Film>
                    <ejemplo:Film Titulo="Munich" Genero="CienciaFiccion" Oscar="False" Calificación="4"></ejemplo:Film>
                    <ejemplo:Film Titulo="Encuentro Cercano de Tercer Tipo" Genero="CienciaFiccion" Oscar="False" Calificación="4.1"></ejemplo:Film>
                    <ejemplo:Film Titulo="Inteligencia Artificial" Genero="CienciaFiccion" Oscar="False" Calificación="3.7"></ejemplo:Film>
               
                   
                </ejemplo:Director.Filmes>
            </ejemplo:Director>

        </Window.Resources>

        <Grid Margin="0,0,0,0" Height="238" Width="750">
            <!-- Visualización del objeto de negocios -->
            <Grid  Margin="0,0,453,166" Width="350">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>

                <TextBlock Text="{Binding Path=Titulo, Source={StaticResource filmInfiltrados}}"  FontWeight="Bold" FontSize="16" Grid.Row="0"/>
                <TextBlock Text="Género:" Grid.Row="1"/>
                <TextBlock Margin ="60,0" Text="{Binding Genero, Source={StaticResource filmInfiltrados}}" Grid.Row="1"/>
                <TextBlock Text="Ganó Oscar:" Grid.Row="2"/>
                <TextBlock Margin ="100,0" Text="{Binding Oscar, Source={StaticResource filmInfiltrados}}" Grid.Row="2"/>
                <TextBlock Text="Calificación:" Grid.Row="3"/>
                <TextBlock Margin ="100,0" Text="{Binding Calificación, Source={StaticResource filmInfiltrados}}" Grid.Row="3"/>
            </Grid>

            <!-- Edición del objeto de negocios ¡¡ESTO ES UNA LÍNEA DE COMENTARIOS EN WPF!! -->
            <Grid Margin="102,164,500,35">
                <Button Click="Modify1_Click">Cambiar por Titanic</Button>
            </Grid>
            <Grid Background="Azure"  Margin="370,1,12,123">
                <Grid.RowDefinitions>
                    <RowDefinition Height="30"/>
                    <RowDefinition Height="28"/>
                    <RowDefinition Height="21"/>
                    <RowDefinition Height="25"/>
                    <RowDefinition Height="10*" />
                </Grid.RowDefinitions>

                <TextBox Text="{Binding Titulo, Source={StaticResource filmInfiltrados}}" FontWeight="Bold" FontSize="16" Grid.Row="0"/>
                <TextBlock  Text="Género:" Grid.Row="1" Margin="0,4,0,16" Grid.RowSpan="2" />
                <TextBox Margin ="58,3,62,2" Text="{Binding Genero, Source={StaticResource filmInfiltrados}}" FontSize="10" Grid.Row="1" />
                <TextBlock  Text="Ganó Oscar:" Grid.Row="2" Margin="0,4,0,16" Grid.RowSpan="2" />
                <TextBox Margin ="100,4,100,2"   Text="{Binding Oscar, Source={StaticResource filmInfiltrados}}" Grid.Row="2" FontSize="8" />
                <TextBlock Text="Calificación:" Grid.Row="3" Margin="0,4,0,0" />
                <TextBox Margin ="70,5,70,4"  Text="{Binding Calificación, Source={StaticResource filmInfiltrados}}" Grid.Row="3" FontSize="10" />
            </Grid>
        </Grid>

    </Window>

    Y este el código C#:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.ComponentModel;    /// Para poder declarar el Noficador de cambios de propiedad.
    using System.Collections.ObjectModel; /// Para poder declarar ObservableCollection<string> Filmes---> ARRAY

    namespace WPF_EnlaceDatos
    {
        /// <summary>
        /// Lógica de interacción para MainWindow.xaml
        /// </summary>
        public partial class EnlaceObjetoNegocio : Window
        {
            public EnlaceObjetoNegocio()
            {
                InitializeComponent();
            }

            private void Modify1_Click(object sender, RoutedEventArgs args)
            {
                Film film = Resources["filmInfiltrados"] as Film;
                film.Titulo = "Titanic";
                film.Genero = Genero.Catastrofismo;
                film.Oscar = true;
                film.Calificación = 4.2;
            }
        }
        public class Notificador : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string name)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        //La declaración del tipo FILM va en el código behind C#.
        public enum Genero { Mafia, Drama, Catastrofismo, Aventuras, Comedia, Oeste, CienciaFiccion }

        public class Film : Notificador
        {
            string titulo;
            Director director;
            Genero genero;
            bool? oscar;
            double calificación;
            //public ObservableCollection<string> actores;
            public Film() { }

            public Film(string titulo, Genero genero, bool? oscar, double calificación, Director director)
            {
                this.Titulo = titulo;
                this.Genero = genero;
                this.Oscar = oscar;
                this.Calificación = calificación;
                this.Director = director;
                //this.Actores = actores;
            }
            public string Titulo
            {
                get { return titulo; }
                set
                {
                    if (titulo == value) return;
                    titulo = value;
                    OnPropertyChanged("Titulo");
                }
            }
            public Genero Genero
            {
                get { return genero; }
                set
                {
                    if (genero == value) return;
                    genero = value;
                    OnPropertyChanged("Genero");
                }
            }
            public bool? Oscar
            {
                get { return oscar; }
                set
                {
                    if (oscar == value) return;
                    oscar = value;
                    OnPropertyChanged("Oscar");
                }

            }
            public double Calificación
            {
                get { return calificación; }
                set
                {
                    if (calificación == value) return;
                    calificación = value;
                    OnPropertyChanged("Calificación");
                }
            }
            public Director Director
            {
                get { return director; }
                set
                {
                    if (director == value) return;
                    director = value;
                    OnPropertyChanged("Director");
                }
            }
            //public ObservableCollection<string> Actores {
            //    get { return actores; }
            //    set
            //    {
            //        if (actores  == value) return;
            //        actores = value;
            //        OnPropertyChanged("Actores");
            //    }
            //}
        }
        public class Director : Notificador
        {

            string nombre;
            string nacionalidad;
            public ObservableCollection<string> filmes;
            public Director() { }

            public Director(string nombre, string nacionalidad, ObservableCollection<Film> filmes)
            {
                this.Nombre = nombre;
                this.Nacionalidad = nacionalidad;
                this.Filmes = new filmes();
               
            }
            public string Nombre
            {
                get { return Nombre; }
                set
                {
                    if (Nombre == value) return;
                    Nombre = value;
                    OnPropertyChanged("Nombre");
                }
            }
            public string Nacionalidad
            {
                get { return Nacionalidad; }
                set
                {
                    if (Nacionalidad == value) return;
                    Nacionalidad = value;
                    OnPropertyChanged("Nacionalidad");
                }
            }

            public class Filmes : ObservableCollection<Film>
            {
                public ObservableCollection<Film> Data { get; set; }
                public Filmes()
                {
                    Data = new ObservableCollection<Film>();
                    Data.Add(new Film() { Titulo = "Jurassik Park", Genero = WPF_EnlaceDatos.Genero.Aventuras, Oscar = true, Calificación = 4.0 });
                    Data.Add(new Film() { Titulo = "La Lista de Schindler", Genero = WPF_EnlaceDatos.Genero.Drama, Oscar = true, Calificación = 4.2 });
                    Data.Add(new Film() { Titulo = "E.T.", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = true, Calificación = 4.1 });
                    Data.Add(new Film() { Titulo = "Tiburon", Genero = WPF_EnlaceDatos.Genero.Aventuras, Oscar = false, Calificación = 4.7 });
                    Data.Add(new Film() { Titulo = "Color Púrpura", Genero = WPF_EnlaceDatos.Genero.Drama, Oscar = false, Calificación = 4.3 });
                    Data.Add(new Film() { Titulo = "Munich", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = true, Calificación = 3.5 });
                    Data.Add(new Film() { Titulo = "Encuentro Cercano de Tercer Tipo", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = false, Calificación = 3.0 });
                    Data.Add(new Film() { Titulo = "Inteligencia Artificial", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = false, Calificación = 3.8 });
                }
            }
        }


    }

    Uso Visual Studio 2010 para el desarrollo sobre Windows 7.

    Por favor, a ver si alguien me puede echar una mano, porque no consigo avanzar. Gracias de antemano y un saludo.

     

    viernes, 25 de marzo de 2011 11:24

Todas las respuestas

  • Es mala idea querer aprender desde lo complejo. Deberìas empezar por tutoriales paso a paso o en su defecto por ejemplos màs simples.

    1-Para poder ayudar, es necesario que específiques los errores de depuración.

    2-Intenta crear este código paso a paso, recuerda Divide y Venceras.

    2- Si de casualidad copiaste el código, deberìas revisar que  xmlns:ejemplo="clr-namespace:WPF_EnlaceDatos" sea realmente el namespace.                                      

    Saludos

     

     


    Custom Control Silverlight
    "Blog Ingphillip's Prog: TODO WEB
    viernes, 25 de marzo de 2011 22:15
  • Hola Felipe, gracias por contestar.

    Digamos que estoy aprendiendo por urgencia de trabajo. Ya llevo un tiempecito con esto y desde luego, he empezado con tutoriales desde abajo.

    Lo que pasa es que, como ejercicio, intento implementar una simple pantalla maestro-detalle que me muestre para un director (seleccionado a la izquierda) las películas que ha hecho (a la derecha) y los actores que han participado.

    Los errores que me muestra el depurador son los siguientes:

     

    Error    1    'Filmes': no se puede hacer referencia a un tipo a través de una expresión; pruebe con 'WPF_EnlaceDatos.Director.Filmes'    C:\Users\cgallardo\Documents\Visual Studio 2010\Projects\WPF_EnlaceDatos_MaestroDetalle - copia\WPF_EnlaceDatos\MainWindow.xaml.cs    143    18    WPF_EnlaceDatos

    Error    2    'WPF_EnlaceDatos.Director.filmes' es 'campo' pero se utiliza como 'tipo'    C:\Users\cgallardo\Documents\Visual Studio 2010\Projects\WPF_EnlaceDatos_MaestroDetalle - copia\WPF_EnlaceDatos\MainWindow.xaml.cs    143    31    WPF_EnlaceDatos

    Decirte que he intentado dividir el código y mostrar primero las películas de un director y no lo logro. Tampoco logro mostrar los actores de una película en cuestión.

    A ver si me puedes ayudar por favor. Gracias.

    lunes, 28 de marzo de 2011 8:27
  • Hola galvi.

    Bien, si quieres que te funciones, debes realizar algunas modificaciones:

     

    1.- en el codigo xaml, la linea :

    <ejemplo:Film Titulo="E.T." Genero="CienciaFicción" Oscar="True" Calificación ="4"></ejemplo:Film>
    

    te dara error, pero compilara aun con ese error, se debe a que el genero tiene una palabra que no esta en la enumeracion, ya que conforme esta escrito tiene acento y en la enumeracion 'Genero' del code behind, no tiene acento 

    NOTA: Eliminar el acento.

    2.- la clase 'Filmes' esta dentro de la clase 'Director' no creo que eso sea lo que el autor quiso poner, ademas como tenemos que crear una nueva propiedad, la clase hay que sacarla o cambiarle el nombre (Yo opto por sacarla, ya que tiene mas sentido).

    de modo que la clase Filmes, se corta y se pone debajo, como una clase mas en el namespace 'WPF_EnlaceDatos'

    3.- parece faltar una propiedad en la clase 'Director', y tiene toda la pinta de llamarse 'Filmes', de modo que hay que añadirle la propiedad.

    4.- en el constructor del Director, se pasa un parametro que no se usa, es filmes, de modo que supongo que se quiere asociar ese parametro a la propiedad que hemos creado.

    5.- el ObservableCollection<string> no parece tener mucho sentido, cuando la clase Filmes tiene un ObservableCollection<Film>, parece que la propiedad se deberia de cambiar (aunque esto depende de la arquitectura), de modo que en un principio, la cambiamos.

    6.- las propiedades, usan el nombre de las propiedades para darles valor, esto no tiene ningun sentido, se deben usar las variables miembro, de modo que hay que cambiarlo.

    Creo que no me dejo nada, de todas formas una vez funcionando y compilando, se deberia de ver que hace lo correcto (pero eso te lo dejo a ti, para que toques cosas y aprendas ;)

     

    En definitiva, el codigo c#, queda de la siguiente forma para que funcione (el xaml, solo tiene lo del punto 1):

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.ComponentModel;  /// Para poder declarar el Noficador de cambios de propiedad.
    using System.Collections.ObjectModel; /// Para poder declarar ObservableCollection<string> Filmes---> ARRAY
    
    namespace WPF_EnlaceDatos
    {
      /// <summary>
      /// Lógica de interacción para MainWindow.xaml
      /// </summary>
      public partial class EnlaceObjetoNegocio : Window
      {
        public EnlaceObjetoNegocio()
        {
          InitializeComponent();
        }
    
        private void Modify1_Click(object sender, RoutedEventArgs args)
        {
          Film film = Resources["filmInfiltrados"] as Film;
          film.Titulo = "Titanic";
          film.Genero = Genero.Catastrofismo;
          film.Oscar = true;
          film.Calificación = 4.2;
        }
      }
      public class Notificador : INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
          if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
      }
    
      //La declaración del tipo FILM va en el código behind C#.
      public enum Genero { Mafia, Drama, Catastrofismo, Aventuras, Comedia, Oeste, CienciaFiccion }
    
      public class Film : Notificador 
      {
        string titulo;
        Director director;
        Genero genero;
        bool? oscar;
        double calificación;
        //public ObservableCollection<string> actores;
        public Film() { }
    
        public Film(string titulo, Genero genero, bool? oscar, double calificación, Director director)
        {
          this.Titulo = titulo;
          this.Genero = genero;
          this.Oscar = oscar;
          this.Calificación = calificación;
          this.Director = director;
          //this.Actores = actores;
        }
        public string Titulo
        {
          get { return titulo; }
          set
          {
            if (titulo == value) return;
            titulo = value;
            OnPropertyChanged("Titulo");
          }
        }
        public Genero Genero
        {
          get { return genero; }
          set
          {
            if (genero == value) return;
            genero = value;
            OnPropertyChanged("Genero");
          }
        }
        public bool? Oscar
        {
          get { return oscar; }
          set
          {
            if (oscar == value) return;
            oscar = value;
            OnPropertyChanged("Oscar");
          }
    
        }
        public double Calificación
        {
          get { return calificación; }
          set
          {
            if (calificación == value) return;
            calificación = value;
            OnPropertyChanged("Calificación");
          }
        }
        public Director Director
        {
          get { return director; }
          set
          {
            if (director == value) return;
            director = value;
            OnPropertyChanged("Director");
          }
        }
        //public ObservableCollection<string> Actores {
        //  get { return actores; }
        //  set
        //  {
        //    if (actores == value) return;
        //    actores = value;
        //    OnPropertyChanged("Actores");
        //  }
        //}
      }
      public class Director : Notificador
      {
    
        string nombre;
        string nacionalidad;
        public ObservableCollection<Film> filmes;
        public Director() { }
    
        public Director(string nombre, string nacionalidad, ObservableCollection<Film> filmes)
        {
          this.Nombre = nombre;
          this.Nacionalidad = nacionalidad;
          this.Filmes = filmes;
          
        }
    
        public string Nombre
        {
          get { return this.nombre; }
          set
          {
            if (this.nombre == value) return;
            this.nombre = value;
            OnPropertyChanged("Nombre");
          }
        }
        public string Nacionalidad
        {
          get { return this.nacionalidad; }
          set
          {
            if (this.nacionalidad == value) return;
            this.nacionalidad = value;
            OnPropertyChanged("Nacionalidad");
          }
        }
    
        public ObservableCollection<Film> Filmes
        {
          get { return this.filmes; }
          set
          {
            if (this.filmes == value) return;
            this.filmes = value;
            OnPropertyChanged("Filmes");
          }
        }
      }
    
    
      public class Filmes : ObservableCollection<Film>
      {
        public ObservableCollection<Film> Data { get; set; }
        public Filmes()
        {
          Data = new ObservableCollection<Film>();
          Data.Add(new Film() { Titulo = "Jurassik Park", Genero = WPF_EnlaceDatos.Genero.Aventuras, Oscar = true, Calificación = 4.0 });
          Data.Add(new Film() { Titulo = "La Lista de Schindler", Genero = WPF_EnlaceDatos.Genero.Drama, Oscar = true, Calificación = 4.2 });
          Data.Add(new Film() { Titulo = "E.T.", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = true, Calificación = 4.1 });
          Data.Add(new Film() { Titulo = "Tiburon", Genero = WPF_EnlaceDatos.Genero.Aventuras, Oscar = false, Calificación = 4.7 });
          Data.Add(new Film() { Titulo = "Color Púrpura", Genero = WPF_EnlaceDatos.Genero.Drama, Oscar = false, Calificación = 4.3 });
          Data.Add(new Film() { Titulo = "Munich", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = true, Calificación = 3.5 });
          Data.Add(new Film() { Titulo = "Encuentro Cercano de Tercer Tipo", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = false, Calificación = 3.0 });
          Data.Add(new Film() { Titulo = "Inteligencia Artificial", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = false, Calificación = 3.8 });
        }
      }
    
    
    
    
    }
    

    Ya contaras como te va.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    lunes, 28 de marzo de 2011 11:59
  • Hola David, me has ayudado mucho. Desde luego que sí.

    Pero no consigo que haga lo que pretendo: Quiero a la izquierda un panel que me ponga todos las películas que he introducido para un director. Y a la derecha otro panel al estilo Maestro-Detalle, que para la película seleccionada en el panel izquierdo, a la derecha haga un desglose de sus datos.

    Para ello tengo el siguiente XAML:

     

    <Window x:Class="WPF_EnlaceDatos.EnlaceObjetoNegocio"      
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ejemplo="clr-namespace:WPF_EnlaceDatos"
            Title="Peliculas con varios actores" Height="250" Width="800">
    <!-- Hay que poner en la x:Class 'WPF_EnlaceDatos.EnlaceObjetoNegocio' y en la partial class de c# poner 'EnlaceObjetoNegocio : Window', si no no funciona en enlace a Film. -->
        <Window.Resources>
            <ejemplo:Film x:Key="filmInfiltrados" Titulo="Infiltrados" Genero="Mafia" Oscar="{x:Null}" Calificación="4.7" />
            <ejemplo:Director x:Key="Spielberg" Nombre="Steven Spielberg" Nacionalidad="USA">
                <ejemplo:Director.Filmes>
                    <ejemplo:Film Titulo="Jurassik Park" Genero="Aventuras" Oscar="True" Calificación="4" />
                    <ejemplo:Film Titulo="La Lista de Schindler" Genero="Drama" Oscar="True" Calificación="4.5" />
                    <ejemplo:Film Titulo="E.T." Genero="CienciaFiccion" Oscar="True" Calificación ="4"></ejemplo:Film>
                    <ejemplo:Film Titulo="Tiburon" Genero="Aventuras" Oscar="False" Calificación="4.2"></ejemplo:Film>
                    <ejemplo:Film Titulo="Color Púrpura" Genero="Drama" Oscar="False" Calificación="4.7"></ejemplo:Film>
                    <ejemplo:Film Titulo="Munich" Genero="CienciaFiccion" Oscar="False" Calificación="4"></ejemplo:Film>
                    <ejemplo:Film Titulo="Encuentro Cercano de Tercer Tipo" Genero="CienciaFiccion" Oscar="False" Calificación="4.1"></ejemplo:Film>
                    <ejemplo:Film Titulo="Inteligencia Artificial" Genero="CienciaFiccion" Oscar="False" Calificación="3.7"></ejemplo:Film>
                </ejemplo:Director.Filmes>
            </ejemplo:Director>
        </Window.Resources>

            <!-- Visualización del objeto de negocios -->
            <Grid  DataContext="{Binding SelectedItem, ElementName=lbFilmes}">
                <Grid.ColumnDefinitions>
                <ColumnDefinition Width="192"/>
                <ColumnDefinition Width="586*" />
            </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                <RowDefinition Height="177"/>
                <RowDefinition Height="34*" />
            </Grid.RowDefinitions>
                    <StackPanel DataContext="{StaticResource Spielberg}" Margin="4,4,0,0">
                        <TextBlock FontSize="14" FontWeight="Bold">Filmes</TextBlock>
                        <ListBox Name="lbFilmes" ItemsSource="{Binding Filmes}" Height="153" />
                    </StackPanel>
                    <StackPanel Margin="0,0,230,67" Grid.Column="1">
                        <TextBlock Text="{Binding Titulo}" FontWeight="Bold" FontSize="14" Grid.ColumnSpan="2"/>
                        <TextBlock Text="Género:" Grid.Row="1" Grid.Column="0"/>
                        <TextBlock Text="{Binding Genero}" Grid.Row="1" Grid.Column="1"/>
                        <TextBlock Text="Oscar:" Grid.Row="2" Grid.Column="0"/>
                        <TextBlock Text="{Binding Oscar}" Grid.Row="2" Grid.Column="1"/>
                        <TextBlock Text="Calificación:" Grid.Row="3" Grid.Column="0"/>
                        <TextBlock Text="{Binding Calificación}" Grid.Row="3" Grid.Column="1"/>
                        <TextBlock Text="Protagonistas:" Grid.Row="4" Grid.Column="0"/>
                        <ItemsControl ItemsSource="{Binding Actores}" Grid.Row="4" Grid.Column="1"/>
                    </StackPanel>
             </Grid>

            <!-- Edición del objeto de negocios ¡¡ESTO ES UNA LÍNEA DE COMENTARIOS EN WPF!! -->

    </Window>

    Y me sale el siguiente error que no sé qué indica:

    'La propiedad de colección 'WPF_EnlaceDatos.Director'.'Filmes' es nula.' (número de línea: '11'; posición de línea: '18').

     

    ¿Qué estoy haciendo mal ahora? Gracias de antemano.

    martes, 29 de marzo de 2011 17:30
  • Hola galvi.

    Si, ya le vas dando algo de cuerpo.

    El error es por que estas enlazando la coleccion 'filmes' de la clase 'Director' pero esta es nula, ya que en ningun momento se inicializa, de modo que tienes que inicializarla.

    de modo que 2 cosas solamente:

    1.- la coleccion 'filmes' se debe inicializar, en un principio, lo logico es en un constructor, de modo que hay que añadir un constructor a la clase director por defecto como este (o algo similar):

        public Director()
        {
          this.Nombre = string.Empty;
          this.Nacionalidad = string.Empty;
          // 1.- inicializar usando la clase 'Filmes'
          this.Filmes = new Filmes().Data; 
          // 2.- inicializar vacio para ser creado por los recursos xaml
          this.Filmes = new ObservableCollection<Film>();
        }
    

    OJO: en este constructor por defecto he puesto 2 inicializaciones posibles, una usando la clase Filmes (ya que si no se usa se puede quitar) y la otra es inicializando la propiedad desde el codigo xaml. 

    Debe comentarse una linea u otra, dependiendo desde donde se quiera inicializar la propiedad, si se usa la 1, se puede quitar el codigo xaml de los recursos con el tag <Director.Filmes>, en caso de usar la 2 opcion, se puede quitar la clase Filmes, ya que solo sirve para inicializar una coleccion.

     

    2.- en el codigo xaml, te falta poner el miembro que sera usado en la coleccion para mostrar como texto en el ListBox, si no se especifica, como la mayoria de veces, por defecto es el tipo del objeto, de modo que el ListBox, debe ser algo asi:

    <ListBox Name="lbFilmes" ItemsSource="{Binding Filmes}" Height="153" DisplayMemberPath="Titulo" />
    

    O en lugar de Titulo, poner el nombre de una propiedad de la clase 'Film' que se quiera mostrar, tambien se puede crear un dataTemplate para mostrar mas de una propiedad en cada fila del listbox o cualquier otra pijadita.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    martes, 29 de marzo de 2011 19:59
  • Hola David, ya lo voy entendiendo. No obstante, no consigo hacerlo funcionar de ninguna de las dos formas que me propones.

    En la primera opción, la de declarar las películas en el codigo c#, no veo ningún resultado, o sea, me sale el Listbox vacío. Te pongo el código de la primera opción:

    XAML:

    <Window x:Class="WPF_EnlaceDatos.EnlaceObjetoNegocio"      
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ejemplo="clr-namespace:WPF_EnlaceDatos"
            Title="Peliculas con varios actores" Height="250" Width="800">
    <!-- Hay que poner en la x:Class 'WPF_EnlaceDatos.EnlaceObjetoNegocio' y en la partial class de c# poner 'EnlaceObjetoNegocio : Window', si no no funciona en enlace a Film. -->
        <Window.Resources>
            <!--<ejemplo:Film x:Key="filmInfiltrados" Titulo="Infiltrados" Genero="Mafia" Oscar="{x:Null}" Calificación="4.7" />-->
            <ejemplo:Director x:Key="Spielberg" Nombre="Steven Spielberg" Nacionalidad="USA">        </ejemplo:Director>
        </Window.Resources>

        <!-- Visualización del objeto de negocios -->
        <Grid  DataContext="{Binding SelectedItem, ElementName=lbFilmes}">
            <Grid.ColumnDefinitions>
            <ColumnDefinition Width="192"/>
            <ColumnDefinition Width="586*" />
        </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
            <RowDefinition Height="177"/>
            <RowDefinition Height="34*" />
        </Grid.RowDefinitions>
            <StackPanel DataContext="{StaticResource Spielberg}" Margin="4,4,0,0">
                    <TextBlock FontSize="14" FontWeight="Bold">Filmes</TextBlock>
                    <ListBox Name="lbFilmes" ItemsSource="{Binding Filmes}" Height="153" DisplayMemberPath="Titulo" />
            </StackPanel>
            <StackPanel Margin="19,21,211,46" Grid.Column="1">
                <TextBlock Text="{Binding Titulo}" FontWeight="Bold" FontSize="14" Grid.ColumnSpan="2"/>
                <TextBlock Text="Género:" Grid.Row="1" Grid.Column="0"/>
                <TextBlock Text="{Binding Genero}" Grid.Row="1" Grid.Column="1"/>
                <TextBlock Text="Oscar:" Grid.Row="2" Grid.Column="0"/>
                <TextBlock Text="{Binding Oscar}" Grid.Row="2" Grid.Column="1"/>
                <TextBlock Text="Calificación:" Grid.Row="3" Grid.Column="0"/>
                <TextBlock Text="{Binding Calificación}" Grid.Row="3" Grid.Column="1"/>
                <!--<TextBlock Text="Protagonistas:" Grid.Row="4" Grid.Column="0"/>
                <ItemsControl ItemsSource="{Binding Actores}" Grid.Row="4" Grid.Column="1"/>-->
            </StackPanel>
        </Grid>

    </Window>

    C#:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.ComponentModel;  /// Para poder declarar el Noficador de cambios de propiedad.
    using System.Collections.ObjectModel; /// Para poder declarar ObservableCollection<string> Filmes---> ARRAY

    namespace WPF_EnlaceDatos
    {
        /// <summary>
        /// Lógica de interacción para MainWindow.xaml
        /// </summary>
        public partial class EnlaceObjetoNegocio : Window
        {
            public EnlaceObjetoNegocio()
            {
                InitializeComponent();
            }
        }
        public class Notificador : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string name)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        //La declaración del tipo FILM va en el código behind C#.
        public enum Genero { Mafia, Drama, Catastrofismo, Aventuras, Comedia, Oeste, CienciaFiccion }

        public class Film : Notificador
        {
            string titulo;
            Director director;
            Genero genero;
            bool? oscar;
            double calificación;
            //public ObservableCollection<string> actores;
            public Film() { }

            public Film(string titulo, Genero genero, bool? oscar, double calificación, Director director)
            {
                this.Titulo = titulo;
                this.Genero = genero;
                this.Oscar = oscar;
                this.Calificación = calificación;
                this.Director = director;
                //this.Actores = actores;
            }
            public string Titulo
            {
                get { return titulo; }
                set
                {
                    if (titulo == value) return;
                    titulo = value;
                    OnPropertyChanged("Titulo");
                }
            }
            public Genero Genero
            {
                get { return genero; }
                set
                {
                    if (genero == value) return;
                    genero = value;
                    OnPropertyChanged("Genero");
                }
            }
            public bool? Oscar
            {
                get { return oscar; }
                set
                {
                    if (oscar == value) return;
                    oscar = value;
                    OnPropertyChanged("Oscar");
                }

            }
            public double Calificación
            {
                get { return calificación; }
                set
                {
                    if (calificación == value) return;
                    calificación = value;
                    OnPropertyChanged("Calificación");
                }
            }
            public Director Director
            {
                get { return director; }
                set
                {
                    if (director == value) return;
                    director = value;
                    OnPropertyChanged("Director");
                }
            }
            //public ObservableCollection<string> Actores {
            //  get { return actores; }
            //  set
            //  {
            //    if (actores == value) return;
            //    actores = value;
            //    OnPropertyChanged("Actores");
            //  }
            //}
        }
        public class Director : Notificador
        {

            string nombre;
            string nacionalidad;
            public ObservableCollection<Film> filmes;
            public Director() { }

            public Director(string nombre, string nacionalidad, ObservableCollection<Film> filmes)
            {
                //Aquí se inicializan las colecciones y las propiedades. Es lo que se llama Constructor.
                this.Nombre = string.Empty;
                this.Nacionalidad = string.Empty;
                //O usamos la opción 1, declarando todo en el código behind de C#; o usamos la opción 2, declarando por aquí la inicialización y el resto en el XAML.
                // 1.- inicializar usando la clase 'Filmes'
                this.Filmes = new Filmes().Data;
                // 2.- inicializar vacio para ser creado por los recursos xaml
                //this.Filmes = new ObservableCollection<Film>();
            }

            public string Nombre
            {
                get { return this.nombre; }
                set
                {
                    if (this.nombre == value) return;
                    this.nombre = value;
                    OnPropertyChanged("Nombre");
                }
            }
            public string Nacionalidad
            {
                get { return this.nacionalidad; }
                set
                {
                    if (this.nacionalidad == value) return;
                    this.nacionalidad = value;
                    OnPropertyChanged("Nacionalidad");
                }
            }

            public ObservableCollection<Film> Filmes
            {
                get { return this.filmes; }
                set
                {
                    if (this.filmes == value) return;
                    this.filmes = value;
                    OnPropertyChanged("Filmes");
                }
            }
        }

        public class Filmes : ObservableCollection<Film>
        {
            // 1.- Usando la clase 'Filmes'
            public ObservableCollection<Film> Data { get; set; }
            public Filmes()
            {
                Data = new ObservableCollection<Film>();
                Data.Add(new Film() { Titulo = "Jurassik Park", Genero = WPF_EnlaceDatos.Genero.Aventuras, Oscar = true, Calificación = 4.0 });
                Data.Add(new Film() { Titulo = "La Lista de Schindler", Genero = WPF_EnlaceDatos.Genero.Drama, Oscar = true, Calificación = 4.2 });
                Data.Add(new Film() { Titulo = "E.T.", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = true, Calificación = 4.1 });
                Data.Add(new Film() { Titulo = "Tiburon", Genero = WPF_EnlaceDatos.Genero.Aventuras, Oscar = false, Calificación = 4.7 });
                Data.Add(new Film() { Titulo = "Color Púrpura", Genero = WPF_EnlaceDatos.Genero.Drama, Oscar = false, Calificación = 4.3 });
                Data.Add(new Film() { Titulo = "Munich", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = true, Calificación = 3.5 });
                Data.Add(new Film() { Titulo = "Encuentro Cercano de Tercer Tipo", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = false, Calificación = 3.0 });
                Data.Add(new Film() { Titulo = "Inteligencia Artificial", Genero = WPF_EnlaceDatos.Genero.CienciaFiccion, Oscar = false, Calificación = 3.8 });
            }
        }
    }

    ¿Qué estoy haciendo mal ahora? Muchas gracias por tu atención y un saludo.

    miércoles, 30 de marzo de 2011 8:32
  • Hola Galvi.

    Vale, estas poniendo la inicializacion en el constructor que no toca,

    En el codigo, tienes estos 2 constructores:

     

    //Constructor por defecto
    public Film() { }
    
    //Constructor sobrecargado
    public Film(string titulo, Genero genero, bool? oscar, double calificación, Director director)
        {
          this.Titulo = titulo;
          this.Genero = genero;
          this.Oscar = oscar;
          this.Calificación = calificación;
          this.Director = director;
          //this.Actores = actores;
        }
    

     

    La inicializacion debe estar en el constructor por defecto, ya que es el que es usado por el sistema de bindings de forma predeterminada, de modo que el constructor con parametros, a no ser que lo necesites para tu programacion, lo puedes quitar si quieres y dejar solo el constructor por defecto.

    De modo que aunque dejes el constructor sobrecargado para cualquier otro uso, el constructor por defecto debe ser algo asi (o como tu quieras inicializarlo):

     public Director()
      {
       this.Nombre = string.Empty;
       this.Nacionalidad = string.Empty;
       // 1.- inicializar usando la clase 'Filmes'
       this.Filmes = new Filmes().Data; 
       // 2.- inicializar vacio para ser creado por los recursos xaml
       this.Filmes = new ObservableCollection<Film>();
      }
    
    

     

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    miércoles, 30 de marzo de 2011 9:31
  • Muchísimas gracias David.

     

    Me ha funcionado perfectamente ahora.

     

    Un saludo!

    miércoles, 30 de marzo de 2011 15:26
  • Ok, galvi.

    Si te funciona todo bien, selecciona una respuesta para cerrar el post y no dejarlo abierto.

    PD.- por cierto, no he visto a Torrente 4 en tu lista de pelis, jejeje.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/

    miércoles, 30 de marzo de 2011 18:55