posts - 13, comments - 67, trackbacks - 0, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

2011年9月28日

WP7迷你框架G.Controls  1.0版本,源码发布。

点击下载

下载本源码的同学支持下。有什么意见的可以提出来,以便我开发下个版本。

目前本版本使用的SDK是7.1的,暂时还没有添加本地数据库的开发框架,不过已经计划在下一个版本发布的时候会一并添加进去,以及一个轻量级的MVVM框架,目标是开发一个轻量但功能强大的WP7开发框架,提高开发效率。

框架的教程在上一篇的博客中已经介绍,不会的请看上一篇博客

有什么问题请随时联系我!

posted @ 2011-09-28 10:09 ghwghw 阅读(1125) 评论(6) 编辑

2011年9月26日

很久没有写博客了,今天我给大家介绍一个我自己写的一个WP7开发框架G.Controls,首先我将罗列下目前WP7开发遇到的问题。

1.页面之间如何传递复杂的对象?

2.从当前页面返回前一页时如何将当前页的某些数据传递给前一页?

3.如何使得ListBox拥有分页功能?如何使得ListBox中数据在墓碑后自动回复到原来的数据?如何使得ListBox在墓碑后恢复到墓碑前滑动到的项?

4.如何截获附加属性的值的变化

5.如何获取某个UIElement所有子孙控件?在ScrollView滚动的时候如何获取屏幕最上边的控件?

以上种种问题在使用了本框架之后将得到很容易的解决,本人在设计的时候尽量的使得用最少的代码就可以实现以上功能,所以只要使用了本框架,那么你只需写很少的代码就能实现以上的功能。极大的提高开发一个复杂的应用程序的效率,我已经使用该框架开发了多个程序,包括一个电子商务的WP7软件,本人目前使用该框架开发的新浪微博客户端也是使用的该框架,单纯在列表的滑动流畅度方面绝对比新浪官方的流畅,欢迎大家试用。由于已经很长时间没有维护了,所以目前该微博程序还是有不少的Bug,还处于半成品状态,如有问题请直接在设置中给我发送邮件,谢谢!

新浪微博下载

 

如果要使用以上的功能,必须确保当前的页面是继承自GBasePage,添加命名空间: xmlns:gNavigate="clr-namespace:G.Navigate;assembly=G.Controls",然后将PhoneApplicationPage节点改成gNavigate:GBasePage。

我将使用新浪微博的数据来演示。

先添加两个类:Message和UserInfo

下面是Message的类

 public class Message 
{
[XmlElement("created_at")]
public string CreatedTime { get; set; }

[XmlElement("id")]
public string Id { get; set; }

[XmlElement("text")]
public string Text { get; set; }

[XmlElement("thumbnail_pic")]
public string Thumbnail_pic { get; set; }

[XmlElement("bmiddle_pic")]
public string Bmiddle_pic { get; set; }

[XmlElement("original_pic")]
public string Original_pic { get; set; }

[XmlElement("user")]
public UserInfo User { get; set; }

[XmlElement("source")]
public Source Source { get; set; }


[XmlElement("retweeted_status")]
public Message Retweeted { get; set; }

private Count count;
public Count Count
{
get
{
return count;
}
set
{
if (count != value)
{
count = value;
}
}
}

}
public class Count
{
[XmlElement("id")]
public string ID { get; set; }

[XmlElement("comments")]
public int Comments { get; set; }

[XmlElement("rt")]
public int Rt { get; set; }
}
public class Source
{
[XmlElement("a")]
public string Name { get; set; }
}

以下是UserInfo的类:

   public class UserInfo
{
[XmlElement("name")]
public string NickName
{
get;
set;
}

[XmlElement("screen_name")]
public string ScreenName
{
get;
set;
}

[XmlElement("id")]
public string Id
{
get;
set;
}

[XmlElement("description")]
public string Description
{
get;
set;
}

[XmlElement("gender")]
public string Gender
{
get;
set;
}

[XmlElement("profile_image_url")]
public string HeadImage
{
get;
set;
}

[XmlElement("province")]
public string Province
{
get;
set;
}

[XmlElement("city")]
public string City
{
get;
set;
}

[XmlElement("location")]
public string Location
{
get;
set;
}
/// <summary>
/// 博客地址
/// </summary>
[XmlElement("url")]
public string Url
{
get;
set;
}

/// <summary>
/// 微博数
/// </summary>
[XmlElement("statuses_count")]
public string StatusesCount
{
get;
set;
}

/// <summary>
/// 关注数
/// </summary>
[XmlElement("friends_count")]
public string FriendsCount
{
get;
set;
}

/// <summary>
/// 粉丝数
/// </summary>
[XmlElement("followers_count")]
public string FollowersCount
{
get;
set;
}

[XmlElement("following")]
public bool Following
{
get;
set;
}


[XmlElement("verified")]
public bool verified
{
get;
set;
}

[XmlElement("status")]
public Message Message
{
get;
set;
}

public string MaxHeadImag
{
get
{
return this.HeadImage.Replace("/50/", "/180/");
}
}
}

