Windows Phone 显示长文本_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > Windows Phone 显示长文本

Windows Phone 显示长文本

 2013/8/22 10:58:06  綄羙↘xingFu℡  博客园  我要评论(0)
  • 摘要:文采不好,将就着看,见谅思路最重要,故本文不提供源码下载由于WindowsPhone在考虑性能的情况下限制每个TextBlock最多显示高度为2000像素的文本,若超过此值,将自动被截断,显示空白。网上有很多此问题的解决方案,如:计算文字像素,向容器添加多个TextBlock。但此方法效率相对较低且可能导致文本分段不正确。据我所知常使用的方案有两种:1.分页,监听ScrollViewer,当滚动到最下方,自动加载新页内容(类似瀑布流)2.使用WebBrowser方案一在纯文本的情况下可使用
  • 标签:Windows

文采不好,将就着看,见谅

思路最重要,故本文不提供源码下载

 

由于Windows Phone在考虑性能的情况下限制每个TextBlock最多显示高度为2000像素的文本,若超过此值,将自动被截断,显示空白。

网上有很多此问题的解决方案,如:计算文字像素,向容器添加多个TextBlock。但此方法效率相对较低且可能导致文本分段不正确。

据我所知常使用的方案有两种:

1.分页,监听ScrollViewer,当滚动到最下方,自动加载新页内容(类似瀑布流)

2.使用WebBrowser

 

方案一在纯文本的情况下可使用(也存在分段不正确的问题)

本文介绍第二种方案,使用WebBrowser

在使用之前需在网络下载以下文件

1.Newtonsoft.Json.WindowsPhone.dll

用于json解析(本示例仅使用了一小部分此程序集的功能,为提高效率和减小XAP文件大小,您可考虑自行编写解析代码)

2.HtmlAgilityPack.dll

用于解析html,修改图片尺寸(为提高效率和减小XAP文件大小,您可自行编写正则表达式,查询img标签并替换相关属性)

3.jquery-1.9.1.js(其它版本也行)

用于脚本编写(本示例并未大量使用脚本,可不使用jquery,自行编写原生js亦可)

 

概述

windows phone自带IE9浏览器,全面支持HTML5

可完美实现图文混排

开发时,可采用两种方案

1.将读取的文章按文件单独存放到独立存储空间,查看时直接读取相应文件即可。

优点:效率高

缺点:不利于更新,如果日后更新文章模板,在不清除原有文件的情况下,曾经保存的文章板式得不到更新

2.建立数据库,将文章内容存放到数据库,查看时动态生成html页

注:使用此方法需考虑文本被截断的问题,Windows phone使用的是SQL CE,没有text类型字段,字符串类型列最大值为4000个字符,如超过将抛出异常

可使用如下方法解决:将获取的文本内容以3000个字符为单位截取(为什么不是4000?考虑到SQL行最大字节为8049),以多条数据的形式保存(此方法并不是最好的,如有更好解决方法请指教)

优点:方便更新,不占用手机内存

缺点:性能较方案一低

 

由于WebBrowser控件默认允许拖动和放大缩小

阻止缩放可在Html的Head中添加:

<meta content="width=device-width,user-scalable=no" name="viewport">

 

阻止拖动,我们可做如下工作,具体可参考:http://www.scottlogic.com/blog/2010/03/04/linq-to-visual-tree.html

或百度搜索:LinqToVisualTree

 

操作思路

1.编写主要逻辑代码

2.相应的资源文件和模板放入项目,将生成操作设置为:Resources

之所以要做这一步,是因为WebBrowser控件读取的是独立存储空间的文件,在控件初始化时,需读取相应文件将其存放到独立存储空间

 

运行时思路

1.将拷贝的资源文件和模板文件转移到独立存储空间

2.获取文章详细内容

3.读取模板文件

4.替换模板内容

5.保存html文件

6.显示html

 

关于图片加载

加载内容,难免会存在图片,图片都存在于网络且尺寸不同,若每次显示都加载网络图片,势必会浪费用户流量,耗费时间

解决尺寸不同:

通过正则表达式或其它手段获取img标签,将宽设置为100%,删除高(自适应)

解决图片路径:

