none
Behavior para ListBox Windows Phone RRS feed

  • Pregunta

  • Hola a todos!!

    Estoy teniendo problemas para implentar un behavior.  El tema es que estoy empezando con el MVVM y tengo un proyecto que utiliza un control ListBox, lo que quiero es añadir un Behavior al ListBox y que cuando seleccione un elemento del control ListBox se lance un comando (Command) desde el Behavior con el objetivo que ese comando contenga una referencia de ICommand pertenciente a una proiedad de mi ViewModel. De esta manera lo que hago es  que cuando se seleccione un elemento de mi ListBox se ejecute un método en mi VIewModel. He realizo pruebas por separado y funciona pero cuando lo hago junto me casca!! Excepción [System.Windows.Markup.XamlParseException] {"Set property 'PruebaComando.MisBehaviors.BehaviorParaList.Command'
    threw an exception. [Line: 32 Position: 66]"}.  He creado especificamente un miproyecto para implementar esto:

    La Vista:

    <phone:PhoneApplicationPage
        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"
       
        xmlns:local="clr-namespace:PruebaComando.ViewModel"
       
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:PruebaComando_MisBehaviors="clr-namespace:PruebaComando.MisBehaviors"
        x:Class="PruebaComando.MainPage"
       
        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">

        <phone:PhoneApplicationPage.DataContext>
            <local:VM_MainPage/>
        </phone:PhoneApplicationPage.DataContext>

        <!--LayoutRoot es la cuadrícula raíz donde se coloca todo el contenido de la página-->
        <Grid x:Name="LayoutRoot" Background="Transparent">
         
            <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

                <ListBox  x:Name="MenuLista" Margin="0,0,-12,0">
                 <i:Interaction.Behaviors>
                        <PruebaComando_MisBehaviors:BehaviorParaList Command="{Binding MiComando}"/>
                 </i:Interaction.Behaviors>
                    <StackPanel Orientation="Horizontal" Margin="0,0,0,17">
                        <TextBlock Text="opcion1"/>
                    </StackPanel>

                    <StackPanel Orientation="Horizontal" Margin="0,0,0,17">
                        <TextBlock Text="opcion2"/>
                    </StackPanel>
                </ListBox>

            </Grid>
        </Grid>

    </phone:PhoneApplicationPage>

      

    EL Behavior:

    namespace PruebaComando.MisBehaviors
    {
        public class BehaviorParaList : Behavior<System.Windows.Controls.ListBox>
        {

            ListBox ltb;

            private static readonly DependencyProperty CommandProperty
                      = DependencyProperty.Register("Command",
                                                    typeof(ICommand),
                                                    typeof(Object),
                                                    null);

            public ICommand Command
            {
                get
                {
                    return (ICommand)this.GetValue(CommandProperty);
                }
                set
                {
                    this.SetValue(CommandProperty, value);
                }
            }

            public BehaviorParaList()
            {
                //  CommandoList.CanExecuteChanged += new EventHandler(CommandoList_CanExecuteChanged);
            }

            //void CommandoList_CanExecuteChanged(object sender, EventArgs e)
            //{
            //    //para refrescar la interfaz de usuario
            //    //podría a dependiendo del valor de un parámetro deshabilitar la lista. por ejemplo
            //}


            protected override void OnAttached()
            {
                base.OnAttached();
                AssociatedObject.Loaded += AssociatedObject_Loaded;
            }

            void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
            {
                ltb = (ListBox)sender;
                ltb.SelectionChanged += new SelectionChangedEventHandler(ltb_SelectionChanged);
            }

            void ltb_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                Command.Execute(null);
            
            }


            protected override void OnDetaching()
            {
                base.OnDetaching();
                ltb.SelectionChanged -= ltb_SelectionChanged;
                AssociatedObject.Loaded -= AssociatedObject_Loaded;
            }
           
        }
    }

    El ViewModel

    namespace PruebaComando.ViewModel
    {
        public class VM_MainPage
        {
          private MiComando comando;

            public MiComando Comando
            {
                get { return comando; }
                set { comando = value; }
            }

            public VM_MainPage()
            {
                comando = new MiComando();
            }
        }
    }

    La clase del Comando

    namespace PruebaComando
    {
        public class MiComando:ICommand
        {

            public MiComando() {}

            bool ICommand.CanExecute(object parameter)
            {
                return true;
            }

            public event EventHandler CanExecuteChanged;

            void ICommand.Execute(object parameter)
            {
                MessageBox.Show("Hola Mundo desde un comando!");

            }
        }

    }

    Por favor podéis echar un vistazo a ver si veís algo raro.  Muchas gracias de verdad!!!!

     He subido  proyecto a
    https://skydrive.live.com/redir?resid=E99AB99D0960D4F8!151 (proyecto que contiene el exclusivamente el código mencionado)

    *NOta: Utilizaria una clase "DelegateCommand" (en mi proyecto original la uso) pero me da el mismo error. Aquí he hecho este ejemplo sin Delegate Comand para que se vea mas facil. (el error es el mismo con Delegate Comand)


    Santiago Pomar


    sábado, 16 de junio de 2012 16:02

