This commit is contained in:
Beatriz Stollnitz 2019-08-05 20:35:22 -07:00
Родитель f3c58dea69
Коммит 68590ad108
15 изменённых файлов: 552 добавлений и 0 удалений

Двоичные данные
60-SLCollectionViewSource/Images/60SLCollectionViewSource.PNG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 8.2 KiB

Просмотреть файл

@ -0,0 +1,36 @@
# Silverlight's CollectionViewSource
In my <a href="http://www.zagstudio.com/blog/387">last post</a>, I explained the reasoning behind adding CollectionViewSource to WPF. In this post I will talk about CollectionViewSource in Silverlight (introduced in Silverlight 3) and compare it with its WPF counterpart.
If you recall from my last post, CollectionViewSource was added to WPF mainly to permit view-related scenarios to be expressed in XAML (so they could be tooled), and also to aid in remembering the current item of previously displayed collections. The reasons for adding CollectionViewSource to Silverlight were very different. Before the introduction of CollectionViewSource, Silverlight collections were not automatically wrapped by views - in fact the concept of "views" didn't even exist in Silverlight 2. There was no way to sort or filter a collection (other than modifying the collection itself), or to build a master-detail scenario based on currency (although you could create a master-detail scenario based on selection). The introduction of CollectionViewSource enabled all of those scenarios in Silverlight, while improving compatibility with WPF.
Just like in WPF, a class is considered a "view" if it implements ICollectionView. All the views that we're used to interacting with derive from CollectionView, which in turn implements ICollectionView. Silverlight provides implementations only for EnumerableCollectionView and ListCollectionView, which means that it is able to generate views only for collections that implement IEnumerable or IList. These are by far the two most common scenarios. Unlike WPF, Silverlight's CollectionView, EnumerableCollectionView and ListCollectionView classes are all internal.
In addition to these, Silverlight also contains a PagedCollectionView class (this is unique to Silverlight). You can manually wrap your collection with this view to add filtering, sorting, grouping, currency tracking and paging to your collection. <a href="http://timheuer.com/blog/archive/2009/11/04/updated-silverlight-3-datagrid-grouping-data-pagedcollectionview.aspx">Tim Heuer</a> shows an example of its usage. Silverlight's CollectionViewSource, on the other hand, provides the ability to filter, sort, and track currency, but it does not offer the ability to group data.
Unlike WPF, Silverlight only wraps collections with a view when CollectionViewSource is used as an intermediary. If you simply bind an ItemsControl to a collection, no "default view" will be created internally for you. Also, since the ItemCollection class doesn't implement ICollectionView, it's not possible to sort or filter non-data bound items that have been added to an ItemsControl.
Just like in WPF, Silverlight's CollectionViewSource creates a view to wrap a collection when its Source property points to a new collection. In both platforms, it is not necessary to specify "Path=View" when binding to the CollectionViewSource - the binding does that automatically. Here's the syntax you use to bind to a CollectionViewSource:
<UserControl.Resources>
<CollectionViewSource x:Key="cvs" />
</UserControl.Resources>
<ListBox ItemsSource="{Binding Source={StaticResource cvs}}" />
Notice that I didnt have to specify "{Binding Source={StaticResource cvs}, Path=View}" to bind to the view exposed by the CollectionViewSource. Both syntaxes are equivalent, but the second is unnecessary - the binding engine knows to drill into the View property when given a CollectionViewSource.
In WPF, when the CollectionViewSource points to several collections throughout its life, it creates a view for each of them and remembers those views. My last post explains how this feature enables a common scenario that would be a bit of work to implement without CollectionViewSource. I'm very glad to say that this feature has also been implemented in Silverlight, so the selection behavior of my previous post's WPF sample works the same way in Silverlight.
In fact, porting that sample to Silverlight was straightforward. The only difference was that in WPF, Bindings within the resources inherit the Window's DataContext. This enabled me to write the following code/XAML to bind the CollectionViewSource's Source to the Window's DataContext:
this.DataContext = new Mountains();
<CollectionViewSource Source="{Binding}" x:Key="cvs1"/>
This same feature is not present in Silverlight 3. Here's one equivalent way of implementing that behavior in Silverlight:
<local:Mountains x:Key="mountains" />
<CollectionViewSource Source="{Binding Source={StaticResource mountains}}" x:Key="cvs1"/>