这里使用PageListBox来展示数据,添加命名空间:     xmlns:gControls="clr-namespace:G.Controls;assembly=G.Controls"

然后使用PageListBox来展示数据:

<gControls:PageListBox x:Name="listbox"
SelectionChanged
="listbox_SelectionChanged"
BeginLoadData
="listbox_BeginLoadData">
<gControls:PageListBox.ItemTemplate>
<DataTemplate>
<Border toolkit:TiltEffect.IsTiltEnabled="True"
BorderBrush
="{StaticResource PhoneBorderBrush}"
BorderThickness
="0,1,0,1"
Margin
="0,0,0,10"
CornerRadius
="5">
<StackPanel Margin="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<gControls:TextButton Foreground="{StaticResource PhoneAccentBrush}"
Text
="{Binding User.NickName}"
FontSize
="22"
HorizontalAlignment
="Left"
x:Name
="btnNickName" />
<TextBlock Text="{Binding Source.Name}"
Grid.Column
="1"
HorizontalAlignment
="Right"
Foreground
="{StaticResource PhoneAccentBrush}" />
</Grid>

<TextBlock Text="{Binding Text}"
FontSize
="18"
TextWrapping
="Wrap" />

<gControls:ImageButton ImageSource="{Binding Thumbnail_pic}"
Tag
="{Binding Original_pic}"
Click
="ImageButton_Click"
HorizontalAlignment
="Center">
</gControls:ImageButton>
</StackPanel>
</Border>
</DataTemplate>
</gControls:PageListBox.ItemTemplate>
</gControls:PageListBox>

然后在cs代码中插入以下代码:

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
this.listbox.EnableTombstoneListBox<Message>(this);
}

上面这段代码是每当导航到当前页的时候就启用墓碑功能,这样,当墓碑后PageListBox会自动到恢复原来的数据。

        private void listbox_BeginLoadData(object sender, G.Controls.PageEventArgs e)
{
System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
timer.Tick += (a, b) =>
{
XmlAttributes rootAttrs = new XmlAttributes();
rootAttrs.XmlRoot = new XmlRootAttribute("statuses");
XmlAttributeOverrides attrOvrs = new XmlAttributeOverrides();
attrOvrs.Add(typeof(GetMessagesResponse), rootAttrs);
System.Xml.Serialization.XmlSerializer se = new System.Xml.Serialization.XmlSerializer(typeof(GetMessagesResponse), attrOvrs);
GetMessagesResponse response = se.Deserialize(Application.GetResourceStream(new Uri("/PhoneApp2;component/weibo.xml", UriKind.Relative)).Stream) as GetMessagesResponse;
this.listbox.LoadData<Message>(response.Messages);
this.ShowState(string.Format("当前页{0},每页{1}条数据", e.PageNum, e.PageSize));
timer.Stop();
};
timer.Start();
}


以上代码是模拟从服务端获取数据,并且将XML数据转换成相对应的类,使用    this.listbox.LoadData<Message>(response.Messages);添加数据,this.ShowState(string.Format("当前页{0},每页{1}条数据", e.PageNum, e.PageSize));方法将会以一个黄条状的提示信息在屏幕最上那边提示信息。

以上工作以后,PageListBox就已经拥有了分页、墓碑、墓碑后自动滑动到墓碑前项的功能。

以下演示页面间数据的传递功能,就是将一个Message对象传递给下一页。

    private void listbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (listbox.SelectedItem != null)
{
Message message = listbox.SelectedItem as Message;
this.NavigationService.Navigate("/Page1.xaml", message);
this.listbox.SelectedItem = null;
}
}

以上代码的核心是    this.NavigationService.Navigate("/Page1.xaml", message);这个方法将会将message传递给下一页。

在下一页中如何取数据?

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
Message message = this.NavigationContext.Param as Message;
this.ContentPanel.DataContext = message;
}

以上代码的核心就是this.NavigationContext.Param ,Param 就是前一页传递过来的参数,是要该参数能够被序列化,那么就不用担心墓碑后丢失的问题,因为我已经处理过了。

 

下面演示如何将当前页的数据传递给前一页:加入当前页有一个TextBox,当我返回到前一页的时候需要将TextBox的值传递给前一页,

