一、说明
本文代码来源:
《windows phone 7 程序设计》 Charles Petzold
控件效果:
二、要点:
1.ItemControl、子项容器模板(ItemsControl.ItemsPanel)和子项模板(ItemsControl.ItemTemplate)
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Students}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:StudentCard />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<petzold:OverlapPanel Orientation="Vertical"
MinimumOverlap="24" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
2.UseControl、VisualStateManager
1).VisualStateManager必须紧跟在于UseControl顶级控件:
<UserControl.RenderTransform>
<TranslateTransform x:Name="translate" />
</UserControl.RenderTransform>
<!-- Border是StudentCard控件的顶级控件-->
<Border.....>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Open">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="translate"
Storyboard.TargetProperty="X"
To="220" Duration="0:0:1" />
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="translate"
Storyboard.TargetProperty="X"
Duration="0:0:1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
...
</Border>
2).当依赖属性
public static readonly DependencyProperty IsOpenProperty =
DependencyProperty.Register("IsOpen",
typeof(bool),
typeof(StudentCard),
new PropertyMetadata(false, OnIsOpenChanged));
改变时就改变控件的视觉状态:
static void OnIsOpenChanged(DependencyObject obj,
DependencyPropertyChangedEventArgs args)
{
(obj as StudentCard).OnIsOpenChanged(args);
}
void OnIsOpenChanged(DependencyPropertyChangedEventArgs args)
{
VisualStateManager.GoToState(this, IsOpen ? "Open" : "Normal", false);
}
3.重写布局控件Panel中的方法:
1). protected override Size MeasureOverride(Size availableSize);
MeasureOverride方法为该布局控件确定每个子元素的大小。
MeasureOverride调用其所有子元素的Measure方法(UIElement中定义的,密封的Sealed方法)。
各个子元素的Measure方法又调用自己的MeasureOverride,这样一直持续遍历完整棵树。
2).protected override Size ArrangeOverride(Size finalSize);
ArrangeOverride方法为该布局控件把子元素排列到相对于自身的位置。
ArrangeOverride调用其所有子元素的Arrange方法(UIElement中定义的,密封的Sealed方法)。
各个子元素的Arrange方法又调用自己的ArrangeOverride,这样一直持续遍历完整棵树。
三、源码
Mainpage.xmal:
<phone:PhoneApplicationPage x:Class="StudentCardFile.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:elpaso="clr-namespace:ElPasoHighSchool;assembly=ElPasoHighSchool" xmlns:petzold="clr-namespace:Petzold.Phone.Silverlight;assembly=Petzold.Phone.Silverlight" xmlns:local="clr-namespace:StudentCardFile" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <phone:PhoneApplicationPage.Resources> <elpaso:StudentBodyPresenter x:Key="studentBodyPresenter" /> </phone:PhoneApplicationPage.Resources> <!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="STUDENT CARD FILE" Style="{StaticResource PhoneTextNormalStyle}"/> </StackPanel> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" DataContext="{Binding Source={StaticResource studentBodyPresenter}, Path=StudentBody}"> <ScrollViewer> <ItemsControl ItemsSource="{Binding Students}"> <ItemsControl.ItemTemplate> <DataTemplate> <local:StudentCard /> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <petzold:OverlapPanel Orientation="Vertical" MinimumOverlap="24" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> </ScrollViewer> </Grid> </Grid> <!--Sample code showing usage of ApplicationBar--> <!--<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="MenuItem 1"/> <shell:ApplicationBarMenuItem Text="MenuItem 2"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>--> </phone:PhoneApplicationPage>