通过正则表达式或其它手段获取img标签,得到图片url,将图片缓存至独立存储空间,下次加载,首先判断独立存储空间是否存在对应文件,如存在则直接加载,若不存在则在加载网络图片的同时将图片缓存至独立存储空间。

 

class="code_img_closed" src="/Upload/Images/2013082210/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('00143993-f4f1-4b99-9820-e8e8a707249f',event)" src="/Upload/Images/2013082210/2B1B950FA3DF188F.gif" alt="" />
/// <summary>
        /// 调整图片
        /// </summary>
        /// <param name="html"></param>
        /// <param name="imageWidth"></param>
        /// <returns></returns>
        private string RevisionImg(string html, int imageWidth)
        {
            HtmlDocument document = new HtmlDocument();
            document.LoadHtml(html);
            if (document == null) { return html; }
            var images = document.DocumentNode.SelectNodes("//img");
            if (images == null || images.Count == 0) { return html; }
            foreach (HtmlNode image in images)
            {
                if (imageWidth != 0)
                {
                    image.Attributes.Remove("width");
                    //image.Attributes.Add("width", string.Format("{0}px", imageWidth));
                    image.Attributes.Add("width", string.Format("{0}%", 100));
                }
                if (image.Attributes["height"] != null)
                {
                    image.Attributes["height"].Remove();
                }
                if (image.Attributes["src"] != null)
                {
                    try
                    {
                        string imageUrl = image.Attributes["src"].Value;
                        //获取图片url,若不存在,则缓存至独立存储空间
                        StorageCachedImage cacheImage = new StorageCachedImage(new Uri(imageUrl, UriKind.Absolute));
                        if (cacheImage.IsSaveLocal)
                        {
                            imageUrl = "/" + cacheImage.ImageUri.Replace("\\", "/").TrimStart('/');
                        }
                        image.Attributes["src"].Value = imageUrl;
                    }
                    catch { }
                }
            }
            return document.DocumentNode.OuterHtml;
        }
代码片段

 

 

关于javascript与C#互操作

设置WebBrowser控件IsScriptEnabled属性为True

注册WebBrowser控件LoadCompleted和ScriptNotify事件

在LoadCompleted事件中可编写调用js初始化方法

在ScriptNotify事件中可监听javascript,脚本中通过window.external.notify触发ScriptNotify事件

public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this._webBrowser = this.GetTemplateChild("WebBrowser") as WebBrowser;
            this._webBrowser.LoadCompleted += _webBrowser_LoadCompleted;
            this._webBrowser.ScriptNotify += _webBrowser_ScriptNotify;

        }

        void _webBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            this._webBrowser.InvokeScript("init");
        }

        void _webBrowser_ScriptNotify(object sender, NotifyEventArgs e)
        {
            string keyValue = e.Value;
            if (string.IsNullOrWhiteSpace(keyValue)) { return; }
            JObject jObject = JObject.Parse(keyValue);
            string key = jObject["key"].Value<string>();
            string value = jObject["value"].Value<string>();
            if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(value)) { return; }

            if (key == "imgClick")
            {

            }
            else if (key == "aClick")
            {
                this.OpenLink(value);
            }
        }
代码片段

 

 

 

源码

新建项目,创建自定义控件WebBrowserArticle

using HtmlAgilityPack;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using ZP.AppLibrary;

namespace ZP.Controls
{
    public class WebBrowserArticle : Control
    {
        private const string _htmlTemplateFilePath = "/html/content_template.html";
        private const string _htmlFilePath = "/html/index.html";

        private WebBrowser _webBrowser;
        public bool ScrollDisabled { get; set; }//是否禁用滚动
        public WebBrowserArticle()
        {
            this.DefaultStyleKey = typeof(WebBrowserArticle);
            this.Loaded += WebBrowserArticle_Loaded;
        }

        #region 属性
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register(
                "Title",
                typeof(string),
                typeof(WebBrowserArticle),
                new PropertyMetadata(null, OnTextPropertyChanged));
        public string Title
        {
            get
            {
                return (string)GetValue(TitleProperty);
            }
            set
            {
                SetValue(TitleProperty, value);
            }
        }


