none
INotifyPropertyChanging y Blendability RRS feed

  • Pregunta

  • Buenas de nuevo,

    Siento escribir para quejarme siempre, pero mirandolo desde otro punto de vista cabe pensar que si todos los dias trabajo con tecnología Microsoft y me quejo tan de cuando en cuando es pq en mi dia a dia disfruto continuamente de las bondades que ofrecen dichas tecnologías. Lamentablemente de esta parte positiva no suele quedar registro en los foros :))

    Esta vez os escribo porque me he encontrado con que cuando utilizo en mi viewmodel una propiedad con una clase de dominio que implenta INotifyPropertyChanging, dicho ViewModel deja de ser "Blendable".

    Sin embargo Blend si soporta que dicha clase implemente INotifyPropertyChanged.

    El principal motivo por el cual uso INotifyPropertyChanging es pq tengo entendido que ayuda a optimizar las operaciones del DataContext que accede a SQLCE.

    ¿Hay Alguna forma de hacer que Blend se trague una clase que implemente INotifyPropertyChanging o tengo que restirngirme a INotifyPropertyChanged si quiero estos ViewModels Blendables?

    Un saludo!

    viernes, 18 de noviembre de 2011 9:04

Todas las respuestas

  • Buenas Sergio.

    La queja es el motor del avance tio, si todos decimos que si con la cabeza como burros y no nos quejamos y encontramos problemas y fallos, Windows Phone no avanzará NUNCA!! Así que, desde este punto de vista, estas haciendo un muy buen trabajo empujando los límites y haciendo que la plataforma crezca :)

    Al lío!!

    He implementado INotifyPropertyChanging en una clase vacia con un constructor y la he establecido como datacontext de una ventana y me sigue funcionando perfectamente. Le he añadido una propiedad que lance el evento PropertyChanging y un textbox en la página enlazado a ella que actualice la propiedad y todo me funciona bien... ¿Seguro que es cosa del INotifyPropertyChanging? y no algún efecto de otra parte del código? ¿Puedes reproducirlo en un proyecto pequeño y poner el codigo por aquí para verlo?

    Un saludote!


    MCTS - .NET 4.0 Windows Applications
    MCTS - .NET 4.0 Data Access
    MCTS - .NET 4.0 Service Communication Applications
    MCPD - .NET 4.0 Windows Developer
    Visita mi Blog en Geeks.ms
    Sigueme en Twitter
    sábado, 19 de noviembre de 2011 10:45
    Moderador
  • Me alegro de que pensemos igual Josue :)
    Respecto al pseudoproblema :). Lo he mirado y es automático comento la interface INotifyPropertyChanging.
        public class Pedido: 
            // INotifyPropertyChanging,
              INotifyPropertyChanged
    
    Comento el código encargado de lanzar el evento
      /*
        #region INotifyPropertyChanging
            private static PropertyChangingEventArgs emptyChangingEventArgs <br/>					= new PropertyChangingEventArgs(String.Empty);
    
            public event PropertyChangingEventHandler PropertyChanging;
    
            protected virtual void SendPropertyChanging()
            {
                if ((this.PropertyChanging != null))
                {
                    this.PropertyChanging(this, emptyChangingEventArgs);
                }
            }
    		
        #endregion
    */
    

    Y comento las llamadas al método anterior:
        public int Codigo
        {
            get { return _Codigo; }
            set
            {
                if (_Codigo != value)
                {
    		this.OnCodigoChanging(value);
                    //this.SendPropertyChanging();
                    this._Codigo = value;
                    this.SendPropertyChanged("Codigo");
                    this.OnCodigoChanged();					
                }
            }
        }
    
    Tras hacer esto en Blend todo funciona correctamente. Si descomento lo comentado va mal.
    Describo mejor que quiere decir lo de "va mal":
    Inicialmente aparentemente funciona bien (no da ninguna excepción) Blend no devuelve ningún mensaje al cargar la vista. El problema se da cuando tienes un VM que muestra una propiedad de un tipo que implementa IPropertyChanging e IPropertyChanged y en el cconstructor asignas a dicha propiedad una nueva instancia de su tipo.
    Debugueando Blend en tiempo de diseño, veo que el problema se da exactamente cuando en el constructor del ViewModel crea la instacia del tipo que implementa IPropertyChanging e IPropertyChanged y se la asigna a la correspondiente propiedad del ViewModel. En ese momento se da la excepción que Blend silenciosamente saca en la solapa de mensajes y por supuesto la vista mostrada en Blend no muestra las propiedades "bindeadas" del objeto que se creó cuando se dió el error.
    Ando algo liado, si con este intento de descripción del problema no es posible reproducirlo en unos dias envio un ejemplo...
    Un saludote jejeje  :))))



    sábado, 19 de noviembre de 2011 14:38
  • Hola de nuevo,

    He encontrado un momento para hacer un ejemplo sencillo que provoca el error que comente:
     
    Este es mi archivo app.xaml
    <Application 
        x:Class="SQLServer.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
        xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
    
        <!--Application Resources-->
        <Application.Resources>
            <vm:ViewModelLocator xmlns:vm="clr-namespace:SQLServer.Model"
                                 x:Key="Locator" />        
        </Application.Resources>
    
        <Application.ApplicationLifetimeObjects>
            <!--Required object that handles lifetime events for the application-->
            <shell:PhoneApplicationService 
                Launching="Application_Launching" Closing="Application_Closing" 
                Activated="Application_Activated" Deactivated="Application_Deactivated"/>
        </Application.ApplicationLifetimeObjects>
    
    </Application>
    

    Este el archivo MaingPage.xaml que carga en el datacontext un objeto que implementa INotifyPropertyChanging
     
    <phone:PhoneApplicationPage 
        x:Class="SQLServer.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
        xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
        FontFamily="{StaticResource PhoneFontFamilyNormal}"
        FontSize="{StaticResource PhoneFontSizeNormal}"
        Foreground="{StaticResource PhoneForegroundBrush}"
        SupportedOrientations="Portrait" Orientation="Portrait"
        shell:SystemTray.IsVisible="True"
        DataContext="{Binding Login, Mode=OneWay, Source={StaticResource Locator}}">
    
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="80"></RowDefinition>
            </Grid.RowDefinitions>
    
            <TextBox Text="{Binding Nombre, Mode=OneTime}" ></TextBox>
    
        </Grid>
    
    </phone:PhoneApplicationPage>
    

    El codebehind no lo muestro pq no he insertado código en el.
    Este es el ViewModelLocator.cs simple que registro como recurso en el App.xaml
    using System;
    using System.Linq;
    using Microsoft.Phone.Controls;
    using System.ComponentModel;
    
    namespace SQLServer.Model
    {
        public class ViewModelLocator
        {
            public ViewModelLocator()
            { 
                _Login=new Login();
                
                _Login.Nombre="Pepe";
            }
    
            private Login _Login;
            public Login Login { get { return _Login; } }
    
        }
    }
    

    Y finalmente es la clase Login que implementa INotifyPropertyChanging y que asigno como datacontext del MainPage.xaml
    using System;
    using System.ComponentModel;
    
    
    namespace SQLServer.Model
    {
        public class Login : INotifyPropertyChanged, INotifyPropertyChanging
        {
    
            #region Properties
    
            public const string NombrePropertyName = "Nombre";
            private string _Nombre = "";
            public string Nombre
            {
                get
                {
                    return _Nombre;
                }
    
                set
                {
                    this.SendPropertyChanging();
                    this._Nombre = value;
                    this.SendPropertyChanged("Nombre");
                }
            }
    
            #endregion
    
            #region INotifyPropertyChanging
            
            private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
    
            public event PropertyChangingEventHandler PropertyChanging;
            
            protected virtual void SendPropertyChanging()
            {
                
                if ((this.PropertyChanging != null))
                {
                    this.PropertyChanging(this, emptyChangingEventArgs);
                }
                
            }        
    
            #endregion
         
            #region INotifyPropertyChanged
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void SendPropertyChanged(String propertyName)
            {
                if ((this.PropertyChanged != null))
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
    
            #endregion
        }
    }
    
    
    Si compilamos y a continuación desde VS2010 accedemos en la vista gráfica al archivo MainPage.xaml obtenemos el siguiente error:
    "Error 3 Cannot create an instance of "ViewModelLocator". C:\PROYECTOS\SQLServerCESample\SQLServerSample\SQLServer\app.xaml 10 9 SQLServer"
    Sin embargo si comento las líneas que implementan el interface INotifyPropertyChanging el archivo MainPage.xaml carga sin problemas en vista de diseño.
    Este es el archivo Login.cs con las líneas comentadas para que funcione sin problemas:
    using System;
    using System.ComponentModel;
    
    
    namespace SQLServer.Model
    {
        public class Login : INotifyPropertyChanged //, INotifyPropertyChanging
        {
    
            #region Properties
    
            public const string NombrePropertyName = "Nombre";
            private string _Nombre = "";
            public string Nombre
            {
                get
                {
                    return _Nombre;
                }
    
                set
                {
            //        this.SendPropertyChanging();
                    this._Nombre = value;
                    this.SendPropertyChanged("Nombre");
                }
            }
    
            #endregion
            /*
            #region INotifyPropertyChanging
            
            private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
    
            public event PropertyChangingEventHandler PropertyChanging;
            
            protected virtual void SendPropertyChanging()
            {
                
                if ((this.PropertyChanging != null))
                {
                    this.PropertyChanging(this, emptyChangingEventArgs);
                }
                
            }        
    
            #endregion
            */
    
            #region INotifyPropertyChanged
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void SendPropertyChanged(String propertyName)
            {
                if ((this.PropertyChanged != null))
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
    
            #endregion
        }
    }
    
    

    Un saludo!
    domingo, 11 de diciembre de 2011 21:27