Inicio > .NET > [Silverlight] Issue al extender algún control, mis controles dentro de este se generan nulos. Silverlight 3 y 4

[Silverlight] Issue al extender algún control, mis controles dentro de este se generan nulos. Silverlight 3 y 4

Buenas,

Les platico de que va esto, imaginen que hacen una aplicación en donde tendrán un UserControl contenedor de otros Controles, como si fuera un Grid, StackPanel, etc. pero propio, es decir;  que nosotros lo creamos con estilo, funcionalidad y forma.

Primero creamos nuestro control, agregamos un nuevo UserControl al que llamaremos ContenedorPrincipal con el siguiente código XAML y cs.

XAML.

<Grid>
        <Rectangle Fill="Green" StrokeThickness="0" 
                   RadiusX="5"
                   RadiusY="5"  Margin="0" 
                   Canvas.ZIndex="-1"/>
        <Grid Margin="0">
            <Grid >
                <TextBlock x:Name="mensaje" Text="Mensaje" 
                           TextWrapping="Wrap" 
                           FontWeight="Bold" 
                           Foreground="White" Margin="0,2,0,0"                            
                           TextAlignment="Right" 
                           VerticalAlignment="Top" 
                           HorizontalAlignment="Center"                      >
                </TextBlock>
            </Grid>
            <Grid Margin="0,20,0,0">
                <StackPanel Margin="5,2" x:Name="contenedor" 
                            Canvas.ZIndex="2" />
                <Rectangle StrokeThickness="0" RadiusX="5" 
                           RadiusY="5" Margin="2" 
                           Fill="White" />
            </Grid>
        </Grid>
    </Grid>

Code Behind .cs

public string Texto
       {
           get { return mensaje.Text; }
           set { mensaje.Text = value; }
       }

       public StackPanel ControlHijo
       {
           get 
           {
               return contenedor.Children[0] as StackPanel;
           }
           set
           {
               contenedor.Children.Clear();
               contenedor.Children.Add(value);
           }
       }

Y nuestro control se ve así:

imageYa con el control, pensamos en reutilizarlo y dentro de el colocar todos los controles que necesitemos, de cualquier tipo, veamos como lo usariamos en una pagina xaml. Esto se haría así:

Agregamos la referencia del ensamblado de nuestro proyecto en el XAML:

xmlns:t="clr-namespace:IssueSilverlight"

luego dentro del Grid agregamos el control así:

        
<t:ContenedorPrincipal Texto="Mensaje del Contenedor Principal">
    <t:ContenedorPrincipal.ControlHijo>
        <StackPanel>
            <Button x:Name="botonPrueba" Content="Hola Mundo" 
                    Margin="5"
                        Width="100"/>
        </StackPanel>
    </t:ContenedorPrincipal.ControlHijo>
</t:ContenedorPrincipal>

Hasta este momento todo bien, si al boton que agregamos dentro del stackPanel le agregamos un evento como el Loaded, Click, etc, vean lo que sucede. Hacemos la prueba con el Loaded

private void botonPrueba_Loaded(object sender, RoutedEventArgs e)
{
    botonPrueba.Content = "nuevo mensaje";
}

Vean lo que sucede al correr la aplicación:

image

Me dice que mi botonPrueba no se ha creado y que es nulo :S, alguien me puede decir porque, si se supone que es su mismo evento Loaded. Por un momento pensé que era cosa de como se generan los controles en Silverlight, que primero se crea el Control Padre y por ultimo los hijos, pero NO, esto esta mal.

Ustedes que harían si les pasa esto, seguramente buscar en google, no?,pero que buscarían: “Object referece not set to an instance of an object”, no verdad, la verdad es que no tenemos muchas herramientas para buscar como resolver esto.

Bueno ps aquí mi solución, por si les pasa esto. Sin ser experto en la materia, les puedo decir que al parecer el problema es con el código XAML, al parecer no permite crear instancias de controles dentro de un contenedor como el que creamos, es decir; para el xaml nuestro control botonPrueba realmente no existe, esto al parecer por el x:Name, que aunque no nos marca error sucede. Es más si hacen esto en WPF les marca un error jajaja. “Qué cosas no?”

Entonces mi solución es, agregar al proyecto un archivo de código y crear nuestro control a patin, en puro code behind, claro nuestra clase debe heredar de UserControl e implementar una interface de ISupportInitialize, solo para Silverlight 4 porcierto jaja.

Código de mi control sin archivo .xaml

public class ContenedorCodeBehind : UserControl, ISupportInitialize
{
    private TextBlock mensaje;