首先在当前页添加TextBox和一个按钮

            <StackPanel Orientation="Horizontal"
Grid.Row
="2">
<TextBox Width="300"
x:Name
="txt" />
<Button Content="返回"
Click
="Button_Click" />
</StackPanel>

然后在当前页的cs后台代码中插入以下代码:

     protected override void OnNavigatingFromBack(NavigateBackFromEventArgs e)
{
base.OnNavigatingFromBack(e);
e.HasHandle = true;
e.Param = txt.Text;
}

注意,必须将HasHandle设置为True,否则返回的时候接收不到数据的!

然后在前一页添加以下代码:

       protected override void OnNavigatingBackFrom(NavigateBackFromEventArgs e)
{
base.OnNavigatingBackFrom(e);
MessageBox.Show(e.Param as string);
}

以上就实现了从当前页返回前一页传递数据的功能。



 现在演示如何截获ScrollView的VerticalOffset属性值的更改:

首先在页面中添加一个ScrollView,然后在后台代码或者直接在XAML插入代码,下面演示使用后台代码的方式实现:

G.PropertyValueChangedNotify.Create("VerticalOffset", scrollView).PropertyValueChanged += new G.PropertyValueChangedHandle(ScrollView_PropertyValueChanged);
 

使用上面的代码注册VerticalOffset属性更改后的事件通知

   void ScrollView_PropertyValueChanged(DependencyObject d, G.PropertyValueChangedEventArgs e)
{
txtScroll.Text = e.NewValue.ToString();
}

以上代码就可以将ScrollView的当前VerticalOffset的属性值截获。

以下演示框架中的一个ChildWindow控件:当我点击微博的某张图片的时候,需要查看大图,这时候就需要使用ChildWindow来实现该功能了。

添加一个XAML文件,代码如下:

<childWindow:ChildWindow x:Class="PhoneApp2.BrowserImageChildWindow"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d
="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc
="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable
="d"
xmlns:childWindow
="clr-namespace:G.Controls;assembly=G.Controls"
FontFamily
="{StaticResource PhoneFontFamilyNormal}"
FontSize
="{StaticResource PhoneFontSizeNormal}"
Foreground
="{StaticResource PhoneForegroundBrush}"
d:DesignHeight
="480"
d:DesignWidth
="480">

<Grid x:Name="LayoutRoot" Background="Black">
<Image Source="{Binding}" />
</Grid>
</childWindow:ChildWindow>

修改后台代码

public BrowserImageChildWindow(string url)
{
InitializeComponent();
this.LayoutRoot.DataContext = url;
}

然后当单击图片的时候浏览大图:

       private void ImageButton_Click(object sender, RoutedEventArgs e)
{
ImageButton btn = sender as ImageButton;
BrowserImageChildWindow windows = new BrowserImageChildWindow(btn.Tag as string);
windows.Show();
}

框架中还有其他很多的功能,如果大家有兴趣的话可以自己研究下该框架。

后面我会写一篇博客专门讨论如何提升WP7程序性能的文章,相信各位都曾被WP7的性能问题困扰吧?

以下贴出Demo源码下载链接:

 点击下载

以上源码只是demo的源码,并未贴出框架的源码。如果需要的可以向我索取源码,如果索要的人多的话我会直接把源码发出来的,嘿嘿!

 

未经本人允许,不得私自使用本框架进行商业行为!

 

posted @ 2011-09-26 17:57 ghwghw 阅读(1999) 评论(18) 编辑

2011年5月29日

1.RichTextBox,这个控件不说大家也知道是干什么的了!当初我做WP7微博客户端的时候因为没有richtextbox控件只能将内容全部放在一个textblock中呈现,现在有了RichTextBox控件我们可以自己格式化文本了。

2.Socket支持。有了socket的支持,那么开发IM应用就变得可能了!

3.Glyphs添加了FontSource属性,那么开发XPS文档阅读器也可以了,大家可以下载我原来在XPS文档阅读器博客中的源码,稍微改动下就可以用了!

4.ViewBox控件,说实话这个控件我在silverlight中也没怎么用,所以这里就不发表意见了。

5.在System.Windows.Media命名控件下加入了对摄像头和麦克的支持。这样开发自己的摄像头应用软件就变得可行了。

6.在Microsoft.Phone.BackgroundAudio命名空间下加入了后台播放音乐的支持。这样我们可以开发自己的音乐播放器了!

7.在Microsoft.Phone.BackgroundTransfer加入了后台文件传输的支持,这个功能还没试用过。