        public static readonly DependencyProperty OtherDataProperty =
            DependencyProperty.Register(
                "OtherData",
                typeof(string),
                typeof(WebBrowserArticle),
                new PropertyMetadata(null, OnTextPropertyChanged));
        /// <summary>
        /// 其它数据(多个用字符“~”分隔)
        /// </summary>
        public string OtherData
        {
            get
            {
                return (string)GetValue(OtherDataProperty);
            }
            set
            {
                SetValue(OtherDataProperty, value);
            }
        }

        public static readonly DependencyProperty BodyProperty =
            DependencyProperty.Register(
                "Body",
                typeof(string),
                typeof(WebBrowserArticle),
                new PropertyMetadata(null, OnTextPropertyChanged));
        public string Body
        {
            get
            {
                return (string)GetValue(BodyProperty);
            }
            set
            {
                SetValue(BodyProperty, value);
            }
        }
        #endregion

        void WebBrowserArticle_Loaded(object sender, RoutedEventArgs e)
        {
            if (this._webBrowser != null)
            {
                this.SaveHtml();

                var border = this._webBrowser.Descendants<Border>().Last() as Border;
                border.ManipulationDelta += Border_ManipulationDelta;
                border.ManipulationCompleted += Border_ManipulationCompleted;
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this._webBrowser = this.GetTemplateChild("WebBrowser") as WebBrowser;
            this._webBrowser.LoadCompleted += _webBrowser_LoadCompleted;
            this._webBrowser.ScriptNotify += _webBrowser_ScriptNotify;

        }

        void _webBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            this._webBrowser.InvokeScript("init");
        }

        void _webBrowser_ScriptNotify(object sender, NotifyEventArgs e)
        {
            string keyValue = e.Value;
            if (string.IsNullOrWhiteSpace(keyValue)) { return; }
            JObject jObject = JObject.Parse(keyValue);
            string key = jObject["key"].Value<string>();
            string value = jObject["value"].Value<string>();
            if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(value)) { return; }

            if (key == "imgClick")
            {

            }
            else if (key == "aClick")
            {
                this.OpenLink(value);
            }
        }

        /// <summary>
        /// 打开链接
        /// </summary>
        /// <param name="url"></param>
        private void OpenLink(string url)
        {
            WebBrowserTask webBrowserTask = new WebBrowserTask();
            webBrowserTask.Uri = new Uri(url, UriKind.Absolute);
            webBrowserTask.Show();
        }

        private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WebBrowserArticle source = (WebBrowserArticle)d;
            //string html = (string)e.NewValue;
            source.SaveHtml();
        }

        private void SaveHtml()
        {
            if (this._webBrowser == null || this.Title == null || this.OtherData == null || this.Body == null) { return; }
            Common.CopyContentToIsolatedStorage("/Controls;component/WebBrowserArticle/html/content_template.html", _htmlTemplateFilePath);
            string template = IsolatedStorageHelper.OpenFile(_htmlTemplateFilePath);
            template = template.Replace("{title}", this.Title);
            template = template.Replace("{body}", this.Body);
            string otherHtml = string.Empty;
            string otherData = this.OtherData;
            if (!string.IsNullOrWhiteSpace(otherData))
            {
                string[] otherDatas = otherData.Split(new string[] { "~" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string item in otherDatas)
                {
                    otherHtml += string.Format("<span class=\"otherData\">{0}</span>", item);
                }
            }
            template = template.Replace("{otherData}", otherHtml);
            template = this.RevisionImg(template, (int)this._webBrowser.ActualWidth);
            IsolatedStorageHelper.SaveFile(_htmlFilePath, template);

            Common.CopyContentToIsolatedStorage("/Controls;component/WebBrowserArticle/html/js/jquery-1.9.1.js", "/html/js/jquery-1.9.1.js");
            Common.CopyContentToIsolatedStorage("/Controls;component/WebBrowserArticle/html/js/content.js", "/html/js/content.js");
            Common.CopyContentToIsolatedStorage("/Controls;component/WebBrowserArticle/html/css/content.css", "/html/css/content.css");
            this._webBrowser.Navigate(new Uri(_htmlFilePath, UriKind.RelativeOrAbsolute));
        }

        /// <summary>
        /// 调整图片
        /// </summary>
        /// <param name="html"></param>
        /// <param name="imageWidth"></param>
        /// <returns></returns>
        private string RevisionImg(string html, int imageWidth)
        {
            HtmlDocument document = new HtmlDocument();
            document.LoadHtml(html);
            if (document == null) { return html; }
            var images = document.DocumentNode.SelectNodes("//img");
            if (images == null || images.Count == 0) { return html; }
            foreach (HtmlNode image in images)
            {
                if (imageWidth != 0)
                {
                    image.Attributes.Remove("width");
                    //image.Attributes.Add("width", string.Format("{0}px", imageWidth));
                    image.Attributes.Add("width", string.Format("{0}%", 100));
                }
                if (image.Attributes["height"] != null)
                {
                    image.Attributes["height"].Remove();
                }
                if (image.Attributes["src"] != null)
                {
                    try
                    {
                        string imageUrl = image.Attributes["src"].Value;
                        //获取图片url,若不存在,则缓存至独立存储空间
                        StorageCachedImage cacheImage = new StorageCachedImage(new Uri(imageUrl, UriKind.Absolute));
                        if (cacheImage.IsSaveLocal)
                        {
                            imageUrl = "/" + cacheImage.ImageUri.Replace("\\", "/").TrimStart('/');
                        }
                        image.Attributes["src"].Value = imageUrl;
                    }
                    catch { }
                }
            }
            return document.DocumentNode.OuterHtml;
        }

        #region 阻止拖动
        private void Border_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            if (e.FinalVelocities.ExpansionVelocity.X != 0.0 ||
                e.FinalVelocities.ExpansionVelocity.Y != 0.0)
            {
                e.Handled = true;
            }
        }

        private void Border_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            if (e.DeltaManipulation.Scale.X != 0.0 ||
                e.DeltaManipulation.Scale.Y != 0.0)
            {
                e.Handled = true;
            }
            if (ScrollDisabled)
            {
                if (e.DeltaManipulation.Translation.X != 0.0 ||
                  e.DeltaManipulation.Translation.Y != 0.0)
                {
                    e.Handled = true;
                }
            }
        }
        #endregion
    }
}
代码片段

 

 

