|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
来吧!老师们!我代表千千万万的asp.net/C#的初学者在这里呼唤着!成绩形貌
WPF自带的ListView和DataGrid控,都供应了数据分组的撑持,并能够对分组的Header举行自界说。可是,假如想在每一个分组的Header中,显现出天职组的"小计"就不是一件简单的事变了。
假定要用一个ListView用于显现全校先生成就。按班级分组,并在分组头中显现班级均匀分。
最后的效果大抵以下:
.在分组的Header中显现天职组的Aggregation
怎样?有甚么思绪?完成的难点有:
- GroupHeader中的第一例显现为分组的称号。
- GroupHeader中的别的列与数据分歧。
- GroupHeader中各列的宽度与ListView中列对应一直分歧。
- GroupHeader中各列的对齐体例与ListView中各列分歧。
数据
Model层只要一个类,ScoreInfo,代码以下:
publicclassScoreInfo
{
publicScoreInfo(stringstudentNo,stringclassName,intmath,intenglish)
{
StudentNo=studentNo;
ClassName=className;
MathScore=math;
EnglishScore=english;
}
publicstringStudentNo{get;set;}
publicstringClassName{get;set;}
publicintMathScore{get;set;}
publicintEnglishScore{get;set;}
[ReadOnly(true)]
publicintTotalScore
{
get{returnMathScore+EnglishScore;}
}
}
一次测验中,先生的这些数据都不会变。以是不必要完成INotifyPropertyChanged接口。
DAL层间接前往假数据,代码以下:
publicclassSchoolScoreProvider
{
publicList<ScoreInfo>ReadAllScoreInfo()
{
varrandom=newRandom();
return(fromiinEnumerable.Range(0,4)
letclassName=String.Format("({0})班",i+1)
fromsinEnumerable.Range(i*6+1,6)
letmScore=random.Next(101)
leteScore=random.Next(101)
selectnewScoreInfo(s.ToString(),className,mScore,eScore))
.ToList();
}
}
在XAML中声明(实体化)数据源,代码以下:
<!--PrepareDataSource-->
<!--Justfordemo,DONTinitializeyourDataSourcethiswayinrealproject.-->
<ObjectDataProviderx:Key="Data"
ObjectType="{x:Typel:SchoolScoreProvider}"
MethodName="ReadAllScoreInfo"/>
<CollectionViewSourcex:Key="DataView"
Source="{StaticResourceData}">
<!--GroupByClassName-->
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescriptionPropertyName="ClassName"/>
</CollectionViewSource.GroupDescriptions>
<!--SortByTotalScore-->
<CollectionViewSource.SortDescriptions>
<c:SortDescriptionPropertyName="TotalScore"Direction="Descending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
UI层代码
然后是ListView的界说:
<ListViewDataContext="{StaticResourceDataView}"
ItemsSource="{Binding}">
<!--SpecifythecurrentListViewshouldGroupdatasourceitems.-->
<ListView.GroupStyle>
<GroupStyle/>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<!--CellTemplateistheonlyNORMALwaytomakethecolumntextrightalign.-->
<!--ThefollowingcodeshouldworkswiththedefaultListViewItemstyleaboveinResources.
BUTitdoesnt.
<GridViewColumnHeader="学号"Width="75"
DisplayMemberBinding="{BindingStudentNo}"
TextBlock.TextAlignment="Right"/>
Think,ifyouneedtochangetheAlignmentwhilerunning.Theirdifferenceswillbeobvious.
-->
<GridViewColumnHeader="学号"Width="75">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlockText="{BindingStudentNo}"
TextAlignment="Right"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumnHeader="数学成就"Width="75">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlockText="{BindingMathScore}"
TextAlignment="Right"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumnHeader="英语成就"Width="75">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlockText="{BindingEnglishScore}"
TextAlignment="Right"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
为了让Group撑持排列,间接能想到的办法就是在个中安排一个ListViewItem。经由实验这个计划是可行的。必要自界说GroupItem的ControlTemplate。代码以下:
<!--CustomGroupItemtosupportgroupcollaps/expand-->
<StyleTargetType="{x:TypeGroupItem}">
<SetterProperty="Template">
<Setter.Value>
<ControlTemplateTargetType="{x:TypeGroupItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinitionHeight="Auto"/>
<RowDefinitionHeight="*"/>
</Grid.RowDefinitions>
<ListViewItemStyle="{StaticResourceGroupHeaderListViewItemStyle}"
Content="{BindingConverter={StaticResourceGroupDataAggregator}}"/>
<ToggleButtonName="expander"
Style="{StaticResourceToggleExpanderStyle}"/>
<ItemsPresenterGrid.Row="1"
Visibility="{BindingIsChecked,ElementName=expander,Converter={StaticResourceBooleanToVisibilityConverter}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
个中的关头点是,在内里放了一个ListViewItem。这里间接放GridViewRowPresenter也是能够准确显现出数据的,可是因为没有ListViewItem作Host,每列中的笔墨会一直向左对齐。
利用一个Converter,对以后组的数据举行Aggregation,天生一个暗示班级均匀分的ScoreInfo。Convert的代码以下:
publicclassGroupDataAggregator:IValueConverter
{
publicobjectConvert(objectvalue,Typetype,objectarg,CultureInfoculture)
{
vargroupData=valueasCollectionViewGroup;
if(groupData!=null)
{
varscores=groupData.Items.Cast<ScoreInfo>();
varavgMath=(int)scores.Average(x=>x.MathScore);
varavgEng=(int)scores.Average(x=>x.EnglishScore);
returnnewScoreInfo(groupData.Name.ToString(),null,avgMath,avgEng);
}
returnnewInvalidOperationException();
}
publicobjectConvertBack(objectvalue,Typetype,objectarg,CultureInfoculture)
{
thrownewNotImplementedException();
}
}
固然,这个Convert其实不重点。另外一个重点是,要为GroupItem中的ListViewItem写一个特别的Style,不然,甚么工具都看不到。
<!--StyleapplytoallListViewItem,tomakeitscellstretch.-->
<StyleTargetType="{x:TypeListViewItem}">
<SetterProperty="HorizontalContentAlignment"Value="Stretch"/>
</Style>
<!--StyleapplytotheListViewIteminGroupItemheader-->
<Stylex:Key="GroupHeaderListViewItemStyle"
TargetType="{x:TypeListViewItem}"
BasedOn="{StaticResource{x:TypeListViewItem}}">
<SetterProperty="Template">
<Setter.Value>
<ControlTemplateTargetType="{x:TypeListViewItem}">
<!--KEYSTEP:BindingtheColumnstoListViews-->
<GridViewRowPresenterColumns="{BindingView.Columns,RelativeSource={RelativeSourceMode=FindAncestor,AncestorType={x:TypeListView}}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
关头的一步就是给GridViewRowPresenter指定Columns,ListView可不会主动为这个外人设置这个属性的。
再归去讲GroupItem,用于睁开GroupItem的是其Template中的ToggleButton,即图中三角图标。其代码以下:
<!--ThetogglebuttoninGroupItemHeader,usedtoexpand/collapsagroup-->
<Stylex:Key="ToggleExpanderStyle"
TargetType="{x:TypeToggleButton}">
<SetterProperty="Width"Value="16"/>
<SetterProperty="Height"Value="16"/>
<SetterProperty="HorizontalAlignment"Value="Left"/>
<SetterProperty="VerticalAlignment"Value="Center"/>
<SetterProperty="HorizontalContentAlignment"Value="Center"/>
<SetterProperty="VerticalContentAlignment"Value="Center"/>
<SetterProperty="IsChecked"Value="True"/>
<SetterProperty="BorderThickness"Value="1"/>
<SetterProperty="BorderBrush"Value="Black"/>
<SetterProperty="Background"Value="Black"/>
<SetterProperty="Padding"Value="0"/>
<SetterProperty="SnapsToDevicePixels"Value="True"/>
<SetterProperty="FocusVisualStyle"Value="{x:Null}"/>
<SetterProperty="IsTabStop"Value="False"/>
<SetterProperty="Content">
<Setter.Value>
<StreamGeometry>M6,0L6,6L0,6Z</StreamGeometry>
</Setter.Value>
</Setter>
<SetterProperty="Template">
<Setter.Value>
<ControlTemplateTargetType="{x:TypeToggleButton}">
<!--Theborderisusedtomakethecontrolarectanglewhichiseasiertoclick.-->
<BorderBackground="Transparent"
BorderThickness="0">
<PathStretch="None"
Data="{TemplateBindingContent}"
Margin="{TemplateBindingPadding}"
Fill="{TemplateBindingBackground}"
Stroke="{TemplateBindingBorderBrush}"
StrokeThickness="{TemplateBindingBorderThickness}"
VerticalAlignment="{TemplateBindingVerticalContentAlignment}"
HorizontalAlignment="{TemplateBindingHorizontalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<TriggerProperty="IsMouseOver"Value="True">
<SetterProperty="Background"Value="#007ACC"/>
<SetterProperty="BorderBrush"Value="#007ACC"/>
</Trigger>
<TriggerProperty="IsChecked"Value="False">
<SetterProperty="Background"Value="White"/>
<SetterProperty="Content">
<Setter.Value>
<StreamGeometry>M0,0L4,4L0,8Z</StreamGeometry>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
题外话
另给勤劳些、不喜好吃冷饭的同砚几个思索的偏向,用于确认对下面代码的了解水平。
针对下面这个ToggleButton的Style:
- 每一个Setter都有甚么感化?删除每个都有甚么分歧成果?哪些是能够删除的?(用时5分钟)
- 利用TemplateBinding与间接在ControlTemplate中写值有甚么分歧?(30秒)
- 为何把BorderThickness绑定给了Path,而不是Border?(30秒)
- Style中的Trigger可否放在ControlTemplate.Triggers中?为何利用StyleTrigger而不是ControlTemplateTrigger?(5分钟)
- 假如你不会StreamGeometry中的语法,那末实验解读StreamGeometry中的语法(个中Z暗示曲线向原点闭合),并写出一个+-号作风的ToggleButtonStyle。(15分钟)
假如只是要计划。这里是完全的代码。
那做企业软件是不是最好用J2EE? |
|