博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

WP7开发迷你框架G.Controls 介绍

Posted on 2011-09-26 17:57  ghwghw  阅读(2815)  评论(19编辑  收藏  举报

很久没有写博客了,今天我给大家介绍一个我自己写的一个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的源码,并未贴出框架的源码。如果需要的可以向我索取源码,如果索要的人多的话我会直接把源码发出来的,嘿嘿!

 

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