新建目录:themes

在目录themes新建:generic.xaml

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:system="clr-namespace:System;assembly=System"
    xmlns:controls="clr-namespace:当前控件命名空间;assembly=当前控件程序集名称"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:windows="clr-namespace:System.Windows;assembly=System.Windows">
    
    <Style TargetType="controls:WebBrowserArticle">
        <Style.Setters>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <phone:WebBrowser Name="WebBrowser" IsScriptEnabled="True" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style.Setters>
    </Style>
    
</ResourceDictionary>
代码片段

 

将“当前控件命名空间”替换为你所建立自定义控件的命名空间

将“当前空间程序集名称”替换为你所建立自定义控件的程序集名称

如:

 

 

新建html模板,并导入相关文件

 

body {
    margin: 0;
    padding: 0px;
    -ms-text-size-adjust: none;
}

header {
    padding: 0px 0 20px;
}

.title {
    font-size: 25px;
    font-weight: bold;
    line-height: 30px;
    color: #454545;
    margin: 10px 0 20px 0px;
}

.otherInfo {
    font-size: 12px;
    color: #afafaf;
}

.otherData {
    margin: 0px 5px 0 5px;
}

article {
    margin-top: -15px;
    line-height: 25px;
    margin-right: 0px;
    margin-bottom:50px;
    font-size: 14px;
    color: #7c7c7c;
}

    article div {
        clear: both;
        float: right;
        margin: 10px 2px 5px 5px;
        overflow: hidden;
        height: 125px;
        width: 125px;
    }

        article div img {
            border: 0;
        }

    article p {
        margin: 0;
    }
content.css

 

 

var xapKEY = {
    imgClick: "imgClick",
    aClick: "aClick"
};

function callXAP(key, value) {
    var jsonData = "{key:\"" + key + "\",value:\"" + value + "\"}";
    window.external.notify(jsonData);
}

