Social Icons

lunes, 22 de noviembre de 2010

Code Snippets en C# y ¿Por qué mi binding TwoWay no funciona?

Bien, respecto al problema de los bindings TwoWays, hoy he aprendido que no funcionan por arte de magia, si no que cada propiedad tiene que implementar la notificación de cambio de propiedad... vamos lo que viene a ser la INotifyPropertyChanged. No es muy complicado, pero se tarda un poco más que en declarar la propiedad con notificación, por cierto viene todo bien explicado aquí, y esto nos lleva al tema de los Code Snippets.

Lo de crear Code Snippets (Fragentos de Código) es una de esas cosas que siempre he dejado para aprender más tarde y al final nunca he aprendido... hasta hoy, que tenía que hacer un objeto con más de treinta propiedades que lanzasen el PropertyChanged y no he podido retrasarlo más.

Para aumentar mi productividad he perdido un poco el tiempo y me he creado un Code Snipplet para las propiedades que implementan el INotifyPropertyChanged, lo he llamado propNot en otro alarde de originalidad sin precedentes.
Para ello, en Visual Studio me fui a Tools y desde allí al Code Snippets Manager. Una vez allí seleccioné C# y luego copié habilmente la dirección de la carpeta de los Code Snippets de usuario (My Code Snippets).


Me situé en esa carpeta, creé un fichero .snippet y escribí esto:
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
 <CodeSnippet Format="1.0.0">
  <Header>
   <Title>propNot</Title>
   <Shortcut>propNot</Shortcut>
   <Description>Code snippet for properties with NotifyPropertyChanged</Description>
   <Author>Chan</Author>
   <SnippetTypes>
    <SnippetType>Expansion</SnippetType>
    <SnippetType>SurroundsWith</SnippetType>
   </SnippetTypes>
  </Header>
  <Snippet>
   <Declarations>
    <Literal>
     <ID>privName</ID>
     <Default>privName</Default>
     <ToolTip>Private name of the property</ToolTip>
    </Literal>
    <Literal>
     <ID>pubName</ID>
     <Default>pubName</Default>
     <ToolTip>Public name of the property</ToolTip>
    </Literal>
    <Literal>
     <ID>type</ID>
     <Default>string</Default>
     <ToolTip>Type of the property</ToolTip>
    </Literal>
   </Declarations>
   <Code Language="csharp"><![CDATA[private $type$ $privName$;
        
    public $type$ $pubName$
    {
     get { return $privName$; }

     set
     {
      $privName$ = value;
      // Call NotifyPropertyChanged when the property is updated
      NotifyPropertyChanged("$pubName$");
     }
    }]]>
   </Code>
  </Snippet>
 </CodeSnippet>
</CodeSnippets>

Probado y funcionando, tanto el binding TwoWay como los Code Snippets. Ahora que sé cómo se hace lo voy a hacer muy a menudo. --EDITO-- Mentí, no los hago a menudo porque soy MUY flojo, pero sí que uso mucho este otro snippet:
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
 <CodeSnippet Format="1.0.0">
  <Header>
   <Title>INotify region with the necessary methods to implement the interface</Title>
   <Shortcut>inotifyregion</Shortcut>
   <Description>Creates region with the necessary methods to implement the interface INotifyPropertyChanged</Description>
   <Author>Jose Sanchez</Author>
   <SnippetTypes>
    <SnippetType>Expansion</SnippetType>
    <SnippetType>SurroundsWith</SnippetType>
   </SnippetTypes>
  </Header>
  <Snippet>
   <Declarations />
   <Code Language="csharp"><![CDATA[#region INotifyMethods
        // Declare the event
        public event PropertyChangedEventHandler PropertyChanged;

        // Create the OnPropertyChanged method to raise the event
        protected void NotifyPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion]]>
   </Code>
  </Snippet>
 </CodeSnippet>
</CodeSnippets>

No hay comentarios:

martes, 9 de noviembre de 2010

Cambiando el NewValue en el PropertyChangedCallback

Normalmente no escribo sobre Silverlight, básicamente es por dos razones, la primera es que todo viene perfectamente explicado en un montón de blogs justo al contrario que SharePoint y la segunda es porque tampoco trabajo tanto con Silverlight como para encontrarme problemas. Era perfecto hasta que lo conocí, como tantas otras cosas...


Últimamente estoy teniendo que usar bastante esta tecnología casi nueva para mí y ya desfasada para Microsoft y se me plantean dudas, como por ejemplo la de hoy.

Estaba creando un botón para añadirlo a una DataGrid como DataGridTemplateColumn y necesitaba crearme una DependencyProperty para poder hacer el Binding, hasta aquí todo más o menos claro, pero en el último momento cuando ya me veía victorioso me surgió una duda... si la propiedad (una URL en este caso) no cumple con los requisitos que yo quiero ¿Cómo hago para modificar el NewValue en el mismo PropertyChangedCallback?

El truco está en llamar a SetValue, que no dispara el evento, porque si no obviamente crearíamos un bucle infinito. Algo así.
public string CommentsURL
{
    get { return (string)GetValue(CommentsURLProperty); }
    set { SetValue(CommentsURLProperty, value); }
}

public static readonly DependencyProperty CommentsURLProperty =
    DependencyProperty.Register("CommentsURL", typeof(string), typeof(ButtonComments),
    new PropertyMetadata(new PropertyChangedCallback(ChangedURL)));

private static void ChangedURL(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    try
    {
        string url = e.NewValue.ToString().Split(',')[0];
        new Uri(url);
        d.SetValue(e.Property, url);

        (d as ButtonComments).IsEnabled = true;
    }
    catch
    {
        (d as ButtonComments).IsEnabled = false;
    }
}
Nótese la sutileza del código siempre intentando evitar una excepción antes de que se produzca.


Al final, por si alguien siente curiosidad, el webpart ha quedado así:


"Los intelectuales arreglan los problemas, los genios los evitan."

No hay comentarios: