none
Añadir manejador a evento click de botón dentro de ItemTemplate RRS feed

  • Pregunta

  • Hola a todos,

    Estoy creando un CustomControl que contiene un ListBox, y este en su ItemTemplate tiene un Button. Me encuentro con el problema de que necesito añadir un manejador al evento Click del botón y no lo consigo.

     

    En el código de la clase tengo lo siguiente:

    public override void OnApplyTemplate()
     {
      base.OnApplyTemplate();
      
      DataTemplate dt = ((ListBox)GetTemplateChild("ListDocumentos")).ItemTemplate;
      DependencyObject Do = dt.LoadContent();
      ((Button)((Grid)Do).Children[3]).MouseLeftButtonUp += new MouseButtonEventHandler(DragFile_MouseLeftButtonUp);
      base.MouseLeftButtonUp +=new MouseButtonEventHandler(DragFile_MouseLeftButtonUp);
     }
    

    Y en el código XAML del fichero "generic.xaml" tengo el siguiente código para crear el ListBox:

    <ListBox x:Name="ListDocumentos">
     <ListBox.ItemTemplate>
      <DataTemplate x:Name="LBDataTemplate">
       <Button x:Name="btGuardar" Content="Guardar"/>
      </DataTemplate>
     </ListBox.ItemTemplate>
    </ListBox>
    

     

    Al botón llamado "btGuardar" quiero poder añadirle un manejador para hacer una serie de acciones cuando clicken el botón. Pero con el código que tengo no lo consigo. Si alguien se ha peleado con esto alguna vez, o sabe la respuesta, le estaré agradecido si puede hecharme una mano.

    Gracias.

    • Editado kOtIk-Dev jueves, 2 de septiembre de 2010 8:18
    miércoles, 1 de septiembre de 2010 14:13

