Search code examples
c#windows-phone-7windows-phone-8windows-phonelonglistselector

Command of Listbox inside long list selector not firing - Windows phone 8 - MVVM


I am creating custom phone book which reads phone book contacts and displays inside my application. So I am creating a long list selector and a listbox inside it.

My listbox will contain phone contact name and list of phone number with the check box under the particular name. I wrote an event trigger inside my listbox to make track of the checkbox is clicked or not.

PROBLEM : Event is not firing in the view model. I suspect since the listbox is present inside another list(long list selector), event is not firing.

Here is xaml code:

<phone:LongListSelector Grid.Row="3" LayoutMode="List" ItemsSource="{Binding PhoneBookDataSource}" IsGroupingEnabled="True" HideEmptyGroups="True">
        <phone:LongListSelector.ItemTemplate>
            <DataTemplate>
            <StackPanel Orientation="Vertical" >
                    <TextBlock Text="{Binding PhoneContactName}" FontWeight="SemiBold" FontSize="36" Foreground="Green"></TextBlock>
                    <ListBox ItemsSource="{Binding LstPhoneContactNumber,Mode=TwoWay}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
                        <i:Interaction.Triggers>
                                <i:EventTrigger EventName="Tap">
                                    <i:InvokeCommandAction Command="{Binding PhoneNumberCheckedStateChangeCommand}" />
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Grid Width="480">
                                    <TextBlock Text="{Binding PhoneNumberItem}" FontSize="25" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="Gray"></TextBlock>
                                    <CheckBox Foreground="Black" Background="Black" VerticalAlignment="Center" HorizontalAlignment="Right" IsChecked="{Binding IsPhoneNumberItemChecked,Mode=TwoWay}"></CheckBox>
                                </Grid>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
            </StackPanel>
            </DataTemplate>
        </phone:LongListSelector.ItemTemplate>
        <phone:LongListSelector.GroupHeaderTemplate>
            <DataTemplate>
                <Border Background="Transparent" Padding="5">
                    <Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62" 
     Height="62" Margin="0,0,18,0" HorizontalAlignment="Left">
                        <TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" 
        FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    </Border>
                </Border>
            </DataTemplate>
        </phone:LongListSelector.GroupHeaderTemplate>
        <phone:LongListSelector.JumpListStyle>
            <Style TargetType="phone:LongListSelector">
                <Setter Property="GridCellSize"  Value="113,113"/>
                <Setter Property="LayoutMode" Value="Grid" />
                <Setter Property="ItemTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
                                <TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6" 
           Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/>
                            </Border>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </phone:LongListSelector.JumpListStyle>
    </phone:LongListSelector>

Here is my view model:

public DelegateCommand PhoneNumberCheckedStateChangeCommand { get; set; }
    public DelegateCommand SendSMSCommand { get; set; }

public CustomPhoneBookViewModel(INavigationService nav, IDataService data, IAESEnDecrypt encrypt, IGeoLocationService geoLocation, IMessageBus msgBus, ISmartDispatcher smartDispatcher)
        : base(nav, data, encrypt, geoLocation, msgBus, smartDispatcher)
    {
        IsProgressBarBusy = true;
        PhoneContactsList = new ObservableCollection<PhoneBookEntity>();
        PhoneBookDataSource = new ObservableCollection<LLSAlphaKeyGroup<PhoneBookEntity>>();
        InitializeDelegateCommands();
        GetDeviceResolution();
        ReadPhoneBook();
    }

private void OnPhoneNumberItemCheckedStateChangedCommand()
    {
        try
        {
            foreach (var parentItem in PhoneBookDataSource)
            {
                foreach (var childItem in parentItem)
                {
                    foreach (var item in childItem.LstPhoneContactNumber)
                    {
                        if (item.IsPhoneNumberItemChecked)
                            IsSendSMSButtonEnabled = true;
                        return;
                    }
                }
                IsSendSMSButtonEnabled = false;
            }
        }
        catch { }
        finally
        {
            SendSMSCommand.RaiseCanExecuteChanged();
        }
    }

Any suggestions is appreciated!!


Solution

  • The easiest way of making the nested ListBox interaction bind to the global ViewModel (instead of to its own, nested DataContext) is to assign a unique name to the outmost LongListSelector:

    <phone:LongListSelector x:Name="OuterList" Grid.Row="3" LayoutMode="List" ItemsSource="{Binding PhoneBookDataSource}" IsGroupingEnabled="True" HideEmptyGroups="True">
    

    and explicitly bind the Command to this element's DataContext (which is the global ViewModel):

    <i:InvokeCommandAction Command="{Binding ElementName=OuterList, Path=DataContext.PhoneNumberCheckedStateChangeCommand}" />