修改:经过研究,发现只要在Frame上设置JournalEntry.KeepAlive="True"就可以使用第一种绑定到Source的最简单的办法来实现文中的效果。不用自己管理Page

这几天给给别人做了几个Demo,但觉得每个Demo都做一个工程太麻烦,不好管理,于是决定把每个Demo都各自用Page,然后通过一个列表,可以选择各个页面来查看。就如下图的效果:

当从左边选中一项后,右边的Frame会展示相应的内容。

我采用了一个xml文件来描述相关的信息,示例如下:

<?xml version="1.0" encoding="utf-8" ?>
<Pages>
  <Page Name="Page1" Uri="/FrameContent;Component/Page1.xaml"/>
  <Page Name="Page2" Uri="/FrameContent;Component/Page2.xaml"/>
</Pages>

这是一个非常简单的描述,每个Page项描述这个Page的Name和对应的xaml文件,然后我们可以简单用下面的方式来绑定这些信息来达到目的:

<ListBox x:Name="ListBox1"
          ItemsSource="{Binding Source={StaticResource ListSource}}" 
          DisplayMemberPath="@Name"/>
<!-- 最简单的方式就是用Frame的Source来做绑定,不过这样会导致每次都生成新的实例 -->
<Frame DataContext="{Binding ElementName=ListBox1, Path=SelectedItem}" 
       Source="{Binding XPath=@Uri}"/>

不过,这样有一个小小的问题在于,每次我切换Page的时候,都将重新生成一个Page的实例,以前在Page上做的一些操作会消失。这不是我想要的,我希望有一个类似于PagePool的东西来缓存我这些创建好的页面,这样在切换的时候会减少创建实例的开销,同时可以保证无论怎么切换始终是同一个Page的实例。于是我做了如下的更改:

<ListBox x:Name="ListBox1"
         ItemsSource="{Binding Source={StaticResource ListSource}}" 
         DisplayMemberPath="@Name"/>
<Frame x:Name="PageHost1"
       NavigationUIVisibility="Hidden"
       Content="{Binding ElementName=ListBox1, Path=SelectedItem, Converter={StaticResource Converter}}"/>

我直接把Frame的Content属性绑定到选中的项上,并且用一个Converter来返回Page的实例,在Converter里面,我用一个Dictionary来保存创建过的页面,保证它们只会被创建一次:

public class FrameContentConverter : IValueConverter
    {
        // 使用Page池来减少创建Page的开销
        private Dictionary<string, Page> _pagePool = new Dictionary<string, Page>();

        IValueConverter Members#region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            // 把Frame的Content绑定到ListBox的SelectedItem上,无法对变化做出响应
            XmlElement node = value as XmlElement;
            if (node != null)
            {
                string name = node.Attributes["Name"].Value;
                string uri = node.Attributes["Uri"].Value;

                if (this._pagePool.ContainsKey(name))
                {
                    return this._pagePool[name];
                }
                else
                {
                    Page page = Application.LoadComponent(new Uri(uri, UriKind.Relative)) as Page;
                    this._pagePool.Add(name, page);
                    return page;
                }
            }
            return null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            XmlElement node = value as XmlElement;
            if (node != null)
            {
                string name = node.Attributes["Name"].Value;
                string uri = node.Attributes["Uri"].Value;

                if (this._pagePool.ContainsKey(name))
                {
                    return this._pagePool[name];
                }
                else
                {
                    Page page = Application.LoadComponent(new Uri(uri, UriKind.Relative)) as Page;
                    this._pagePool.Add(name, page);
                    return page;
                }
            }
            return null;
        }

        #endregion
    }

理论上来说,这应该工作良好,然而,实际上却发生一点小小的意外:

Frame展示的内容只跟第一次选中的项有关,其后无论如何切换,Frame的内容均不受影响

难道是Frame的Content属性默认是以OneTime的模式来绑定的?于是我显示地指定Mode=OneWay,结果依然如此。

莫非Frame的Content属性只能指定一次?好吧,既然正着来不行,那我就试试反着的。

索性,我把ListBox的SeletedItem使用OneWayToSource的模式绑定到Frame的Content属性上。当然,这种情况下,FrameContentConverter里面的ConvertBack方法需要实现。

<ListBox x:Name="ListBox2" 
         ItemsSource="{Binding Source={StaticResource ListSource}}"
         DisplayMemberPath="@Name"
         SelectedItem="{Binding ElementName=PageHost2, Path=Content, Converter={StaticResource Converter}, Mode=OneWayToSource}"/>
<Frame x:Name="PageHost2" NavigationUIVisibility="Hidden"/>

采用这种方式后,一切正常了:

这说明,Frame的Content属性不是只能设置一次的,只是在对Frame的Content属性做绑定时,由于某种未知的原因,无法对数据源的变化产生响应,鉴于我目前的系统是Vista SP1,上次的Frame出现了渲染上的问题,这次我也没有找没装SP1的机子做测试,所以我并不能确定这是WPF本身的BUG还是sp1引起的问题,还是我某个地方没有弄好造成的。

做了一个对比的示例,有兴趣的读者可以下载回去看看。http://files.cnblogs.com/RMay/FrameContent.rar