function init() {
    //$("img").click(function () {
    //    var currObj = $(this);
    //    var imageUrl = currObj.attr("src").toLowerCase();
    //    if (imageUrl.indexOf('.gif') > 0) {
    //        currObj.remove();
    //    } else {
    //        currObj.mousedown(function () {
    //            callXAP(xapKEY.imgClick, imageUrl);
    //        });
    //    }
    //});
    //$("a img").unbind("click");
    $("a").click(function () {
        var currObj = $(this);
        var link = currObj.attr("href");
        if (link && link.indexOf("javascript:") == -1) {
            callXAP(xapKEY.aClick, link);
        }
        return false;
    });
    $("embed,object").remove();
}
content.js

 

 

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="UTF-8">
    <meta content="width=device-width,user-scalable=no" name="viewport">
    <link href="css/content.css" rel="stylesheet" />
    <script type="text/javascript" src="js/jquery-1.9.1.js"></script>
</head>
<body>
    <header>
        <div class="title">{title}</div>
        <div class="otherInfo">{otherData}</div>
    </header>
    <article>
        {body}
    </article>
    <script type="text/javascript" src="js/content.js"></script>
</body>
</html>
content_template.html

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;

namespace ZP.AppLibrary
{
    /// <summary>
    /// Adapts a DependencyObject to provide methods required for generate
    /// a Linq To Tree API
    /// </summary>
    public class VisualTreeAdapter : ILinqTree<DependencyObject>
    {
        private DependencyObject _item;

        public VisualTreeAdapter(DependencyObject item)
        {
            _item = item;
        }

        public IEnumerable<DependencyObject> Children()
        {
            int childrenCount = VisualTreeHelper.GetChildrenCount(_item);
            for (int i = 0; i < childrenCount; i++)
            {
                yield return VisualTreeHelper.GetChild(_item, i);
            }
        }

        public DependencyObject Parent
        {
            get
            {
                return VisualTreeHelper.GetParent(_item);
            }
        }
    }
    /// <summary>
    /// Defines an interface that must be implemented to generate the LinqToTree methods
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ILinqTree<T>
    {
        IEnumerable<T> Children();

        T Parent { get; }
    }

    public static class TreeExtensions
    {
        /// <summary>
        /// Returns a collection of descendant elements.
        /// </summary>
        public static IEnumerable<DependencyObject> Descendants(this DependencyObject item)
        {
            ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item);
            foreach (var child in adapter.Children())
            {
                yield return child;

                foreach (var grandChild in child.Descendants())
                {
                    yield return grandChild;
                }
            }
        }

        /// <summary>
        /// Returns a collection containing this element and all descendant elements.
        /// </summary>
        public static IEnumerable<DependencyObject> DescendantsAndSelf(this DependencyObject item)
        {
            yield return item;

            foreach (var child in item.Descendants())
            {
                yield return child;
            }
        }

        /// <summary>
        /// Returns a collection of ancestor elements.
        /// </summary>
        public static IEnumerable<DependencyObject> Ancestors(this DependencyObject item)
        {
            ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item);

