在WindowsPhone8中生成基于MVVM Light的LongListSelector导航事件bug修改

在《在WindowsPhone8中生成基于MVVM Light的LongListSelector导航事件》一文中,我们对LongListSelector绑定了相应命令、消息和数据,在运行程序时,发现一个问题:

我们的命令绑定在了LongListSelector中,用来处理导航事件,这在一般情况下,即绑定的控件不为LongListSelector时,是非常完美的。但是对于LongListSelector,它还存在一个GroupHeader,即A\B\C\D.....这个标题,好,根据上个APP点击这些标题,杯具,bug:

1.如果进入APP直接点击LongListSelector的GroupHeader,那么直接报空引用异常,因为它并不包含一个实例.Name的属性,无法传参、导航。

2.如果进入APP点击LongListSelector的某一项,再点击GroupHeader,好吧..会发生蛋疼的效果,GroupHeader会闪现一下选择拼音的页面,然后直接执行页面导航,导航的页面为我们上一次进入的某项的页。

如何解决呢?折腾了半天,想到了一个方法:把EventToCommand写到TextBlock中而不是LongListSelector中:

<phone:LongListSelector
                   x:Name="MountainIndexLLS"
                   JumpListStyle="{StaticResource AddrBookJumpListStyle}"
                   Background="Transparent"
                   GroupHeaderTemplate="{StaticResource AddrBookGroupHeaderTemplate}"        
                   LayoutMode="List"
                   IsGroupingEnabled="true"
                   HideEmptyGroups ="true" ItemsSource="{Binding DataSource}">
                    <phone:LongListSelector.ItemTemplate>
                        <DataTemplate>
                            <StackPanel VerticalAlignment="Top">
                                <TextBlock FontWeight="Bold"  Text="{Binding Name}" Style="{StaticResource PhoneTextLargeStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" Foreground="White" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="Tap">
                                            <cmd:EventToCommand Command="{Binding TapCommand}" CommandParameter="{Binding SelectedItem,ElementName=MountainIndexLLS}"/>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBlock>
                                <TextBlock Text="{Binding Region}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap" FontFamily="{StaticResource PhoneFontFamilySemiBold}" Foreground="Gray"/>
                            </StackPanel>
                        </DataTemplate>  
                    </phone:LongListSelector.ItemTemplate>
                </phone:LongListSelector>

 恭喜,如果完全复制这段代码,再一次陷入无解状态,命令无法执行,百度一下:DataTemplate Command,就知道有多少人碰到这个问题:DataTemplate中无法访问到DataContext,因此绑定不会出现任何效果。怎么解决呢?

我们需要精确这个绑定的位置,修改〈cmd:...>这段代码如下:

<i:EventTrigger EventName="Tap">
                                            <cmd:EventToCommand Command="{Binding Source={StaticResource Locator},Path=Main.TapCommand}" CommandParameter="{Binding}"/>
                                        </i:EventTrigger>

 OK,可以成功绑定,只不过我们现在处理导航的事件放在了TextBlock中(下图中的山峰名),而不是LongListSelector中,这样,LLS得GroupHeader就不会受到TapCommand的影响了。效果如下:

(上图中,点击LLS的GroupHeader,便不会执行导航命令,因为我们把TapCommand单独绑定在了TextBlock上)

导航成功,第二款APP的框架终于完成,MVVM改造的好辛苦...

对于MVVM,查了很多资料。有一位同学的疑问也是我的疑问:

http://www.cnblogs.com/icuit/archive/2012/05/11/2495396.html

他这样说:我的疑问在此,原来的思路是将NavigationContext获取到的信息绑定到B页面的某个控件中,并通过B页面的某个带参数的command事件将获取到的信息传递给到B页面的viewModel中并绑定B页面的某个方法中更新B页面的UI。 后来朋友告诉我直接用红色的语句实现,我总觉得这样看起来有点怪怪的,这样有破坏mvvm的原则么? 忘了在哪里看过有文章说尽量不在code-behind中写逻辑?可我觉得有时候不用code-behind会太憋屈。 请大家一起讨论一下关于mvvm中的消息模式应该如何考虑。

第二个页面的Code-Behind里放更新UI的代码,这到底是否符合MVVM-Light的本质,我也不是很清晰,希望在以后的学习工作中能更透彻的认识MVVM。

原文地址:https://www.cnblogs.com/valentineisme/p/3089722.html