Двоичные данные
60-SLCollectionViewSource/SLCollectionViewSource.xap Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SLCollectionViewSource", "SLCollectionViewSource\SLCollectionViewSource.csproj", "{73D84A6F-D1C9-4782-A895-BB5DFC604CC4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{73D84A6F-D1C9-4782-A895-BB5DFC604CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73D84A6F-D1C9-4782-A895-BB5DFC604CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73D84A6F-D1C9-4782-A895-BB5DFC604CC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73D84A6F-D1C9-4782-A895-BB5DFC604CC4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,8 @@
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SLCollectionViewSource.App"
>
<Application.Resources>
</Application.Resources>
</Application>

Просмотреть файл

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SLCollectionViewSource
{
public partial class App : Application
{
public App()
{
this.Startup += this.Application_Startup;
this.Exit += this.Application_Exit;
this.UnhandledException += this.Application_UnhandledException;
InitializeComponent();
}
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
}
private void Application_Exit(object sender, EventArgs e)
{
}
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
// If the app is running outside of the debugger then report the exception using
// the browser's exception mechanism. On IE this will display it a yellow alert
// icon in the status bar and Firefox will display a script error.
if (!System.Diagnostics.Debugger.IsAttached)
{
// NOTE: This will allow the application to continue running after an exception has been thrown
// but not handled.
// For production applications this error handling should be replaced with something that will
// report the error to the website and stop the application.
e.Handled = true;
Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
}
}
private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
{
try
{
string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
}
catch (Exception)
{
}
}
}
}

Просмотреть файл