Respuestas

  • Hola!

    Varias cosas que tienes incorrectas en tu código:

    En primer lugar, en tu ViewModel, Expon una propiedad de tipo ICommand, no MiComando, y solo con Get, no necesitas el Set:

    public ICommand Comando
    {
        get { return comando; }
    }

    En el xaml de la mainPage, no enlazas a MiComando, tienes que enlazar a tu propiedad Comando:

    <i:Interaction.Behaviors>
        <PruebaComando_MisBehaviors:BehaviorParaList Command="{Binding Comando}" />
    </i:Interaction.Behaviors>

    Y en tu comando, cuando registrar la dependency property, el tipo de su owner no puede ser Object, debe ser el behavior y el tipo de la propiedad debe ser ICommand que es el valor que te va a llegar:

    private static readonly DependencyProperty CommandProperty
                = DependencyProperty.RegisterAttached("Command",
                                            typeof(ICommand),
                                            typeof(BehaviorParaList), null);

    Con estos cambios, te funcionará perfectamente.

    Un saludo!


    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

    • Marcado como respuesta Santiago Pomar lunes, 18 de junio de 2012 6:55
    lunes, 18 de junio de 2012 5:58
    Moderador

Todas las respuestas

  • Hola!

    Varias cosas que tienes incorrectas en tu código:

    En primer lugar, en tu ViewModel, Expon una propiedad de tipo ICommand, no MiComando, y solo con Get, no necesitas el Set:

    public ICommand Comando
    {
        get { return comando; }
    }

    En el xaml de la mainPage, no enlazas a MiComando, tienes que enlazar a tu propiedad Comando:

    <i:Interaction.Behaviors>
        <PruebaComando_MisBehaviors:BehaviorParaList Command="{Binding Comando}" />
    </i:Interaction.Behaviors>

    Y en tu comando, cuando registrar la dependency property, el tipo de su owner no puede ser Object, debe ser el behavior y el tipo de la propiedad debe ser ICommand que es el valor que te va a llegar:

    private static readonly DependencyProperty CommandProperty
                = DependencyProperty.RegisterAttached("Command",
                                            typeof(ICommand),
                                            typeof(BehaviorParaList), null);

    Con estos cambios, te funcionará perfectamente.

    Un saludo!


    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

    • Marcado como respuesta Santiago Pomar lunes, 18 de junio de 2012 6:55
    lunes, 18 de junio de 2012 5:58
    Moderador
  • Pues sí. Ahora ya funciona. Muchísimas gracias Yeray!!! :-)

    Un saludo y gracias.


    Santiago Pomar


    lunes, 18 de junio de 2012 6:55