8.在Microsoft.Phone.UserData命名空间下加入了多个跟用户信息相关的API,具体的内容请自行发掘。

9.添加了自定义手机铃声的支持

10.在Microsoft.Phone.Schedule命名空间下添加了对Schedule的支持。

WP7的芒果更新带来了很多的新功能,以上提到的只是所有新功能中的一部分。其他的心功能大家可以自行挖掘。

posted @ 2011-05-29 00:05 ghwghw 阅读(1641) 评论(2) 编辑

2011年3月22日

最近在开发windows phone 7的应用程序,下面我总结下着段时间的使用以及开发体验:

1、WP7的界面做的实在是太棒了,一目了然!很清爽!

2、开发的时候颜色选择是比较头疼的,因为所有的控件都是使用了WP7系统默认的颜色!所以为了能够配合WP7的风格还是尽量采用系统默认的颜色,这样的话,当用户改变系统的主题的时候,你的应用程序的颜色也会跟着相应的改变!还有一个就是WP7墓碑机制,我们在开发WP应用程序的时候为了配合墓碑机制专门写了一个框架,当然框架中也不是只有墓碑机制,还有一个导航框架!

3、手机下面的三个键(返回键、开始键、搜索键)(手机型号为:HTC  HT7),设计的实在是糟糕透了,严重影响使用体验,我经常会不小心按到其中的三个键,如果程序没有启用墓碑机制,那么这种误按将会使你崩溃!如果三个键改成按钮式的那种,而不是触摸式的将会好很多!

4、如果你以前没使用过silverlight,那么你在开发的过程中将会遇到很多性能问题!这种性能问题不是说手机不好,而是你写的代码有问题!最典型的是ListBox的VirtualizingStackPanel,而这个问题在数据量大的情况下将会特别明显!即使你启用了VirtualizingStackPanel,并且将VirtualizationMode设置了Recycling,你也会碰到莫名其妙的问题!

5、WP7现在的第一方或者第三方控件太少了,当然这个问题不是很大,很多控件我们自己都可以开发!

6、最近在做新浪微博WP7客户端,但是WP7缺少类似RichTextBox的控件,也许你会说TextBlock可以格式化文本,但是TextBlock无法添加控件,尤其是可点击的按钮!当然这个问题通过必要的变通手段还是能解决的,但是会很复杂!

7、我得喷下WP7的墓碑机制,太坑爹了!如果你启用了墓碑机制,那么意味着你的程序的复杂度将会成倍的增长,尤其是那种本身比较复杂的程序,那么就等着杯具吧!你可能会为你启用了墓碑机制而后悔!

posted @ 2011-03-22 12:45 ghwghw 阅读(772) 评论(4) 编辑

2010年7月19日

 

XPS是微软的一个文档标准,就像Adobe的PDF,现在网上也有很多的PDF文档在线阅读器,而XPS文档阅读器很少几乎没有。今天我将我制作的这个XPS文档阅读器拿出来跟大家分享,也顺便期望某个高手能解决一些问题,共同进步。本XPS阅读器可以实现的效果如下:可以完美还原原来文档的原貌,添加页面导航功能(类似于Word中标题导航,如果是外部URL的链接那么将打开新页面),添加了翻页动画效果(提供了属性可以自定义翻页动画)。

随着Silverlight4 的发布,Silverlight版的XPS阅读器也变的可行。其实国外牛人早在Silverlight3的时候就发布了XPS阅读器,但却是收费的。最主要的原因是Silverlight4以前的所有版本都不支持为Glyphs设置FontSource属性。这样导致了除非你另写一套类库来模拟Glyphs不然只有购买第三方的类库。可是现在Silverlight支持位Glyphs设置FontSource属性了,所以现在我们可以设计制作一个Silverlight版的XPS阅读器。唯一的遗憾是无法读取直接由打印出来的XPS文档,只能读取由Office转换过来的XPS文档,问题出在当文档时由打印获得的XPS文档的时候,无法获取相关的资源(期望某位高手能解决)。下图是本项目的类文件:

 

 

这里几乎所有的类文件都是按照XPS的文档结构来建立的。我们可以随便拿出一个由office转换来的XPS文档,然后将文件的后缀名改为zip格式,然后解压文件就可以看到整个文档的结构了。所有类中最重要的类有三个:XpsDocument这个类是承载文档的(也就是流Stream),XpsToSilverlightXaml这个类是专门负责将XML转换成Xaml(参考国外的一篇blog,名字忘了),FixedPage这个类是专门用来承载页面的(负责显示页面),其他的类就是为了辅助以及配合文档结构用的。