@ -0,0 +1,118 @@
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
namespace SLCollectionViewSource
{
public class Mountains : ObservableCollection<Mountain>
{
public Mountains()
{
// Whistler
Mountain whistler = new Mountain("Whistler");
Lift bigRedExpress = new Lift("Big Red Express");
bigRedExpress.Runs.Add("Headwall");
bigRedExpress.Runs.Add("Fisheye");
bigRedExpress.Runs.Add("Jimmy's Joker");
Lift garbanzoExpress = new Lift("Garbanzo Express");
garbanzoExpress.Runs.Add("Raven");
Lift orangeChair = new Lift("Orange chair");
orangeChair.Runs.Add("Orange peel");
orangeChair.Runs.Add("Banana peel");
orangeChair.Runs.Add("Upper Dave Murray Downhill");
whistler.Lifts.Add(bigRedExpress);
whistler.Lifts.Add(garbanzoExpress);
whistler.Lifts.Add(orangeChair);
// Stevens Pass
Mountain stevensPass = new Mountain("Stevens Pass");
Lift tyeMill = new Lift("Tye Mill");
tyeMill.Runs.Add("Roller coaster");
tyeMill.Runs.Add("Skid road");
tyeMill.Runs.Add("Crest trail");
Lift jupiterChair = new Lift("Jupiter chair");
jupiterChair.Runs.Add("Corona bowl");
jupiterChair.Runs.Add("Lower gemini");
Lift southernCrossChair = new Lift("Southern cross chair");
southernCrossChair.Runs.Add("Orion");
southernCrossChair.Runs.Add("Aquarius face");
stevensPass.Lifts.Add(tyeMill);
stevensPass.Lifts.Add(jupiterChair);
stevensPass.Lifts.Add(southernCrossChair);
// Crystal Mountain
Mountain crystal = new Mountain("Crystal Mountain");
Lift rainierExpress = new Lift("Rainier Express");
rainierExpress.Runs.Add("Iceberg ridge");
rainierExpress.Runs.Add("Pro course");
rainierExpress.Runs.Add("Lucky shot");
Lift greenValley = new Lift("Green Valley");
greenValley.Runs.Add("Green back");
greenValley.Runs.Add("Northway ridge");
crystal.Lifts.Add(rainierExpress);
crystal.Lifts.Add(greenValley);
this.Add(whistler);
this.Add(stevensPass);
this.Add(crystal);
}
}
public class Mountain
{
private ObservableCollection<Lift> lifts;
public ObservableCollection<Lift> Lifts
{
get { return lifts; }
set { lifts = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public Mountain(string name)
{
this.name = name;
lifts = new ObservableCollection<Lift>();
}
}
public class Lift
{
private ObservableCollection<string> runs;
public ObservableCollection<string> Runs
{
get { return runs; }
set { runs = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public Lift(string name)
{
this.name = name;
runs = new ObservableCollection<string>();
}
}
}

Просмотреть файл

@ -0,0 +1,39 @@
<UserControl x:Class="SLCollectionViewSource.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SLCollectionViewSource"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
<UserControl.Resources>
<Style TargetType="TextBlock" x:Key="TitleStyle">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Margin" Value="0,0,0,5" />
</Style>
<local:Mountains x:Key="mountains" />
<CollectionViewSource Source="{Binding Source={StaticResource mountains}}" x:Key="cvs1"/>
<CollectionViewSource Source="{Binding Source={StaticResource cvs1}, Path=Lifts}" x:Key="cvs2"/>
<CollectionViewSource Source="{Binding Source={StaticResource cvs2}, Path=Runs}" x:Key="cvs3"/>
</UserControl.Resources>
<Grid Margin="30" Width="500" Height="130">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="Mountains" Style="{StaticResource TitleStyle}"/>
<TextBlock Text="Lifts" Style="{StaticResource TitleStyle}" Grid.Column="1"/>
<TextBlock Text="Runs" Style="{StaticResource TitleStyle}" Grid.Column="2"/>
<ListBox ItemsSource="{Binding Source={StaticResource cvs1}}" DisplayMemberPath="Name" Grid.Row="1"/>
<ListBox ItemsSource="{Binding Source={StaticResource cvs2}}" DisplayMemberPath="Name" Grid.Column="1" Grid.Row="1"/>
<ListBox ItemsSource="{Binding Source={StaticResource cvs3}}" Grid.Column="2" Grid.Row="1"/>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SLCollectionViewSource
{
public partial class MainPage : UserControl
{
public MainPage()
{
this.InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Deployment.Parts>
</Deployment.Parts>
</Deployment>

Просмотреть файл

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SLCollectionViewSource")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("SLCollectionViewSource")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8782c55a-ef0e-4342-9edd-c1537ef40225")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,100 @@
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{73D84A6F-D1C9-4782-A895-BB5DFC604CC4}</ProjectGuid>
<ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SLCollectionViewSource</RootNamespace>
<AssemblyName>SLCollectionViewSource</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<SilverlightApplication>true</SilverlightApplication>
<SupportedCultures>
</SupportedCultures>
<XapOutputs>true</XapOutputs>
<GenerateSilverlightManifest>true</GenerateSilverlightManifest>
<XapFilename>SLCollectionViewSource.xap</XapFilename>
<SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
<SilverlightAppEntry>SLCollectionViewSource.App</SilverlightAppEntry>
<TestPageFileName>TestPage.html</TestPageFileName>
<CreateTestPage>true</CreateTestPage>
<ValidateXaml>true</ValidateXaml>
<EnableOutOfBrowser>false</EnableOutOfBrowser>
<OutOfBrowserSettingsFile>Properties\OutOfBrowserSettings.xml</OutOfBrowserSettingsFile>
<UsePlatformExtensions>false</UsePlatformExtensions>
<ThrowErrorsInValidation>true</ThrowErrorsInValidation>
<LinkedServerProject>
</LinkedServerProject>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>Bin\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;SILVERLIGHT</DefineConstants>
<NoStdLib>true</NoStdLib>
<NoConfig>true</NoConfig>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>Bin\Release</OutputPath>
<DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
<NoStdLib>true</NoStdLib>
<NoConfig>true</NoConfig>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Windows" />
<Reference Include="mscorlib" />
<Reference Include="system" />
<Reference Include="System.Core" />
<Reference Include="System.Net" />
<Reference Include="System.Xml" />
<Reference Include="System.Windows.Browser" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="DataSource.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:MarkupCompilePass1</Generator>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:MarkupCompilePass1</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<None Include="Properties\AppManifest.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\v3.0\Microsoft.Silverlight.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
<SilverlightProjectProperties />
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

Просмотреть файл

@ -0,0 +1,28 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}" xmlns="">
<SilverlightProjectProperties>
<StartPageUrl>
</StartPageUrl>
<StartAction>DynamicPage</StartAction>
<AspNetDebugging>True</AspNetDebugging>
<NativeDebugging>False</NativeDebugging>
<SQLDebugging>False</SQLDebugging>
<ExternalProgram>
</ExternalProgram>
<StartExternalURL>
</StartExternalURL>
<StartCmdLineArguments>
</StartCmdLineArguments>
<StartWorkingDirectory>
</StartWorkingDirectory>
<ShowWebRefOnDebugPrompt>True</ShowWebRefOnDebugPrompt>
<OutOfBrowserProjectToDebug>
</OutOfBrowserProjectToDebug>
<ShowRiaSvcsOnDebugPrompt>True</ShowRiaSvcsOnDebugPrompt>
</SilverlightProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

Просмотреть файл

@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<!-- saved from url=(0014)about:internet -->
<head>
<title>SLCollectionViewSource</title>
<style type="text/css">
html, body {
height: 100%;
overflow: auto;
}
body {
padding: 0;
margin: 0;
}
#silverlightControlHost {
height: 100%;
text-align:center;
}
</style>
<script type="text/javascript">
function onSilverlightError(sender, args) {
var appSource = "";
if (sender != null && sender != 0) {
appSource = sender.getHost().Source;
}
var errorType = args.ErrorType;
var iErrorCode = args.ErrorCode;
if (errorType == "ImageError" || errorType == "MediaError") {
return;
}
var errMsg = "Unhandled Error in Silverlight Application " + appSource + "\n" ;
errMsg += "Code: "+ iErrorCode + " \n";
errMsg += "Category: " + errorType + " \n";
errMsg += "Message: " + args.ErrorMessage + " \n";
if (errorType == "ParserError") {
errMsg += "File: " + args.xamlFile + " \n";
errMsg += "Line: " + args.lineNumber + " \n";
errMsg += "Position: " + args.charPosition + " \n";
}
else if (errorType == "RuntimeError") {
if (args.lineNumber != 0) {
errMsg += "Line: " + args.lineNumber + " \n";
errMsg += "Position: " + args.charPosition + " \n";
}
errMsg += "MethodName: " + args.methodName + " \n";
}
throw new Error(errMsg);
}
</script>
</head>
<body>
<form id="form1" runat="server" style="height:100%">
<div id="silverlightControlHost">
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="SLCollectionViewSource.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
</form>
</body>
</html>