Todas las respuestas

  • No es posible agregar el manejador del evento desde un datatemplate, para eso tienes que hacer uso de un comando,

    <Button Command={Binding MyCustomCommand}/>


    Microsoft Certified Technology Specialist .NET 3.5 WPF Application Development
    Proyecto en Codeplex
    World Wide Finalist Imagine Cup 2007
    C#, WPF, WCF
    LinkedIn
    miércoles, 1 de septiembre de 2010 16:19
  • Hola Kotik.

    No se si entiendo bien tu pregunta ¿quieres agregar un evento al boton?.

    Si quieres agregar un evento, lo puedes realizar desde codigo xaml facilmente de 2 formas (a parte de la que te ha dado iRodfraga, que serian 3).

    opcion 1.- la mas facil es añadirlo tal cual:

     

        <ListBox x:Name="ListDocumentos" >
          <ListBox.ItemTemplate>
            <DataTemplate x:Name="LBDataTemplate">
              <Button x:Name="btGuardar" Content="{Binding XPath=Nombre}" Click="btGuardar_Click"/>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>
        <ListBox.Resources>
    

     

    y en el codigo .cs:

     

        private void btGuardar_Click(object sender, System.Windows.RoutedEventArgs e)
        {    	
          MessageBox.Show("boton pulsado");
        }
    

     

     

    Opcion 2.- setteando el evento mediante un estilo, como por ejemplo:

     

        <ListBox x:Name="ListDocumentos" >
          <ListBox.ItemTemplate>
            <DataTemplate x:Name="LBDataTemplate">
              <Button x:Name="btGuardar" Content="{Binding XPath=Nombre}"/>
            </DataTemplate>
          </ListBox.ItemTemplate>
          <ListBox.Resources>
            <Style TargetType="{x:Type Button}">
              <EventSetter Event="Click" Handler="btGuardar_Click"/>
            </Style>
          </ListBox.Resources>
        </ListBox>
    

     

    Y en el codigo .cs igual que en la opcion 1.

    opcion 3.- Con comandos puedes hacer algo como esto

     

        <ListBox x:Name="ListDocumentos">
          <ListBox.ItemTemplate>
            <DataTemplate x:Name="LBDataTemplate">
              <Button x:Name="btGuardar" Content="{Binding XPath=Nombre}" Command="ApplicationCommands.Help"/>
            </DataTemplate>
          </ListBox.ItemTemplate>
          <ListBox.CommandBindings>
            <CommandBinding Command="{x:Static ApplicationCommands.Help}" Executed="btGuardar_Click" />
          </ListBox.CommandBindings>
        </ListBox>
    

     

    Obviamente deberias de crearte tu propio comando en caso de que no exista en los disponibles por WPF/Silverlight, yo he usado Help como prueba.

    Ya me contaras si es lo que buscabas

     


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    miércoles, 1 de septiembre de 2010 18:44
  • Veamos, primero por partes.

    Nos comentas que quieres hacer un control de usuario, sin embargo, para que te aparezca el generic.xaml es creando un CustomControl, que no son lo mismo.

    1.- El Generic.xaml es un "ResourceDictionary", por ende te marca error al agregar el controlador de eventos.

    2.- En un control de usuario "UserControl" es posible hacer la referencia al controlador de eventos dado que este estaría en codigo detras.

    En el caso 1 solo te queda por utilizar un binding al command.

    En el caso 2 puedes hacer lo que david te explica.


    Microsoft Certified Technology Specialist .NET 3.5 WPF Application Development
    Proyecto en Codeplex
    World Wide Finalist Imagine Cup 2007
    C#, WPF, WCF
    LinkedIn
    miércoles, 1 de septiembre de 2010 21:56
  • No es posible agregar el manejador del evento desde un datatemplate, para eso tienes que hacer uso de un comando,

    <Button Command={Binding MyCustomCommand}/>


    Microsoft Certified Technology Specialist .NET 3.5 WPF Application Development
    Proyecto en Codeplex
    World Wide Finalist Imagine Cup 2007
    C#, WPF, WCF
    LinkedIn

    No había oido hablar de los comandos, llevo relativamente poco programando con Silverlight. Buscaré información al respecto. Muchas gracias.
    jueves, 2 de septiembre de 2010 7:13
  • Tienes razón iRodfraga, perdona que haya creado confusion, pues hace apenas 2 semanas que empecé con Silverlight y aún confundo conceptos. Como tu bien dices, estoy creando un CustomControl.

     

    David_Gonzalez:

     

    Con tu opción 2, he añadido:

     <ListBox.Resources>
      <Style TargetType="{x:Type Button}">
       <EventSetter Event="Click" Handler="btGuardar_Click"/>
      </Style>
     </ListBox.Resources>
    

    Pero me da dos errores:

    1.- "{x:Type Button}" -->The type 'x:Type' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built.

     

    2.- <EventSetter -->The type 'EventSetter' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built.

    Creo que esto será debido a que lo que estoy desarrollando es en Silverlight y no en WPF, fallo por mi parte por no decirlo.

    El primer error consigo solucionarlo añadiendo la referencia

    xmlns:bt="clr-namespace:System.Windows.Controls;assembly=System.Windows" 
    

    Y posteriormente modificando el  tu opción 2 así:

    <ListBox.Resources>
     <Style TargetType="bt:Button" >
      <EventSetter Event="Click" Handler="btGuardar_Click"/>
     </Style>
    </ListBox.Resources>
    

    Solo me queda probar los Binding Commands y os cuento que tal.

     

    Gracias!

    jueves, 2 de septiembre de 2010 7:45
  • Buenos días,

     

    Debo deciros que llevo todo el día de ayer y el de hoy haciendo pruebas y buscando como solucionar el problema que se me presenta, con las soluciones que me habéis dicho.

     

    O yo soy muy torpe o ninguna solución me ha funcionado. Si alguien se brinda a ayudarme le estaré muy agradecido.

    El problema sigue siendo el inicial, tengo un CustomControl con un ListBox. El ListBox tiene un botón en su ItemTemplate. Este botón quiero poder manejar el evento click, pero se me hace imposible.

     

    Gracias.

    viernes, 3 de septiembre de 2010 10:35
  • Hola Kotik.

    Ok, como no indicaste la tecnologia, puse los ejemplos para WPF.

    En silverlight la opcion 1 y 3 funcionan de la misma forma y no hay problema, pero la opcion 2 es una de las cosas que diferencian Silverlight de WPF actualmente.

    En silverlight solo a partir de la version 4 se puede usar el tag TargetType para indicar el tipo de control de destino y su uso es como has indicado, se tiene que poner el tipo unicamente (sin el x:Type), de modo que quedaria algo asi:

    TargetType = "Button".

    No obstante esto no nos sirve, ya que tampoco dispone del eventSetter de la misma forma que en WPF en los estilos, en Silverlight, en lugar de ello, se deben usar comportamientos conocidos como 'Behaviors'. bien, es algo complicado en primera instancia y tienen bastante miga, desde lo mas sencillito hasta uno que te crees tu mismo. (Mediante expression blend, se pueden insertar muy facilmente).

    Bueno te expongo el codigo que reemplaza la opcion 2 haciendo uso de comportamientos:

    codigo xaml:

     

    		<ListBox x:Name="ListDocumentos" >
    			<ListBox.ItemTemplate>
    				<DataTemplate x:Name="LBDataTemplate">
    					<Button x:Name="btGuardar" Content="{Binding email}" >
    						<i:Interaction.Triggers>
           <i:EventTrigger EventName="Click">
            <ei:CallMethodAction MethodName="btGuardar_Click" TargetObject="{Binding ElementName=MainUserControl}" />
    							</i:EventTrigger>
    						</i:Interaction.Triggers>
    					</Button>
    				</DataTemplate>
    			</ListBox.ItemTemplate>
    		</ListBox>
    

     

    en este codigo hay que tener en cuenta que la propiedad 'TargetObject' es el control que implementa el evento (en este ejemplo el UserControl que contiene el ListBox)

    codigo cs

     

      public void btGuardar_Click(object sender, System.Windows.RoutedEventArgs e)
      {
       MessageBox.Show(((Button)e.OriginalSource).Content.ToString());
      }
    

     

    este es el evento declarado en el UserControl.

    (NOTA: el evento debe ser publico para que lo encuentre el comportamiento)

     

    Se me olvida comentar que se deben incluir los siguientes namespaces en el codigo xaml:

      xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
      xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 

     

    Ya me contaras como te va..

     


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    • Propuesto como respuesta CorsarioVasco martes, 7 de septiembre de 2010 20:37
    martes, 7 de septiembre de 2010 8:39