    private StackPanel contenedor;

    public void BeginInit()
    {
        Grid gridPrincipal = new Grid();

        //Rectangulo
        Rectangle rectangle = new Rectangle();
        rectangle.Fill = new SolidColorBrush(Colors.Green);            
        rectangle.RadiusX = 5;
        rectangle.RadiusY = 5;
        Canvas.SetZIndex(rectangle, -1);            
        gridPrincipal.Children.Add(rectangle);

        //Grid que deberia Ser DockPanel
        Grid dockPanel = new Grid();

        Grid grid1 = new Grid();

        #region TextBlock

        //TextBlock
        mensaje = new TextBlock();
        mensaje.Text = "Mensaje";
        mensaje.TextWrapping = System.Windows.TextWrapping.Wrap;
        mensaje.FontWeight = FontWeights.Bold;
        mensaje.Foreground = new SolidColorBrush(Colors.White);
        mensaje.Margin = new Thickness(0, 2, 0, 0);
        mensaje.TextAlignment = TextAlignment.Right;
        mensaje.RenderTransformOrigin = new Point(0, 0);
        mensaje.HorizontalAlignment = HorizontalAlignment.Center;
        mensaje.VerticalAlignment = VerticalAlignment.Top;

        #endregion TextBlock

        grid1.Children.Add(mensaje);
        dockPanel.Children.Add(grid1);


        Grid grid2 = new Grid();
        grid2.Margin = new Thickness(0, 20, 0, 0);
        contenedor = new StackPanel();
        contenedor.Margin = new Thickness(5, 2, 5, 2);
        Canvas.SetZIndex(contenedor, 2);
        grid2.Children.Add(contenedor);


        Rectangle rec = new Rectangle();
        rec.StrokeThickness = 0;
        rec.RadiusX = 5;
        rec.RadiusY = 5;
        rec.Margin = new Thickness(2);

        rec.Fill = new SolidColorBrush(Colors.White);            

        grid2.Children.Add(rec);
        dockPanel.Children.Add(grid2);
        gridPrincipal.Children.Add(dockPanel);

        Content = gridPrincipal;
    }

    public void EndInit()
    {
        //throw new NotImplementedException();
    }

    public StackPanel ControlHijo
    {
        get
        {
            return contenedor.Children[0] as StackPanel;
        }

        set
        {
            contenedor.Children.Clear();
            contenedor.Children.Add(value);
        }
    }

    public string Texto
    {
        get
        {
            return this.mensaje.Text;
        }
        set
        {
            this.mensaje.Text = value;
        }
    }
    
    
}

Si se dan cuenta es el mismo control solo que sin el archivo .XAML. Ahora lo agregamos a nuestra pagina como el anterior y comentamos el código del otro control e incluso agregamos el mismo botonPrueba.

<Grid x:Name="LayoutRoot" Background="White">
    <t:ContenedorCodeBehind Texto="Control sin archivo .xaml">
        <t:ContenedorCodeBehind.ControlHijo>
            <StackPanel>
                <Button x:Name="botonPrueba" Content="Hola Mundo"
                        Margin="5" Loaded="botonPrueba_Loaded"
                    Width="100"/>
            </StackPanel>
        </t:ContenedorCodeBehind.ControlHijo>
    </t:ContenedorCodeBehind>
    <!--<t:ContenedorPrincipal Texto="Mensaje del Contenedor Principal">
        <t:ContenedorPrincipal.ControlHijo>
    <StackPanel>
        <Button x:Name="botonPrueba" Content="Hola Mundo" 
                Margin="5" Loaded="botonPrueba_Loaded"
                    Width="100"/>
    </StackPanel>
</t:ContenedorPrincipal.ControlHijo>
    </t:ContenedorPrincipal>-->
</Grid>

Y si ahora ejecutamos la aplicación… Sorpresa!!!! falla de nuevo jajajaja, naaa ya todo funciona correctamente😀, y ya podemos reutilizar nuestro control contenedor. Eso me pasa por querer hacer tantas cosas desde xaml a patín, mejor usar Expression, aunque este error pasa igual si lo usan😛. Para que vena que es verdad un video con los dos controles y el código fuente.

Video.

Proyecto.

image

Que les sea leve el día!!!

Categorías:.NET
  1. franco
    agosto 6, 2010 a las 4:50 pm

    que tal nor me gusta tu blog esta chido oye podrías poner algunos ejemplos sobre como realizar presentaciones ppt pero en silverlight gracias

  1. No trackbacks yet.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: