WP7:ContextMenu使用中碰到的问题

这两天发现项目占用内存过高,突然就象检查一下各个页面的回收是否正常,最后定位到Silverlight Toolkit中的ContextMenu控件使得我的一个页面在离开的时候无法被正常的回收,这里记录一下定位的过程:

首先,重载页面的OnRemovedFromJournal函数,我们知道当以GoBack的方式回退到回退栈中的前一个页面时,这个函数会被首先执行,然后才是OnNavigatedFrom函数。

1 protected override void OnRemovedFromJournal(JournalEntryRemovedEventArgs e)
2 {
3 this.DataContext = null;
4
5 base.OnRemovedFromJournal(e);
6 }

在OnRemovedFromJournal函数中把页面绑定的DataContext置为null,防止和页面绑定的ViewModel导致页面无法回收。

然后,给页面加上析构函数,好让我知道在离开页面时,是否页面是否会被析构。

~MyTestPage()
{
System.Diagnostics.Debug.WriteLine("Finalizing " + this.GetType().FullName);
}

就是在析构函数中加上个输出语句,便于观察。

再然后就是加上断点,调试项目,跳转到MyTestPage,然后按BackKey进行回退,预料之中首先执行OnRemovedFromJournal函数,但是输出控制台并没有输出那句“Finalizing”,显然页面没有被销毁,它被阻碍了。

可以上网或者在MSDN上查,什么样的情况会导致页面无法回收。我了解的三个基本情况是:

  1. 页面的DataContext为置空,也就是说页面和ViewModel还关联着,这会导致页面无法回收。
  2. 页面中的部分控件会导致页面无法回收(原因有很多,后面会提到)。
  3. 页面中注册的一些事件,没有退订也会导致页面无法回收。

估摸着我碰到的情况应该在2.3中产生,我先尝试着能不能把情况3给排除掉。怎么排除呢,我把xaml中和cs中注册的事件在OnNavigatedFrom函数中全部退订一边,然后在调试程序,和上面一样的步骤看能不能在输出控制台中看见那句“Finalizing ”,然后答案是没有看见,很好,情况3就被排除了。

其实我也认为页面中的控件导致页面无法得到回收最为可能,情况3已经排除了,我就开始把xaml文件中的控件一个个的试(注释、调试、查看结果),好在页面的布局不是很复杂啊,最着定位到这样一个DataTemplate:

 1 <coding4fun:Tile Background="{Binding TileBackgroundBrush}" Margin="2,0,0,2" Click="Tile_Click" Loaded="Tile_Loaded">
2 <toolkit:ContextMenuService.ContextMenu>
3 <toolkit:ContextMenu IsZoomEnabled="False" Foreground="{StaticResource S_White}"
4 Background="{StaticResource PhoneAccentBrush}"
5 BorderBrush="{StaticResource PhoneAccentBrush}">
6 <toolkit:MenuItem Visibility="{Binding , Converter={StaticResource}}"
7 Header="{Binding, Source={StaticResource LocalizedStrings}}"
8 Command="{Binding}" Foreground="White" />
9 <toolkit:MenuItem Visibility="{Binding, Converter={StaticResource}}"
10 Header="{Binding, Source={StaticResource LocalizedStrings}}"
11 Command="{Binding}" Foreground="White" />
12 <toolkit:MenuItem Header="{Binding , Source={StaticResource LocalizedStrings}}"
13 Command="{Binding }" Foreground="White" />
14 </toolkit:ContextMenu>
15 </toolkit:ContextMenuService.ContextMenu>
16 </coding4fun:Tile>

再然后我就把这块代码给注释掉:

<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu IsZoomEnabled="False" Foreground="{StaticResource S_White}"
Background="{StaticResource PhoneAccentBrush}"
BorderBrush="{StaticResource PhoneAccentBrush}">
<toolkit:MenuItem Visibility="{Binding , Converter={StaticResource}}"
Header="{Binding, Source={StaticResource LocalizedStrings}}"
Command="{Binding}" Foreground="White" />
<toolkit:MenuItem Visibility="{Binding, Converter={StaticResource}}"
Header="{Binding, Source={StaticResource LocalizedStrings}}"
Command="{Binding}" Foreground="White" />
<toolkit:MenuItem Header="{Binding , Source={StaticResource LocalizedStrings}}"
Command="{Binding }" Foreground="White" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>

断点、调试,~MyTestPage函数执行了,也就是说页面被析构了,不过在这儿就能断定是ContextMenu的原因么?在MenuItem中还绑定了Command,Command对象虽然好用,不过也可能是元凶,先把它给删掉看是不是Command的原因,结果~MyTestPage木有执行,不是Command的原因,不过到这儿突然发现这个担心其实是多余的,我不是在OnRemovedFromJournal函数中把页面的DataContext置为null了么。

那结果就指向了toolkit:ContextMenu ,是它导致我的页面无法被析构和回收,但是我又不能把它删掉,因为他承载了我需要的功能。没办法只能旁敲侧击,抄小道消灭这个问题,我的解决方案是:

<coding4fun:Tile Background="{Binding TileBackgroundBrush}" Margin="2,0,0,2" Click="Tile_Click" Loaded="Tile_Loaded">

在Tile中注册个Tile_Loaded事件,把所有的Tile维护到一个List中,在页面的OnNavigatedFrom函数中这样写一下,就能把Tile中的ContextMenu给消除掉:

foreach (var item in Tiles)//移除所有的MenuItem否则该页面无法回收
{
var menuItem = ContextMenuService.GetContextMenu(item);
ContextMenuService.SetContextMenu(item,null);
}

再次断点、调试,这回~MyTestPage函数执行了,页面被析构了。

 

@me http://weibo.com/tianyutingxy






转载于:https://www.cnblogs.com/tianyutingxy/archive/2011/11/05/2237084.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值