            var parent = adapter.Parent;
            while (parent != null)
            {
                yield return parent;
                adapter = new VisualTreeAdapter(parent);
                parent = adapter.Parent;
            }
        }

        /// <summary>
        /// Returns a collection containing this element and all ancestor elements.
        /// </summary>
        public static IEnumerable<DependencyObject> AncestorsAndSelf(this DependencyObject item)
        {
            yield return item;

            foreach (var ancestor in item.Ancestors())
            {
                yield return ancestor;
            }
        }

        /// <summary>
        /// Returns a collection of child elements.
        /// </summary>
        public static IEnumerable<DependencyObject> Elements(this DependencyObject item)
        {
            ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item);
            foreach (var child in adapter.Children())
            {
                yield return child;
            }
        }

        /// <summary>
        /// Returns a collection of the sibling elements before this node, in document order.
        /// </summary>
        public static IEnumerable<DependencyObject> ElementsBeforeSelf(this DependencyObject item)
        {
            if (item.Ancestors().FirstOrDefault() == null)
                yield break;
            foreach (var child in item.Ancestors().First().Elements())
            {
                if (child.Equals(item))
                    break;
                yield return child;
            }
        }

        /// <summary>
        /// Returns a collection of the after elements after this node, in document order.
        /// </summary>
        public static IEnumerable<DependencyObject> ElementsAfterSelf(this DependencyObject item)
        {
            if (item.Ancestors().FirstOrDefault() == null)
                yield break;
            bool afterSelf = false;
            foreach (var child in item.Ancestors().First().Elements())
            {
                if (afterSelf)
                    yield return child;

                if (child.Equals(item))
                    afterSelf = true;
            }
        }

        /// <summary>
        /// Returns a collection containing this element and all child elements.
        /// </summary>
        public static IEnumerable<DependencyObject> ElementsAndSelf(this DependencyObject item)
        {
            yield return item;

            foreach (var child in item.Elements())
            {
                yield return child;
            }
        }

        /// <summary>
        /// Returns a collection of descendant elements which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> Descendants<T>(this DependencyObject item)
        {
            return item.Descendants().Where(i => i is T).Cast<DependencyObject>();
        }



        /// <summary>
        /// Returns a collection of the sibling elements before this node, in document order
        /// which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> ElementsBeforeSelf<T>(this DependencyObject item)
        {
            return item.ElementsBeforeSelf().Where(i => i is T).Cast<DependencyObject>();
        }

        /// <summary>
        /// Returns a collection of the after elements after this node, in document order
        /// which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> ElementsAfterSelf<T>(this DependencyObject item)
        {
            return item.ElementsAfterSelf().Where(i => i is T).Cast<DependencyObject>();
        }

        /// <summary>
        /// Returns a collection containing this element and all descendant elements
        /// which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> DescendantsAndSelf<T>(this DependencyObject item)
        {
            return item.DescendantsAndSelf().Where(i => i is T).Cast<DependencyObject>();
        }

        /// <summary>
        /// Returns a collection of ancestor elements which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> Ancestors<T>(this DependencyObject item)
        {
            return item.Ancestors().Where(i => i is T).Cast<DependencyObject>();
        }

        /// <summary>
        /// Returns a collection containing this element and all ancestor elements
        /// which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> AncestorsAndSelf<T>(this DependencyObject item)
        {
            return item.AncestorsAndSelf().Where(i => i is T).Cast<DependencyObject>();
        }

        /// <summary>
        /// Returns a collection of child elements which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> Elements<T>(this DependencyObject item)
        {
            return item.Elements().Where(i => i is T).Cast<DependencyObject>();
        }

        /// <summary>
        /// Returns a collection containing this element and all child elements.
        /// which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> ElementsAndSelf<T>(this DependencyObject item)
        {
            return item.ElementsAndSelf().Where(i => i is T).Cast<DependencyObject>();
        }

    }

    public static class EnumerableTreeExtensions
    {
        /// <summary>
        /// Applies the given function to each of the items in the supplied
        /// IEnumerable.
        /// </summary>
        private static IEnumerable<DependencyObject> DrillDown(this IEnumerable<DependencyObject> items,
            Func<DependencyObject, IEnumerable<DependencyObject>> function)
        {
            foreach (var item in items)
            {
                foreach (var itemChild in function(item))
                {
                    yield return itemChild;
                }
            }
        }


        /// <summary>
        /// Applies the given function to each of the items in the supplied
        /// IEnumerable, which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> DrillDown<T>(this IEnumerable<DependencyObject> items,
            Func<DependencyObject, IEnumerable<DependencyObject>> function)
            where T : DependencyObject
        {
            foreach (var item in items)
            {
                foreach (var itemChild in function(item))
                {
                    if (itemChild is T)
                    {
                        yield return (T)itemChild;
                    }
                }
            }
        }


        /// <summary>
        /// Returns a collection of descendant elements.
        /// </summary>
        public static IEnumerable<DependencyObject> Descendants(this IEnumerable<DependencyObject> items)
        {
            return items.DrillDown(i => i.Descendants());
        }

        /// <summary>
        /// Returns a collection containing this element and all descendant elements.
        /// </summary>
        public static IEnumerable<DependencyObject> DescendantsAndSelf(this IEnumerable<DependencyObject> items)
        {
            return items.DrillDown(i => i.DescendantsAndSelf());
        }

        /// <summary>
        /// Returns a collection of ancestor elements.
        /// </summary>
        public static IEnumerable<DependencyObject> Ancestors(this IEnumerable<DependencyObject> items)
        {
            return items.DrillDown(i => i.Ancestors());
        }

        /// <summary>
        /// Returns a collection containing this element and all ancestor elements.
        /// </summary>
        public static IEnumerable<DependencyObject> AncestorsAndSelf(this IEnumerable<DependencyObject> items)
        {
            return items.DrillDown(i => i.AncestorsAndSelf());
        }

        /// <summary>
        /// Returns a collection of child elements.
        /// </summary>
        public static IEnumerable<DependencyObject> Elements(this IEnumerable<DependencyObject> items)
        {
            return items.DrillDown(i => i.Elements());
        }

        /// <summary>
        /// Returns a collection containing this element and all child elements.
        /// </summary>
        public static IEnumerable<DependencyObject> ElementsAndSelf(this IEnumerable<DependencyObject> items)
        {
            return items.DrillDown(i => i.ElementsAndSelf());
        }


        /// <summary>
        /// Returns a collection of descendant elements which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> Descendants<T>(this IEnumerable<DependencyObject> items)
            where T : DependencyObject
        {
            return items.DrillDown<T>(i => i.Descendants());
        }

        /// <summary>
        /// Returns a collection containing this element and all descendant elements.
        /// which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> DescendantsAndSelf<T>(this IEnumerable<DependencyObject> items)
            where T : DependencyObject
        {
            return items.DrillDown<T>(i => i.DescendantsAndSelf());
        }

        /// <summary>
        /// Returns a collection of ancestor elements which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> Ancestors<T>(this IEnumerable<DependencyObject> items)
            where T : DependencyObject
        {
            return items.DrillDown<T>(i => i.Ancestors());
        }

        /// <summary>
        /// Returns a collection containing this element and all ancestor elements.
        /// which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> AncestorsAndSelf<T>(this IEnumerable<DependencyObject> items)
            where T : DependencyObject
        {
            return items.DrillDown<T>(i => i.AncestorsAndSelf());
        }

        /// <summary>
        /// Returns a collection of child elements which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> Elements<T>(this IEnumerable<DependencyObject> items)
            where T : DependencyObject
        {
            return items.DrillDown<T>(i => i.Elements());
        }

        /// <summary>
        /// Returns a collection containing this element and all child elements.
        /// which match the given type.
        /// </summary>
        public static IEnumerable<DependencyObject> ElementsAndSelf<T>(this IEnumerable<DependencyObject> items)
            where T : DependencyObject
        {
            return items.DrillDown<T>(i => i.ElementsAndSelf());
        }
    }
}
LinqToVisualTree.cs

 

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Media.Imaging;