这里为了区别是否是由Office转换而来的,特意加了一个XpsDocumentType枚举用来表示文档类型。

其他的就不多说了,全都在源码里面。有什么不明白的可以留言给我。

然后下面是XPS控件的用法:

1.  首先在页面中添加控件的引用xmlns:xps="clr-namespace:MyControl.XpsDocument;assembly=MyControl"

2.  然后就是添加控件了

  <ScrollViewer>

        <StackPanel x:Name="LayoutRoot">

            <xps:XpsDocument IsEnableAnima="True"

                             x:Name="xpsDocument"

                             IsEnableNavigate="True">

            </xps:XpsDocument>

            <StackPanel Orientation="Horizontal"

                        HorizontalAlignment="Center">

                <xps:XpsControl x:Name="xpsControl"></xps:XpsControl>

                <Button Content="Load"

                        Click="Button_Click"></Button>

            </StackPanel>

        </StackPanel>

    </ScrollViewer>

其中属性IsEnableAnima表示是否启用翻页动画,如果启用默认的是一个180度旋转动画,也可以通过自定义的方式为Xps控件添加翻页动画。属性IsEnableNavigate表示是否启用页面导航功能。

3.  为button添加事件,用来加载XPS文档:

   private void Button_Click(object sender, RoutedEventArgs e)

        {

            OpenFileDialog opFile = new OpenFileDialog();

            if (opFile.ShowDialog() == true)

            {

                var newStream = new StreamResourceInfo(opFile.File.OpenRead(), null);

                xpsDocument.SetStream(newStream);

                xpsControl.Document = xpsDocument;

            }

        }

至此一个XPS阅读器就完成了。先点击Load按钮加载XPS文档,然后下一页就能显示文档了。如果要添加更多的功能,比如选择文字,放大缩小,那就请各位自行添加了。

         最后,唯一的遗憾是不能加载由打印获取的XPS文档,如果哪位牛人解决了这个问题还请麻烦告诉我下,不胜感激!

 

 

 

 

点击源码下载:

posted @ 2010-07-19 18:04 ghwghw 阅读(4614) 评论(22) 编辑

2010年7月10日

摘要: 刚才看了Artech的也谈事件的文章,文章地址:http://www.cnblogs.com/artech/archive/2010/07/10/1774833.html,他在这篇文章中讲到了MulticastDelegate 类,他说事件本质上是一个MulticastDelegate对象,由此我想到使用MulticastDelegate 类来获取一个事件被注册的次数,下面是我写的一个测试类来测试...阅读全文

posted @ 2010-07-10 16:09 ghwghw 阅读(230) 评论(3) 编辑

2010年4月24日

摘要: 首先在silverlight中式可以捕获摄像头的视频流的,我们可以自己建立一个类,然后继承自VideoSink类,VideoSink类是一个抽象类(位于System.Windows.Media命名空间下s),需要我们实现其中的4个方法 public abstract class VideoSink { public VideoSink(); public CaptureSource Capture...阅读全文

posted @ 2010-04-24 14:11 ghwghw 阅读(1418) 评论(6) 编辑

2010年4月6日

摘要: 关于ado.net entity framework 性能比较网上也有很多,这里我只是初步的介绍下ado.net entity framework使用不同的方法查询数据的不同性能第一部分:重复查询单个实体第一种:Linq To Entitiess代码如下: static void Main(string[] args) { DateTime time1; DateTime time2; time1...阅读全文

posted @ 2010-04-06 15:35 ghwghw 阅读(3570) 评论(5) 编辑

2010年3月25日

摘要: 当我使用vs2010+Silverlight4 想体验下Silverlight的角色管理的功能时,却发生在asp.net 中无法连接数据库的问题,搞了我半天的时间才整明白,现在分享下我的解决方法: 1.首先确保你的机器安装有SQL Server 2005 Express 或者SQL Server 2008 Express,我在第一次安装vs2010的时候SQL Server 2008 Expres...阅读全文

posted @ 2010-03-25 10:06 ghwghw 阅读(1868) 评论(1) 编辑

2010年3月18日

摘要: 这里我来总结一下我在学习过程中体会到的一些需要注意的地方:1.因为 ObjectQuery 实现 IQueryable 和 IEnumerable,因此可以将 ObjectQuery 实现的查询生成器方法与 LINQ 特定的标准查询运算符方法(例如 First 或 Count)结合在一起。与查询生成器方法不同,LINQ 运算符不返回 ObjectQuery2.当创建对象的时候尽量使用对象的静态Cr...阅读全文

posted @ 2010-03-18 11:30 ghwghw 阅读(394) 评论(0) 编辑