转载于:https://www.cnblogs.com/RMay/archive/2008/07/28/1254383.html

【WPF】对Frame控件的Content属性做绑定时出现的一个小问题相关推荐

  1. WPF对某控件添加右键属性

    代码创建右键属性 ContextMenu cm = new ContextMenu();MenuItem mi = new MenuItem();mi.Header = "打开此文件所有文件 ...

  2. WPF中DataGrid控件

    WPF中DataGrid控件的个别属性使用 //设置不可自动拉伸宽度dataGrid.CanUserResizeColumns = false;//第一列不可见dataGrid.HeadersVisi ...

  3. 如何 修改服务器控件的text,设置TextBox控件的TextMode属性

    我想在程式代碼中將TextBox控件的TextMode属性设置為Password,寫成TextBox1.TextMode=MultiLine和TextBox1.TextMode="Multi ...

  4. C#控件及常用属性整理

    C#控件一览表 前所未有的震撼(太详细了) 1.窗体 1.常用属性 (1)Name属性:用来获取或设置窗体的名称,在应用程序中可通过Name属性来引用窗体. (2) WindowState属性: 用来 ...

  5. 2021-08-11 WPF控件专题 Frame 控件详解

    1.Frame 控件介绍 Frame ContentControl 支持导航,可以将一个页面导航到另一个页面. 可能承载Page页, TabItem ContentControl 直接在内部添加元素, ...

  6. WPF中通过控件Margin属性设置控件位置

    WPF中通过控件Margin属性设置控件位置 一.Margin属性简介 二.Margin在cs文件中定义 三.Margin设置控件位置 四.参考文档 一.Margin属性简介 在使用WPF进行页面设计 ...

  7. MVVMLight 实现指定Frame控件的导航

    MVVMLight 实现指定Frame控件的导航 原文:MVVMLight 实现指定Frame控件的导航 在UWP开发中,利用汉堡菜单实现导航是常见的方法.汉堡菜单导航一般都需要新建一个Frame控件 ...

  8. 潜移默化学会WPF(难点控件treeview)--改造TreeView(CheckBox多选择版本),递归绑定数据...

    目前自己对treeview的感慨很多 今天先讲 面对这种 表结构的数据 的其中一种绑定方法,后面多几列其他属性都没关系,例如多个字段, 1  A  0 2  B  0 3  C  0 4  D  1 ...

  9. WPF Calendar 日历控件 样式自定义

    原文:WPF Calendar 日历控件 样式自定义 粗略的在代码上做了些注释 blend 生成出来的模版 有的时候 会生成 跟 vs ui界面不兼容的代码 会导致可视化设计界面 报错崩溃掉 但是确不 ...

  10. 转 8天入门wpf—— 第六天 细说控件

    WPF中的控件大体上分为四类 内容控件 ContentControl直接从Control类中派生出来,内容控件的最大特征是含有一个Content属性,Content属性的类型是Object,因此内容控 ...

最新文章

  1. oracle 表空间初始分配,在Oracle中创建用户时,若未提及DEFAULT TABLESPACE关键字,则Oracle就将哪个表空间分配给用户作为默认表空间。...
  2. Xamarin Essentials教程使用加速度传感器Accelerometer
  3. sprintboot-learn(一)
  4. 1362. 健康的荷斯坦奶牛【难度: 一般 / 二进制枚举】
  5. 邀您参与 | 阿里巴巴如何扩展 K8s 调度器支持 AI 和大数据任务?
  6. Kittle工具抽取文件出现乱码的情况解决方法
  7. POJ3678-Katu Puzzle【2-SAT】
  8. java property_property在Java中的用法
  9. 面试题 35 : 复杂链表的复制
  10. Chrome development tools学习笔记(3)
  11. 如何掌握mysql的查询语句_如何分析mysql的查询语句
  12. 阿里云云计算 15 在线实验--OSS的使用
  13. UVC系列2-探索Android UVC协议
  14. 硬刚Hive | 4万字基础调优面试小总结
  15. linux 使用icc运行tcl,Tcl在ICC2中的应用:定义一个proc,实现将一个cell直接替换成另一个功能不等价的cell...
  16. R语言潜在变量模型、探索性因子分析EFA、验证性因素分析(CFA)、结构方程建模(SEM)之间的关系、潜在变量模型常用包:ltm包、sem包、OpenMx包、Lavaan包、lsa包、ca包等
  17. 高项考试-信息化知识
  18. 利率浮动值60BP什么意思,利率上浮50bp是什么意思
  19. IIS Express 7.5 directory browsing 启用目录浏览
  20. matlab计算后验概率,基于深度神经网络后验概率算法的口语发音评测方法与流程...

热门文章

  1. Linux系统编程四:串口编程,控制LED和蜂鸣器
  2. 数据挖掘导论学习---1
  3. 在Centos6.8上为安装Django1.11.1升级Python2.6到Python3.5
  4. 【database】oracle触发器基础
  5. 数据驱动编程之表驱动法
  6. puppet中anchor的作用
  7. individual program总结2.0
  8. 软件需求工程与UML建模——第九组第六周工作总结
  9. 路飞学城Python-Day42
  10. python爬虫之路——对斗破苍穹进行关键字提取,制作噪声云图