namespace ZP.AppLibrary
{
    /// <summary>
    /// 独立存储缓存图片
    /// </summary>
    public sealed class StorageCachedImage : BitmapSource
    {
        private readonly Uri uriSource;
        private readonly string filePath;
        private const string CacheDirectory = "Shared/ShellContent/CachedImages";
        /// <summary>
        /// 是否保存在本地
        /// </summary>
        public bool IsSaveLocal { get; set; }
        static StorageCachedImage()
        {
            //创建缓存目录
            using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!isolatedStorageFile.DirectoryExists(CacheDirectory))
                {
                    isolatedStorageFile.CreateDirectory(CacheDirectory);
                }
            }
        }

        /// <summary>
        /// 创建一个独立存储缓存的图片源
        /// </summary>
        /// <param name="uriSource"></param>
        public StorageCachedImage(Uri uriSource)
        {
            this.uriSource = uriSource;
            string imageAbsolutePath = uriSource.AbsolutePath.ToLower();
            string extension = Path.GetExtension(imageAbsolutePath).ToLower();
            imageAbsolutePath = imageAbsolutePath.Replace(extension, "");

            //去除扩展名其它字符如:*****.jpg!80、*****.jpg#80
            if (extension.IndexOf(".jpeg") != -1) { extension = ".jpeg"; }
            else if (extension.IndexOf(".jpg") != -1) { extension = ".jpg"; }
            else if (extension.IndexOf(".png") != -1) { extension = ".png"; }
            else if (extension.IndexOf(".bmp") != -1) { extension = ".bmp"; }
            else if (extension.IndexOf(".gif") != -1) { extension = ".gif"; }

            imageAbsolutePath += extension;
            imageAbsolutePath = imageAbsolutePath.TrimStart('/').Replace('/', '_').Replace(':', '_');
            //文件路径
            filePath = Path.Combine(CacheDirectory, imageAbsolutePath);
            OpenCatchSource();
        }

        /// <summary>
        /// 打开缓存源
        /// </summary>
        private void OpenCatchSource()
        {
            bool exist;
            using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                exist = isolatedStorageFile.FileExists(filePath);
            }
            this.IsSaveLocal = exist;
            if (exist)
            {
                SetCacheStreamSource();
            }
            else
            {
                SetWebStreamSource();
            }
        }

        /// <summary>
        /// 设置缓存流到图片
        /// </summary>
        private void SetCacheStreamSource()
        {
            using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var stream = isolatedStorageFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
                {
                    SetSource(stream);
                }
            }
        }

        /// <summary>
        /// 下载Uri中的图片
        /// </summary>
        private void SetWebStreamSource()
        {
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(uriSource);
            httpWebRequest.AllowReadStreamBuffering = true;
            httpWebRequest.BeginGetResponse(ResponseCallBack, httpWebRequest);
        }

        /// <summary>
        /// 下载回调
        /// </summary>
        /// <param name="asyncResult"></param>
        private void ResponseCallBack(IAsyncResult asyncResult)
        {
            var httpWebRequest = asyncResult.AsyncState as HttpWebRequest;
            if (httpWebRequest == null) return;
            try
            {
                var response = httpWebRequest.EndGetResponse(asyncResult);
                using (var stream = response.GetResponseStream())
                {
                    using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        using (var fileStream = isolatedStorageFile.OpenFile
                            (filePath, FileMode.OpenOrCreate, FileAccess.Write))
                        {
                            stream.CopyTo(fileStream);
                        }
                    }
                    Dispatcher.BeginInvoke(SetCacheStreamSource);
                }
            }
            catch (Exception err)
            {
                Debug.WriteLine(err.Message);
            }
        }

        /// <summary>
        /// 当前图片Uri
        /// </summary>
        public string ImageUri
        {
            get
            {
                bool exist;
                using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    exist = isolatedStorageFile.FileExists(this.filePath);
                }
                if (exist)
                {
                    return this.filePath;
                }
                else
                {
                    return uriSource.ToString();
                }
            }
        }
    }
}
StorageCachedImage.cs

 

 

