在《在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。