/// <summary>
        /// 复制文件到独立存储空间
        /// </summary>
        /// <param name="sourceFileUrl">源文件</param>
        /// <param name="saveFileUrl">保存文件</param>
        public static void CopyContentToIsolatedStorage(string sourceFileUrl, string saveFileUrl = null)
        {
            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
            {
                saveFileUrl = string.IsNullOrWhiteSpace(saveFileUrl) ? sourceFileUrl : saveFileUrl;
                //if (iso.FileExists(saveFileUrl)) { iso.DeleteFile(saveFileUrl); }
                if (!iso.FileExists(saveFileUrl))
                {
                    var fullDirectory = System.IO.Path.GetDirectoryName(saveFileUrl);
                    if (!iso.DirectoryExists(fullDirectory))
                    {
                        iso.CreateDirectory(fullDirectory);
                    }

                    using (Stream input = Application.GetResourceStream(new Uri(sourceFileUrl, UriKind.Relative)).Stream)
                    {
                        using (IsolatedStorageFileStream output = iso.CreateFile(saveFileUrl))
                        {
                            byte[] readBuffer = new byte[4096];
                            int bytesRead = -1;
                            while ((bytesRead = input.Read(readBuffer, 0, readBuffer.Length)) > 0)
                            {
                                output.Write(readBuffer, 0, bytesRead);
                            }
                        }
                    }
                }
            }
        }



/// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="content"></param>
        public static void SaveFile(string fileName, string content)
        {
            using (var store = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (store.FileExists(fileName)) { store.DeleteFile(fileName); }
                using (var stream = store.CreateFile(fileName))
                {
                    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(content);
                    stream.Write(buffer, 0, buffer.Length);
                }
            }
        }

        /// <summary>
        /// 打开文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string OpenFile(string fileName)
        {
            string data = string.Empty;
            using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (myIsolatedStorage.FileExists(fileName))
                {
                    using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(fileName, FileMode.Open, FileAccess.ReadWrite))
                    {
                        StreamReader sr = new StreamReader(fileStream, System.Text.Encoding.UTF8);
                        data = sr.ReadToEnd();
                        sr.Close();
                    }
                }
            }
            return data;
        }
其它相关方法

 

发表评论
用户名: 匿名