Windows 10 RTM Release - October 2015 Update 4

This commit is contained in:
Raymond Chen 2015-10-28 17:52:37 -07:00
Родитель 22bbec2c41
Коммит 2b585583c3
42 изменённых файлов: 3199 добавлений и 64 удалений

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

@ -146,46 +146,49 @@ For additional Windows samples, see [Windows on GitHub](http://microsoft.github.
<tr>
<td><a href="Samples/ContextMenu">Context menu</a></td>
<td><a href="Samples/XamlContextMenu">Context menu (XAML)</a></td>
<td><a href="Samples/UserSelection">Disabling selection</a></td>
<td><a href="Samples/XamlDataVirtualization">Data virtualization</a></td>
</tr>
<tr>
<td><a href="Samples/UserSelection">Disabling selection</a></td>
<td><a href="Samples/DisplayOrientation">Display orientation</a></td>
<td><a href="Samples/DWriteTextLayoutCloudFont">Downloadable fonts (DirectWrite)</a></td>
<td><a href="Samples/XamlCloudFontIntegration">Downloadable fonts (XAML)</a></td>
</tr>
<tr>
<td><a href="Samples/XamlCloudFontIntegration">Downloadable fonts (XAML)</a></td>
<td><a href="Samples/XamlDragAndDrop">Drag and drop</a></td>
<td><a href="Samples/XamlFocusVisuals">Focus visuals</a></td>
<td><a href="Samples/FullScreenMode">Full screen mode</a></td>
</tr>
<tr>
<td><a href="Samples/FullScreenMode">Full screen mode</a></td>
<td><a href="Samples/DWriteLineSpacingModes">Line spacing (DirectWrite)</a></td>
<td><a href="Samples/XamlListView">ListView and GridView</a></td>
<td><a href="Samples/LockScreenApps">Lock screen apps</a></td>
</tr>
<tr>
<td><a href="Samples/LockScreenApps">Lock screen apps</a></td>
<td><a href="Samples/MessageDialog">Message dialog</a></td>
<td><a href="Samples/MultipleViews">Multiple views</a></td>
<td><a href="Samples/OCR">OCR</a></td>
</tr>
<tr>
<td><a href="Samples/OCR">OCR</a></td>
<td><a href="Samples/Printing">Printing</a></td>
<td><a href="Samples/XamlPullToRefresh">Pull-to-refresh</a></td>
<td><a href="Samples/XamlResponsiveTechniques">Responsiveness techniques</a></td>
</tr>
<tr>
<td><a href="Samples/XamlResponsiveTechniques">Responsiveness techniques</a></td>
<td><a href="Samples/DpiScaling">Scaling according to DPI</a></td>
<td><a href="Samples/SplashScreen">Splash screen</a></td>
<td><a href="Samples/XamlStateTriggers">State triggers</a></td>
</tr>
<tr>
<td><a href="Samples/XamlStateTriggers">State triggers</a></td>
<td><a href="Samples/XamlTailoredMultipleViews">Tailored multiple views</a></td>
<td><a href="Samples/TitleBar">Title bar</a></td>
<td><a href="Samples/XamlUIBasics">UI basics (XAML)</a></td>
</tr>
<tr>
<td><a href="Samples/XamlUIBasics">UI basics (XAML)</a></td>
<td><a href="Samples/UserInteractionMode">User interaction mode</a></td>
<td><a href="Samples/WebView">WebView control (HTML)</a></td>
</tr>
<tr>
<td><a href="Samples/ResizeAppView">Window resizing</a></td>
</tr>
</table>

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

@ -0,0 +1,58 @@
<!---
category: ContactsAndCalendar
-->
# Contact Card integration sample
This sample shows how to integrate your app into the People App's contact card and the Mini Contact card by using [**annotations**](https://msdn.microsoft.com/en-us/library/windows/apps/windows.applicationmodel.contacts.contactannotationlist.aspx).
**Note** The Windows universal samples require Visual Studio 2015 to build and Windows 10 to execute.
To obtain information about Windows 10 development, go to the [Windows Dev Center](https://dev.windows.com)
To obtain information about Microsoft Visual Studio 2015 and the tools for developing Windows apps, go to [Visual Studio 2015](http://go.microsoft.com/fwlink/?LinkID=532422)
## Related topics
### Samples
[**ContactCards**](../ContactCards)
[**ContactPicker**](../ContactPicker)
### Reference
[**ContactAnnotationList**](https://msdn.microsoft.com/en-us/library/windows/apps/windows.applicationmodel.contacts.contactannotationlist.aspx)
[**ContactAnnotation**](https://msdn.microsoft.com/en-us/library/windows/apps/windows.applicationmodel.contacts.contactannotation.aspx)
[**Windows.ApplicationModel.Contacts**](http://msdn.microsoft.com/library/windows/apps/br225002)
[**Handling URI activation (XAML)**](https://technet.microsoft.com/en-us/windowsserver/hh779670)
## System requirements
**Client:** Windows 10
**Server:** Windows Server 2016 Technical Preview
**Phone:** Windows 10
## Build the sample
1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with the sample you want to build.
2. Start Microsoft Visual Studio 2015 and select **File** \> **Open** \> **Project/Solution**.
3. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the subfolder for this specific sample, then the subfolder for your preferred language (C++, C#, or JavaScript). Double-click the Visual Studio?2015 Solution (.sln) file.
4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
## Run the sample
The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
### Deploying the sample
- Select Build > Deploy Solution.
### Deploying and running the sample
- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.

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

@ -0,0 +1,180 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SDKTemplate</RootNamespace>
<AssemblyName>ContactCardIntegration</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<ItemGroup>
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\SharedContent\cs\App.xaml.cs">
<Link>App.xaml.cs</Link>
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="..\..\..\SharedContent\cs\MainPage.xaml.cs">
<Link>MainPage.xaml.cs</Link>
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="..\..\..\SharedContent\cs\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>
<Compile Include="SampleConfiguration.cs" />
<Compile Include="Scenario1_CreateContacts.xaml.cs">
<DependentUpon>Scenario1_CreateContacts.xaml</DependentUpon>
</Compile>
<Compile Include="Scenario2_ReceiveContact.xaml.cs">
<DependentUpon>Scenario2_ReceiveContact.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="..\..\..\SharedContent\xaml\App.xaml">
<Link>App.xaml</Link>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="..\..\..\SharedContent\cs\MainPage.xaml">
<Link>MainPage.xaml</Link>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Scenario1_CreateContacts.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="..\..\..\SharedContent\xaml\Styles.xaml">
<Link>Styles\Styles.xaml</Link>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Scenario2_ReceiveContact.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Content Include="..\..\..\SharedContent\cs\Default.rd.xml">
<Link>Properties\Default.rd.xml</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\microsoft-sdk.png">
<Link>Assets\microsoft-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\smalltile-sdk.png">
<Link>Assets\smallTile-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\splash-sdk.png">
<Link>Assets\splash-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\squaretile-sdk.png">
<Link>Assets\squareTile-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\storelogo-sdk.png">
<Link>Assets\storeLogo-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\tile-sdk.png">
<Link>Assets\tile-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\windows-sdk.png">
<Link>Assets\windows-sdk.png</Link>
</Content>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.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>
-->
</Project>

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

@ -0,0 +1,40 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContactCardIntegration", "ContactCardIntegration.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

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

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity
Name="Microsoft.SDKSamples.ContactCardIntegration.CS"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="b9d4fe1b-c990-4d36-9df1-bdd8b5b31509" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>Contact Card Integration C# Sample</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Logo>Assets\StoreLogo-sdk.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="ContactCardIntegration.App"
Executable="$targetnametoken$.exe"
EntryPoint="ContactCardIntegration.App">
<uap:VisualElements
DisplayName="Contact Card Integration C# sample"
Square150x150Logo="Assets\squareTile-sdk.png"
Square44x44Logo="Assets\SmallTile-sdk.png"
Description="Contact Card Integration C# sample"
BackgroundColor="#00b2f0">
<uap:SplashScreen Image="Assets\Splash-sdk.png" />
<uap:DefaultTile>
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo" />
</uap:ShowNameOnTiles>
</uap:DefaultTile>
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="ms-voip-call">
<uap:DisplayName>TestCallApp</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="ms-voip-video">
<uap:DisplayName>TestVideoApp</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="ms-ipmessaging">
<uap:DisplayName>TestMsgApp</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="ms-contact-profile">
<uap:DisplayName>TestProfileApp</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<uap:Capability Name="contacts" />
</Capabilities>
</Package>

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

@ -0,0 +1,71 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
using System;
using System.Collections.Generic;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace SDKTemplate
{
public partial class MainPage : Page
{
public const string FEATURE_NAME = "Contact Card integration C# Sample";
List<Scenario> scenarios = new List<Scenario>
{
new Scenario() { Title="Create contacts with annotations", ClassType=typeof(Scenario1_CreateContacts)},
new Scenario() { Title="Receiving a contact", ClassType=typeof(Scenario2_ReceiveContact) },
};
public void NavigateToPageWithParameter(int pageIndex, object parameter)
{
ScenarioControl.SelectedIndex = pageIndex;
ScenarioFrame.Navigate(scenarios[pageIndex].ClassType, parameter);
}
}
public class Scenario
{
public string Title { get; set; }
public Type ClassType { get; set; }
}
public partial class App : Application
{
/// <summary>
// Handle protocol activations.
/// </summary>
protected override void OnActivated(IActivatedEventArgs e)
{
if (e.Kind == ActivationKind.Protocol)
{
Frame rootFrame = CreateRootFrame();
if (rootFrame.Content == null)
{
if (!rootFrame.Navigate(typeof(MainPage)))
{
throw new Exception("Failed to create initial page");
}
}
var p = rootFrame.Content as MainPage;
p.NavigateToPageWithParameter(1, e);
// Ensure the current window is active
Window.Current.Activate();
}
}
}
}

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

@ -0,0 +1,53 @@
<!--
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
-->
<Page
x:Class="SDKTemplate.Scenario1_CreateContacts"
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">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer Margin="12,20,12,12">
<StackPanel>
<TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
<TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap">
Create test contacts with annotations
</TextBlock>
<Button Content="Create test contacts" Click="{x:Bind CreateTestContacts}" Margin="0,10,0,0"/>
<TextBlock Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" Margin="0,10,0,0">
In the People app, go to the contact named TestContact1.
Viewing that contact's profile launches this application.
</TextBlock>
<TextBlock Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" Margin="0,10,0,0">
In the People app, go to the contact named TestContact2.
You can send a message using this app, place a call via this app,
or make a video call via this app.
</TextBlock>
<TextBlock Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" Margin="0,10,0,0">
When an app such as the ContactCards sample displays a mini contact card
for TestContact1 or TestContact2,
this app will appear as an available action.
</TextBlock>
<Button Content="Delete test contacts" Click="{x:Bind DeleteTestContacts}" Margin="0,10,0,0"/>
</StackPanel>
</ScrollViewer>
</Grid>
</Page>

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

@ -0,0 +1,196 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.ApplicationModel.Contacts;
namespace SDKTemplate
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Scenario1_CreateContacts : Page
{
private MainPage rootPage = MainPage.Current;
public Scenario1_CreateContacts()
{
this.InitializeComponent();
}
private async Task<ContactList> _GetContactList()
{
ContactStore store = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
if (null == store)
{
rootPage.NotifyUser("Unable to get a contacts store.", NotifyType.ErrorMessage);
return null;
}
ContactList contactList;
IReadOnlyList<ContactList> contactLists = await store.FindContactListsAsync();
if (0 == contactLists.Count)
{
contactList = await store.CreateContactListAsync("TestContactList");
}
else
{
contactList = contactLists[0];
}
return contactList;
}
private async Task<ContactAnnotationList> _GetContactAnnotationList()
{
ContactAnnotationStore annotationStore = await ContactManager.RequestAnnotationStoreAsync(ContactAnnotationStoreAccessType.AppAnnotationsReadWrite);
if (null == annotationStore)
{
rootPage.NotifyUser("Unable to get an annotations store.", NotifyType.ErrorMessage);
return null;
}
ContactAnnotationList annotationList;
IReadOnlyList<ContactAnnotationList> annotationLists = await annotationStore.FindAnnotationListsAsync();
if (0 == annotationLists.Count)
{
annotationList = await annotationStore.CreateAnnotationListAsync();
}
else
{
annotationList = annotationLists[0];
}
return annotationList;
}
private async void CreateTestContacts()
{
//
// Creating two test contacts with email address and phone number.
//
Contact contact1 = new Contact();
contact1.FirstName = "TestContact1";
ContactEmail email1 = new ContactEmail();
email1.Address = "TestContact1@contoso.com";
contact1.Emails.Add(email1);
ContactPhone phone1 = new ContactPhone();
phone1.Number = "4255550100";
contact1.Phones.Add(phone1);
Contact contact2 = new Contact();
contact2.FirstName = "TestContact2";
ContactEmail email2 = new ContactEmail();
email2.Address = "TestContact2@contoso.com";
email2.Kind = ContactEmailKind.Other;
contact2.Emails.Add(email2);
ContactPhone phone2 = new ContactPhone();
phone2.Number = "4255550101";
phone2.Kind = ContactPhoneKind.Mobile;
contact2.Phones.Add(phone2);
// Save the contacts
ContactList contactList = await _GetContactList();
if (null == contactList)
{
return;
}
await contactList.SaveContactAsync(contact1);
await contactList.SaveContactAsync(contact2);
//
// Create annotations for those test contacts.
// Annotation is the contact meta data that allows People App to generate deep links
// in the contact card that takes the user back into this app.
//
ContactAnnotationList annotationList = await _GetContactAnnotationList();
if (null == annotationList)
{
return;
}
ContactAnnotation annotation = new ContactAnnotation();
annotation.ContactId = contact1.Id;
// Remote ID: The identifier of the user relevant for this app. When this app is
// launched into from the People App, this id will be provided as context on which user
// the operation (e.g. ContactProfile) is for.
annotation.RemoteId = "user12";
// The supported operations flags indicate that this app can fulfill these operations
// for this contact. These flags are read by apps such as the People App to create deep
// links back into this app. This app must also be registered for the relevant
// protocols in the Package.appxmanifest (in this case, ms-contact-profile).
annotation.SupportedOperations = ContactAnnotationOperations.ContactProfile;
if (!await annotationList.TrySaveAnnotationAsync(annotation))
{
rootPage.NotifyUser("Failed to save annotation for TestContact1 to the store.", NotifyType.ErrorMessage);
return;
}
annotation = new ContactAnnotation();
annotation.ContactId = contact2.Id;
annotation.RemoteId = "user22";
// You can also specify multiple supported operations for a contact in a single
// annotation. In this case, this annotation indicates that the user can be
// communicated via VOIP call, Video Call, or IM via this application.
annotation.SupportedOperations = ContactAnnotationOperations.Message |
ContactAnnotationOperations.AudioCall |
ContactAnnotationOperations.VideoCall;
if (!await annotationList.TrySaveAnnotationAsync(annotation))
{
rootPage.NotifyUser("Failed to save annotation for TestContact2 to the store.", NotifyType.ErrorMessage);
return;
}
rootPage.NotifyUser("Sample data created successfully.", NotifyType.StatusMessage);
}
private async void DeleteTestContacts()
{
ContactList contactList = null;
ContactStore store = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
if (null != store)
{
IReadOnlyList<ContactList> contactLists = await store.FindContactListsAsync();
if (0 < contactLists.Count)
{
contactList = contactLists[0];
}
}
if (null != contactList)
{
await contactList.DeleteAsync();
rootPage.NotifyUser("Sample data deleted.", NotifyType.StatusMessage);
}
else
{
rootPage.NotifyUser("Could not delete sample data.", NotifyType.ErrorMessage);
}
}
}
}

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

@ -0,0 +1,36 @@
<!--
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
-->
<Page
x:Class="SDKTemplate.Scenario2_ReceiveContact"
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">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer Margin="12,20,12,12">
<StackPanel>
<TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
<TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap">
Receiving a contact
</TextBlock>
<TextBlock Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" Margin="0,10,0,0">
Use the People app or a mini contact card as described in Scenario 1
to activate this application with a contact.
</TextBlock>
</StackPanel>
</ScrollViewer>
</Grid>
</Page>

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

@ -0,0 +1,47 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
using System;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.ApplicationModel.Activation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace SDKTemplate
{
/// <summary>
/// Page to handle the protocol activation. In this case we simply show the URI and the
/// parameters passed to it.
/// </summary>
public sealed partial class Scenario2_ReceiveContact : Page
{
public Scenario2_ReceiveContact()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var args = e.Parameter as ProtocolActivatedEventArgs;
// Display the result of the protocol activation if we got here as a result of being activated for a protocol.
if (args != null)
{
// Parse the URI to extract the protocol and the contact ids
Uri uri = args.Uri;
MainPage.Current.NotifyUser("Activated with protocol = " + uri.Scheme + ", parameters = " + uri.Query, NotifyType.StatusMessage);
}
}
}
}

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

@ -0,0 +1,16 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}

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

@ -120,21 +120,28 @@ namespace Tasks
StorageFile logFile = await localFolder.CreateFileAsync(logFileName, CreationCollisionOption.OpenIfExists);
// Create a protected file
ProtectedFileCreateResult result = await FileProtectionManager.CreateProtectedAndOpenAsync(localFolder,
fileName, m_EnterpriseID, CreationCollisionOption.ReplaceExisting);
// Create a protected file allows the creation of new files even after keys are dropped so that application
// can create and continue writing to files under lock
m_fileProtStatus = result.ProtectionInfo.Status.ToString();
// Write to File
using (IOutputStream outputStream = result.Stream.GetOutputStreamAt(0))
var result = await FileProtectionManager.CreateProtectedAndOpenAsync(localFolder,
fileName,
m_EnterpriseID,
CreationCollisionOption.ReplaceExisting
);
using (var stream = result.Stream)
{
DataWriter writer = new DataWriter(outputStream);
for (int i = 0; i < 100; i++)
m_fileProtStatus = result.ProtectionInfo.Status.ToString();
// Write to File
using (IOutputStream outputStream = result.Stream.GetOutputStreamAt(0))
{
writer.WriteString(textBody);
await writer.StoreAsync();
DataWriter writer = new DataWriter(outputStream);
for (int i = 0; i < 100; i++)
{
writer.WriteString(textBody);
await writer.StoreAsync();
}
}
}

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

@ -18,7 +18,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="RootPage">
SizeChanged="FileOpenPickerPage_SizeChanged">
<Page.Resources>
<Style x:Key="BaseStatusStyle" TargetType="TextBlock">
@ -79,6 +79,7 @@
<TextBlock x:Name="ScenarioListLabel" Text="Select Scenario:" Grid.Row="1" Style="{StaticResource SubheaderTextBlockStyle}" Margin="0,5,0,0" />
<ListBox x:Name="Scenarios" Margin="0,0,20,0" Grid.Row="2" AutomationProperties.Name="Scenarios" HorizontalAlignment="Left"
VerticalAlignment="Top" ScrollViewer.HorizontalScrollBarVisibility="Auto"
SelectionChanged="{x:Bind OnScenarioSelectionChanged}"
AutomationProperties.LabeledBy="{Binding ElementName=ScenarioListLabel}" MaxHeight="125">
<ListBox.ItemTemplate>
<DataTemplate>

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

@ -28,9 +28,6 @@ namespace SDKTemplate
{
public const string FEATURE_NAME = "File Open Picker Page";
public event System.EventHandler ScenarioLoaded;
public event EventHandler<FileOpenPickerPageSizeChangedEventArgs> FileOpenPickerPageResized;
public Windows.ApplicationModel.Activation.LaunchActivatedEventArgs LaunchArgs;
public static FileOpenPickerPage Current;
@ -70,22 +67,13 @@ namespace SDKTemplate
HiddenFrame.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
LayoutRoot.Children.Add(HiddenFrame);
// Populate the sample title from the constant in the GlobalVariables.cs file.
// Populate the sample title from the constant in this file.
SetFeatureName(FEATURE_NAME);
Scenarios.SelectionChanged += Scenarios_SelectionChanged;
SizeChanged += FileOpenPickerPage_SizeChanged;
}
void FileOpenPickerPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
InvalidateSize();
if (FileOpenPickerPageResized != null)
{
FileOpenPickerPageSizeChangedEventArgs args = new FileOpenPickerPageSizeChangedEventArgs();
args.Width = this.ActualWidth;
FileOpenPickerPageResized(this, args);
}
}
/// <summary>
@ -220,11 +208,6 @@ namespace SDKTemplate
// Populate the input and output sections with the newly loaded content.
InputSection.Content = input;
OutputSection.Content = output;
if (ScenarioLoaded != null)
{
ScenarioLoaded(this, new EventArgs());
}
}
else
{
@ -236,7 +219,7 @@ namespace SDKTemplate
}
void Scenarios_SelectionChanged(object sender, SelectionChangedEventArgs e)
void OnScenarioSelectionChanged()
{
if (Scenarios.SelectedItem != null)
{
@ -284,15 +267,4 @@ namespace SDKTemplate
FeatureName.Text = str;
}
}
public class FileOpenPickerPageSizeChangedEventArgs : EventArgs
{
private double width;
public double Width
{
get { return width; }
set { width = value; }
}
}
}

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

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
<Identity Name="Microsoft.SDKSamples.WebAccountManagement.CPP" Publisher="CN=3B3B1E5A-CE36-4D75-AEDA-6809021F7AA1" Version="1.1.0.8" />
<mp:PhoneIdentity PhoneProductId="35ba7848-dfec-48e3-9197-ac01fd9d3e74" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Identity Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Name="Microsoft.SDKSamples.WebAccountManagement.CPP" Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="ecd494c6-8bb7-4f4e-b04a-a4e96b9eba60" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>Web Account Manager C++ Sample</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>

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

@ -42,7 +42,7 @@ namespace SDKTemplate
Platform::String^ MICROSOFT_PROVIDER_ID = "https://login.microsoft.com";
Platform::String^ CONSUMER_AUTHORITY = "consumers";
Platform::String^ MSA_SCOPE_REQUESTED = "service::wl.basic::DELEGATION";
Platform::String^ MSA_SCOPE_REQUESTED = "wl.basic";
Platform::String^ MSA_CLIENT_ID = "none";
Platform::String^ STORED_ACCOUNT_ID_KEY = "accountid";
Windows::Security::Credentials::WebAccountProvider^ m_provider;

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

@ -44,7 +44,7 @@ namespace SDKTemplate
Platform::String^ MICROSOFT_PROVIDER_ID = "https://login.microsoft.com";
Platform::String^ CONSUMER_AUTHORITY = "consumers";
Platform::String^ ORGANIZATION_AUTHORITY = "organizations";
Platform::String^ MSA_SCOPE_REQUESTED = "service::wl.basic::DELEGATION";
Platform::String^ MSA_SCOPE_REQUESTED = "wl.basic";
Platform::String^ MSA_CLIENT_ID = "none";
Platform::String^ AAD_SCOPE_REQUESTED = "";
Platform::String^ AAD_CLIENT_ID = "c8542080-6873-47b5-bf71-d56378567ceb";

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

@ -45,7 +45,7 @@ namespace SDKTemplate
Platform::String^ MICROSOFT_PROVIDER_ID = "https://login.microsoft.com";
Platform::String^ CONSUMER_AUTHORITY = "consumers";
Platform::String^ ORGANIZATION_AUTHORITY = "organizations";
Platform::String^ MSA_SCOPE_REQUESTED = "service::wl.basic::DELEGATION";
Platform::String^ MSA_SCOPE_REQUESTED = "wl.basic";
Platform::String^ MSA_CLIENT_ID = "none";
Platform::String^ AAD_SCOPE_REQUESTED = "";
Platform::String^ AAD_CLIENT_ID = "c8542080-6873-47b5-bf71-d56378567ceb";

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

@ -47,7 +47,7 @@ namespace SDKTemplate
Platform::String^ MICROSOFT_PROVIDER_ID = "https://login.microsoft.com";
Platform::String^ CONSUMER_AUTHORITY = "consumers";
Platform::String^ ORGANIZATION_AUTHORITY = "organizations";
Platform::String^ MSA_SCOPE_REQUESTED = "service::wl.basic::DELEGATION";
Platform::String^ MSA_SCOPE_REQUESTED = "wl.basic";
Platform::String^ MSA_CLIENT_ID = "none";
Platform::String^ AAD_SCOPE_REQUESTED = "";
Platform::String^ AAD_CLIENT_ID = "c8542080-6873-47b5-bf71-d56378567ceb";

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

@ -251,9 +251,6 @@
<Link>Assets\windows-sdk.png</Link>
</Image>
</ItemGroup>
<ItemGroup>
<SDKReference Include="WindowsDesktop, Version=10.0.10240.0" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

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

@ -67,7 +67,7 @@ namespace Accounts
const string AzureActiveDirectoryAuthority = "organizations";
const string MicrosoftAccountClientId = "none";
const string MicrosoftAccountScopeRequested = "service::wl.basic::DELEGATION";
const string MicrosoftAccountScopeRequested = "wl.basic";
// To obtain azureAD tokens, you must register this app on the AzureAD portal, and obtain the client ID
const string AzureActiveDirectoryClientId = "";

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

@ -41,7 +41,7 @@ namespace Accounts
const string AzureActiveDirectoryAuthority = "organizations";
const string MicrosoftAccountClientId = "none";
const string MicrosoftAccountScopeRequested = "service::wl.basic::DELEGATION";
const string MicrosoftAccountScopeRequested = "wl.basic";
// To obtain azureAD tokens, you must register this app on the AzureAD portal, and obtain the client ID
const string AzureActiveDirectoryClientId = "";

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

@ -42,7 +42,7 @@ namespace Accounts
const string StoredAuthorityKey = "authority";
const string MicrosoftAccountClientId = "none";
const string MicrosoftAccountScopeRequested = "service::wl.basic::DELEGATION";
const string MicrosoftAccountScopeRequested = "wl.basic";
// To obtain azureAD tokens, you must register this app on the AzureAD portal, and obtain the client ID
const string AzureActiveDirectoryClientId = "";

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

@ -32,7 +32,7 @@ namespace Accounts
// Then, you must associate the app with the store.
const string MicrosoftAccountProviderId = "https://login.microsoft.com";
const string ConsumerAuthority = "consumers";
const string AccountScopeRequested = "service::wl.basic::DELEGATION";
const string AccountScopeRequested = "wl.basic";
const string AccountClientId = "none";
const string StoredAccountKey = "accountid";

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

@ -0,0 +1,62 @@
<!---
category: ControlsLayoutAndText
--->
# Data virtualization sample
This sample shows how to implement a data source for XAML list controls that implements data virtualization.
Specifically, this sample shows how to:
- **Implement IItemsRangeInfo:** Use the IItemsRangeInfo interface to understand which items are in view or the buffer area for a list view, and to manage a cache containing those items.
- **Implement ISelectionInfo:** Use the ISelectionInfo interface to manage the selection of items in the list, accounting for the data virtualization.
**Note** The Windows universal samples require Visual Studio 2015 to build and Windows 10 to execute.
To obtain information about Windows 10, go to [Windows 10](http://go.microsoft.com/fwlink/?LinkID=532421)
To obtain information about Microsoft Visual Studio 2015 and the tools for developing Windows apps, go to [Visual Studio 2015](http://go.microsoft.com/fwlink/?LinkID=532422)
## Related topics
[ListView and GridView UI optimization](https://msdn.microsoft.com/en-us/library/windows/apps/mt204776.aspx)
### Samples
[XAML data binding](https://code.msdn.microsoft.com/windowsapps/Data-Binding-7b1d67b5/)
[XAML data binding with x:Bind](../XamlBind)
### Reference
<!-- Add links to related API -->
[IItemsRangeInfo](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.data.iitemsrangeinfo.aspx)
[ISelectionInfo](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.data.iselectioninfo.aspx)
## System requirements
**Client:** Windows 10
**Server:** Windows Server 2016 Technical Preview
**Phone:** Windows 10
## Build the sample
1. Start Microsoft Visual Studio 2015 and select **File** \> **Open** \> **Project/Solution**.
2. Go to the directory to which you unzipped the sample. Double-click the Visual Studio 2015 Solution (.sln) file.
3. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
## Run the sample
The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
### Deploying the sample
- Select Build > Deploy Solution.
### Deploying and running the sample
- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
- The sample uses the StorageFolder API to read the contents of the Pictures folder, if you don't see any results in the sample, its likely that no pictures could be found.

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

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DataVirtualization</RootNamespace>
<AssemblyName>DataVirtualization</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<EnableProjectNCompatibleProfile>true</EnableProjectNCompatibleProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseProjectNToolchain>true</UseProjectNToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NETFX_CORE;WINDOWS_UAP;CODE_ANALYSIS</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseProjectNToolchain>true</UseProjectNToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NETFX_CORE;WINDOWS_UAP;CODE_ANALYSIS</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseProjectNToolchain>true</UseProjectNToolchain>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\SharedContent\cs\App.xaml.cs">
<Link>App.xaml.cs</Link>
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="..\..\..\SharedContent\cs\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>
<Compile Include="SampleConfiguration.cs" />
<Compile Include="Scenario1\ItemCacheManager.cs" />
<Compile Include="Scenario1\FileDataSource.cs" />
<Compile Include="Scenario1\FileItem.cs" />
<Compile Include="Scenario1\ItemIndexRangeExtensions.cs" />
<Compile Include="Scenario1\ItemIndexRangeList.cs" />
<Compile Include="Scenario2\FileDataSource2.cs" />
<Compile Include="Scenario1\Scenario1.xaml.cs">
<DependentUpon>Scenario1.xaml</DependentUpon>
</Compile>
<Compile Include="Scenario2\Scenario2.xaml.cs">
<DependentUpon>Scenario2.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="..\..\..\SharedContent\xaml\App.xaml">
<Link>App.xaml</Link>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Scenario1\Scenario1.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Scenario2\Scenario2.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="..\..\..\SharedContent\xaml\Styles.xaml">
<Link>Styles\Styles.xaml</Link>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<Content Include="..\..\..\SharedContent\media\microsoft-sdk.png">
<Link>Assets\microsoft-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\smalltile-sdk.png">
<Link>Assets\smallTile-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\splash-sdk.png">
<Link>Assets\splash-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\squaretile-sdk.png">
<Link>Assets\squareTile-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\storelogo-sdk.png">
<Link>Assets\storeLogo-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\tile-sdk.png">
<Link>Assets\tile-sdk.png</Link>
</Content>
<Content Include="..\..\..\SharedContent\media\windows-sdk.png">
<Link>Assets\windows-sdk.png</Link>
</Content>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.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>
-->
</Project>

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

@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.22823.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataVirtualization", "DataVirtualization.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(TeamFoundationVersionControl) = preSolution
SccNumberOfProjects = 2
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
SccTeamFoundationServer = https://funnyfarm.visualstudio.com/defaultcollection
SccLocalPath0 = .
SccProjectUniqueName1 = DataVirtualizationSample\\DataVirtualizationSample.csproj
SccProjectName1 = DataVirtualizationSample
SccLocalPath1 = DataVirtualizationSample
EndGlobalSection
EndGlobal

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

@ -0,0 +1,101 @@
<!--
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
-->
<Page
x:Class="SDKTemplate.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SDKTemplate"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="Main"
mc:Ignorable="d">
<Page.Resources>
<local:ScenarioBindingConverter x:Key="ScenarioConverter"></local:ScenarioBindingConverter>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="wideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="641" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Splitter.DisplayMode" Value="Inline"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="narrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Splitter.DisplayMode" Value="Overlay"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SplitView x:Name="Splitter" IsPaneOpen="True" Grid.Column="1">
<SplitView.Pane>
<RelativePanel Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}">
<StackPanel x:Name="HeaderPanel" Orientation="Horizontal">
<Image x:Name="WindowsLogo" Stretch="None" Source="Assets/windows-sdk.png" Margin="0,15,0,0" />
<TextBlock x:Name="Header" Text="Windows platform sample" Style="{StaticResource TagLineTextStyle}" Margin="0,15,0,0" />
</StackPanel>
<TextBlock x:Name="SampleTitle" Text="Sample Title Here" Style="{StaticResource SampleHeaderTextStyle}" TextWrapping="Wrap" RelativePanel.Below="HeaderPanel" Margin="0,10,0,0"/>
<ListBox x:Name="ScenarioControl" SelectionChanged="ScenarioControl_SelectionChanged"
SelectionMode="Single" HorizontalAlignment="Left" Style="{StaticResource ScenarioListBoxStyle}"
VerticalAlignment="Top" RelativePanel.Below="SampleTitle" Margin="0,10,0,0" RelativePanel.Above="FooterPanel">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource ScenarioConverter}}" Style="{StaticResource ListItemTextStyle}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel x:Name="FooterPanel" Orientation="Vertical" RelativePanel.AlignBottomWithPanel="True">
<Image Source="Assets/microsoft-sdk.png" AutomationProperties.Name="Microsoft Logo" Stretch="None" HorizontalAlignment="Left" Margin="10,0,0,0"/>
<TextBlock x:Name="Copyright" Text="&#xA9; Microsoft Corporation. All rights reserved." Style="{StaticResource CopyrightTextStyle}"
RelativePanel.Above="LinksPanel" Margin="10,10,0,0"
TextWrapping="Wrap"/>
<StackPanel x:Name="LinksPanel" Orientation="Horizontal" Margin="10,10,0,10">
<HyperlinkButton Content="Trademarks" Tag="http://www.microsoft.com/About/Legal/EN/US/IntellectualProperty/Trademarks/EN-US.aspx"
Click="Footer_Click" FontSize="12" Style="{StaticResource HyperlinkStyle}" />
<TextBlock Text="|" Style="{StaticResource SeparatorStyle}" VerticalAlignment="Center" />
<HyperlinkButton x:Name="PrivacyLink" Content="Privacy" Tag="http://privacy.microsoft.com" Click="Footer_Click" FontSize="12" Style="{StaticResource HyperlinkStyle}"/>
</StackPanel>
</StackPanel>
</RelativePanel>
</SplitView.Pane>
<RelativePanel>
<Frame x:Name="ScenarioFrame" Margin="0,5,0,0" RelativePanel.AlignTopWithPanel="True" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" RelativePanel.Above="StatusPanel"/>
<StackPanel x:Name="StatusPanel" Orientation="Vertical" RelativePanel.AlignBottomWithPanel="True" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True">
<TextBlock x:Name="StatusLabel" Margin="0,0,0,10" TextWrapping="Wrap" Text="Status:" />
<Border x:Name="StatusBorder" Margin="0,0,0,0" Visibility="Collapsed" >
<TextBlock x:Name="StatusBlock" FontWeight="Bold" MaxHeight="200" MinWidth="{Binding ElementName=Splitter, Path=ActualWidth}" TextTrimming="CharacterEllipsis" Margin="20,10,10,20" TextWrapping="Wrap"/>
</Border>
</StackPanel>
</RelativePanel>
</SplitView>
<Border Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}">
<ToggleButton Style="{StaticResource SymbolButton}" Click="Button_Click" VerticalAlignment="Top" Foreground="{ThemeResource ApplicationForegroundThemeBrush}">
<ToggleButton.Content>
<FontIcon x:Name="Hamburger" FontFamily="Segoe MDL2 Assets" Glyph="&#xE700;" Margin="0,10,0,0"/>
</ToggleButton.Content>
</ToggleButton>
</Border>
</Grid>
</Page>

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

@ -0,0 +1,136 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace SDKTemplate
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public static MainPage Current;
public MainPage()
{
this.InitializeComponent();
// This is a static public property that allows downstream pages to get a handle to the MainPage instance
// in order to call methods that are in this class.
Current = this;
SampleTitle.Text = FEATURE_NAME;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Populate the scenario list from the SampleConfiguration.cs file
ScenarioControl.ItemsSource = scenarios;
if (Window.Current.Bounds.Width < 640)
{
ScenarioControl.SelectedIndex = -1;
}
else
{
ScenarioControl.SelectedIndex = 0;
}
}
/// <summary>
/// Called whenever the user changes selection in the scenarios list. This method will navigate to the respective
/// sample scenario page.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ScenarioControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Clear the status block when navigating scenarios.
NotifyUser(String.Empty, NotifyType.StatusMessage);
ListBox scenarioListBox = sender as ListBox;
Scenario s = scenarioListBox.SelectedItem as Scenario;
if (s != null)
{
ScenarioFrame.Navigate(s.ClassType);
if (Window.Current.Bounds.Width < 640)
{
Splitter.IsPaneOpen = false;
StatusBorder.Visibility = Visibility.Collapsed;
}
}
}
public List<Scenario> Scenarios
{
get { return this.scenarios; }
}
/// <summary>
/// Used to display messages to the user
/// </summary>
/// <param name="strMessage"></param>
/// <param name="type"></param>
public void NotifyUser(string strMessage, NotifyType type)
{
switch (type)
{
case NotifyType.StatusMessage:
StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Green);
break;
case NotifyType.ErrorMessage:
StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Red);
break;
}
StatusBlock.Text = strMessage;
// Collapse the StatusBlock if it has no text to conserve real estate.
StatusBorder.Visibility = (StatusBlock.Text != String.Empty) ? Visibility.Visible : Visibility.Collapsed;
}
async void Footer_Click(object sender, RoutedEventArgs e)
{
await Windows.System.Launcher.LaunchUriAsync(new Uri(((HyperlinkButton)sender).Tag.ToString()));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Splitter.IsPaneOpen = !Splitter.IsPaneOpen;
StatusBorder.Visibility = Visibility.Collapsed;
}
}
public enum NotifyType
{
StatusMessage,
ErrorMessage
};
public class ScenarioBindingConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
Scenario s = value as Scenario;
return (MainPage.Current.Scenarios.IndexOf(s) + 1) + ") " + s.Title;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return true;
}
}
}

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

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity
Name="Microsoft.SDKSamples.DataVirtualization.CS"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="2084f1ac-a7cf-4c1d-a82b-d9a560ab5b48" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>Data Virtualization C# Sample</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Logo>Assets\StoreLogo-sdk.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="DataVirtualization.App"
Executable="$targetnametoken$.exe"
EntryPoint="DataVirtualization.App">
<uap:VisualElements
DisplayName="Data Virtualization C# Sample"
Square150x150Logo="Assets\squareTile-sdk.png"
Square44x44Logo="Assets\SmallTile-sdk.png"
Description="Data Virtualization C# Sample"
BackgroundColor="#00b2f0">
<uap:SplashScreen Image="Assets\Splash-sdk.png" />
<uap:DefaultTile>
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo" />
</uap:ShowNameOnTiles>
</uap:DefaultTile>
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<uap:Capability Name="picturesLibrary"/>
</Capabilities>
</Package>

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

@ -0,0 +1,35 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
using System;
using System.Collections.Generic;
using Windows.UI.Xaml.Controls;
using DataVirtualizationSample;
namespace SDKTemplate
{
public partial class MainPage : Page
{
public const string FEATURE_NAME = "Data Virtualization Sample";
List<Scenario> scenarios = new List<Scenario>
{
new Scenario() { Title="Data Virtualization", ClassType=typeof(Scenario1)},
new Scenario() { Title="Selection Management", ClassType=typeof(Scenario2)},
};
}
public class Scenario
{
public string Title { get; set; }
public Type ClassType { get; set; }
}
}

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

@ -0,0 +1,269 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Search;
using Windows.UI.Core;
using Windows.UI.Xaml.Data;
namespace DataVirtualizationSample
{
//********************************************************************************************
//*
//* Note: This sample uses a custom compiler constant to enable tracing. If you add
//* TRACE_DATASOURCE to the Conditional compilation symbols of the Build tab of the
//* Project Properties window, then the application will spit out trace data to the
//* Output window while debugging.
//*
//********************************************************************************************
/// <summary>
/// A custom datasource over the file system that supports data virtualization
/// </summary>
class FileDataSource : INotifyCollectionChanged, System.Collections.IList, IItemsRangeInfo
{
// Folder that we are browsing
private StorageFolder _folder;
// Query object that will tell us if the folder content changed
private StorageFileQueryResult _queryResult;
// Dispatcher so we can marshal calls back to the UI thread
private CoreDispatcher _dispatcher;
// Cache for the file data that is currently being used
private ItemCacheManager<FileItem> itemCache;
// Total number of files available
private int _count = 1;
public event NotifyCollectionChangedEventHandler CollectionChanged;
private FileDataSource()
{
//Setup the dispatcher for the UI thread
_dispatcher = Windows.UI.Xaml.Window.Current.Dispatcher;
// The ItemCacheManager does most of the heavy lifting. We pass it a callback that it will use to actually fetch data, and the max size of a request
this.itemCache = new ItemCacheManager<FileItem>(fetchDataCallback, 50);
this.itemCache.CacheChanged += ItemCache_CacheChanged;
}
// Factory method to create the datasource
// Requires async work which is why it needs a factory rather than being part of the constructor
public static async Task<FileDataSource> GetDataSoure(string path)
{
FileDataSource ds = new FileDataSource();
StorageFolder f = await StorageFolder.GetFolderFromPathAsync(path);
await ds.SetFolder(f);
return ds;
}
// Set functionality for the folder
public async Task SetFolder(StorageFolder folder)
{
//unhook the old contents changed event if applicable
if (_queryResult != null)
{
_queryResult.ContentsChanged -= QueryResult_ContentsChanged;
}
// Initialize the query and register for changes
_folder = folder;
QueryOptions options = new QueryOptions();
// options.IndexerOption = IndexerOption.DoNotUseIndexer;
_queryResult = _folder.CreateFileQueryWithOptions(options);
_queryResult.ContentsChanged += QueryResult_ContentsChanged;
await UpdateCount();
}
// Handler for when the filesystem notifies us of a change to the file list
private void QueryResult_ContentsChanged(IStorageQueryResultBase sender, object args)
{
// This callback can occur on a different thread so we need to marshal it back to the UI thread
if (!_dispatcher.HasThreadAccess)
{
var t = _dispatcher.RunAsync(CoreDispatcherPriority.Normal, ResetCollection);
}
else
{
ResetCollection();
}
}
// Handles a change notification for the list of files from the OS
private void ResetCollection()
{
// Unhook the old change notification
if (itemCache != null)
{
this.itemCache.CacheChanged -= ItemCache_CacheChanged;
}
// Create a new instance of the cache manager
this.itemCache = new ItemCacheManager<FileItem>(fetchDataCallback, 50);
this.itemCache.CacheChanged += ItemCache_CacheChanged;
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
async Task UpdateCount()
{
_count = (int)await _queryResult.GetItemCountAsync();
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
#region IList Implementation
public bool Contains(object value)
{
return IndexOf(value) != -1;
}
public int IndexOf(object value)
{
return (value != null) ? itemCache.IndexOf((FileItem)value) : -1;
}
public object this[int index]
{
get
{
// The cache will return null if it doesn't have the item. Once the item is fetched it will fire a changed event so that we can inform the list control
return itemCache[index];
}
set
{
throw new NotImplementedException();
}
}
public int Count
{
get { return _count; }
}
#endregion
//Required for the IItemsRangeInfo interface
public void Dispose()
{
itemCache = null;
}
/// <summary>
/// Primary method for IItemsRangeInfo interface
/// Is called when the list control's view is changed
/// </summary>
/// <param name="visibleRange">The range of items that are actually visible</param>
/// <param name="trackedItems">Additional set of ranges that the list is using, for example the buffer regions and focussed element</param>
public void RangesChanged(ItemIndexRange visibleRange, IReadOnlyList<ItemIndexRange> trackedItems)
{
#if TRACE_DATASOURCE
string s = string.Format("* RangesChanged fired: Visible {0}->{1}", visibleRange.FirstIndex, visibleRange.LastIndex);
foreach (ItemIndexRange r in trackedItems) { s += string.Format(" {0}->{1}", r.FirstIndex, r.LastIndex); }
Debug.WriteLine(s);
#endif
// We know that the visible range is included in the broader range so don't need to hand it to the UpdateRanges call
// Update the cache of items based on the new set of ranges. It will callback for additional data if required
itemCache.UpdateRanges(trackedItems.ToArray());
}
// Callback from itemcache that it needs items to be retrieved
// Using this callback model abstracts the details of this specific datasource from the cache implementation
private async Task<FileItem[]> fetchDataCallback(ItemIndexRange batch, CancellationToken ct)
{
// Fetch file objects from filesystem
IReadOnlyList<StorageFile> results = await _queryResult.GetFilesAsync((uint)batch.FirstIndex, Math.Max(batch.Length, 20)).AsTask(ct);
List<FileItem> files = new List<FileItem>();
if (results != null)
{
for (int i = 0; i < results.Count; i++)
{
// Check if request has been cancelled, if so abort getting additional data
ct.ThrowIfCancellationRequested();
// Create our FileItem object with the file data and thumbnail
FileItem newItem = await FileItem.fromStorageFile(results[i], ct);
files.Add(newItem);
}
}
return files.ToArray();
}
// Event fired when items are inserted in the cache
// Used to fire our collection changed event
private void ItemCache_CacheChanged(object sender, CacheChangedEventArgs<FileItem> args)
{
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, args.oldItem, args.newItem, args.itemIndex));
}
}
#region Parts of IList Not Implemented
public int Add(object value)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public void Insert(int index, object value)
{
throw new NotImplementedException();
}
public bool IsFixedSize
{
get { return false; }
}
public bool IsReadOnly
{
get { return false; }
}
public void Remove(object value)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public bool IsSynchronized
{
get { throw new NotImplementedException(); }
}
public object SyncRoot
{
get { throw new NotImplementedException(); }
}
public System.Collections.IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
#endregion
}
}

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

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media.Imaging;
using System.Diagnostics;
using Windows.Storage.Search;
using Windows.Storage.FileProperties;
using Windows.UI.Core;
using System.Threading;
namespace DataVirtualizationSample
{
/// <summary>
/// Represents a file and its properties
/// </summary>
class FileItem
{
public string Filename { get; set; }
public int Size { get; set; }
public BitmapImage ImageData { get; set; }
public string Key { get; private set; }
// Needed to ensure only one request is in progress at once
private static SemaphoreSlim gettingFileProperties = new SemaphoreSlim(1);
// Fetches all the data for the specified file
public async static Task<FileItem> fromStorageFile(StorageFile f, CancellationToken ct)
{
FileItem item = new FileItem();
item.Filename = f.DisplayName;
// Block to make sure we only have one request outstanding
await gettingFileProperties.WaitAsync();
BasicProperties bp = null;
try
{
bp = await f.GetBasicPropertiesAsync().AsTask(ct);
}
catch (Exception) { }
finally
{
gettingFileProperties.Release();
}
ct.ThrowIfCancellationRequested();
item.Size = (int)bp.Size;
item.Key = f.FolderRelativeId;
StorageItemThumbnail thumb = await f.GetThumbnailAsync(ThumbnailMode.SingleItem).AsTask(ct);
ct.ThrowIfCancellationRequested();
BitmapImage img = new BitmapImage();
await img.SetSourceAsync(thumb).AsTask(ct);
item.ImageData = img;
return item;
}
}
}

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

@ -0,0 +1,413 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml.Data;
namespace DataVirtualizationSample
{
// EventArgs class for the CacheChanged event
public class CacheChangedEventArgs<T> : EventArgs
{
public T oldItem { get; set; }
public T newItem { get; set; }
public int itemIndex { get; set; }
}
// Implements a relatively simple cache for items based on a set of ranges
class ItemCacheManager<T>
{
// data structure to hold all the items that are in the ranges the cache manager is looking after
private List<CacheEntryBlock<T>> cacheBlocks;
// List of ranges for items that are not present in the cache
internal ItemIndexRangeList requests;
// list of ranges for items that are present in the cache
private ItemIndexRangeList cachedResults;
// Range of items that is currently being requested
private ItemIndexRange requestInProgress;
// Used to be able to cancel outstanding requests
private CancellationTokenSource cancelTokenSource;
// Callback that will be used to request data
private fetchDataCallbackHandler fetchDataCallback;
// Maximum number of items that can be fetched in one batch
private int maxBatchFetchSize;
// Timer to optimize the the fetching of data so we throttle requests if the list is still changing
private Windows.UI.Xaml.DispatcherTimer timer;
#if DEBUG
// Name for trace messages, and when debugging so you know which instance of the cache manager you are dealing with
string debugName = string.Empty;
#endif
public ItemCacheManager(fetchDataCallbackHandler callback, int batchsize = 50, string debugName = "ItemCacheManager")
{
cacheBlocks = new List<CacheEntryBlock<T>>();
requests = new ItemIndexRangeList();
cachedResults = new ItemIndexRangeList();
fetchDataCallback = callback;
maxBatchFetchSize = batchsize;
//set up a timer that is used to delay fetching data so that we can catch up if the list is scrolling fast
timer = new Windows.UI.Xaml.DispatcherTimer();
timer.Tick += (sender, args) =>
{
fetchData();
};
timer.Interval = new TimeSpan(20 * 10000);
#if DEBUG
this.debugName = debugName;
#endif
#if TRACE_DATASOURCE
Debug.WriteLine(debugName + "* Cache initialized/reset");
#endif
}
public event TypedEventHandler<object, CacheChangedEventArgs<T>> CacheChanged;
/// <summary>
/// Indexer for access to the item cache
/// </summary>
/// <param name="index">Item Index</param>
/// <returns></returns>
public T this[int index]
{
get
{
// iterates through the cache blocks to find the item
foreach (CacheEntryBlock<T> block in cacheBlocks)
{
if (index >= block.FirstIndex && index <= block.lastIndex)
{
return block.Items[index - block.FirstIndex];
}
}
return default(T);
}
set
{
// iterates through the cache blocks to find the right block
for (int i = 0; i < cacheBlocks.Count; i++)
{
CacheEntryBlock<T> block = cacheBlocks[i];
if (index >= block.FirstIndex && index <= block.lastIndex)
{
block.Items[index - block.FirstIndex] = value;
//register that we have the result in the cache
if (value != null) { cachedResults.Add((uint)index, 1); }
return;
}
// We have moved past the block where the item is supposed to live
if (block.FirstIndex > index)
{
AddOrExtendBlock(index, value, i);
return;
}
}
// No blocks exist, so creating a new block
AddOrExtendBlock(index, value, cacheBlocks.Count);
}
}
// Extends an existing block if the item fits at the end, or creates a new block
private void AddOrExtendBlock(int index, T value, int insertBeforeBlock)
{
if (insertBeforeBlock > 0)
{
CacheEntryBlock<T> block = cacheBlocks[insertBeforeBlock - 1];
if (block.lastIndex == index - 1)
{
T[] newItems = new T[block.Length + 1];
Array.Copy(block.Items, newItems, (int)block.Length);
newItems[block.Length] = value;
block.Length++;
block.Items = newItems;
return;
}
}
CacheEntryBlock<T> newBlock = new CacheEntryBlock<T>() { FirstIndex = index, Length = 1, Items = new T[] { value } };
cacheBlocks.Insert(insertBeforeBlock, newBlock);
}
/// <summary>
/// Updates the desired item range of the cache, discarding items that are not needed, and figuring out which items need to be requested. It will then kick off a fetch if required.
/// </summary>
/// <param name="ranges">New set of ranges the cache should hold</param>
public void UpdateRanges(ItemIndexRange[] ranges)
{
//Normalize ranges to get a unique set of discontinuous ranges
ranges = NormalizeRanges(ranges);
// Fail fast if the ranges haven't changed
if (!HasRangesChanged(ranges)) { return; }
//To make the cache update easier, we'll create a new set of CacheEntryBlocks
List<CacheEntryBlock<T>> newCacheBlocks = new List<CacheEntryBlock<T>>();
foreach (ItemIndexRange range in ranges)
{
CacheEntryBlock<T> newBlock = new CacheEntryBlock<T>() { FirstIndex = range.FirstIndex, Length = range.Length, Items = new T[range.Length] };
newCacheBlocks.Add(newBlock);
}
#if TRACE_DATASOURCE
string s = "┌ " + debugName + ".UpdateRanges: ";
foreach (ItemIndexRange range in ranges)
{
s += range.FirstIndex + "->" + range.LastIndex + " ";
}
Debug.WriteLine(s);
#endif
//Copy over data to the new cache blocks from the old ones where there is overlap
int lastTransferred = 0;
for (int i = 0; i < ranges.Length; i++)
{
CacheEntryBlock<T> newBlock = newCacheBlocks[i];
ItemIndexRange range = ranges[i];
int j = lastTransferred;
while (j < this.cacheBlocks.Count && this.cacheBlocks[j].FirstIndex <= ranges[i].LastIndex)
{
ItemIndexRange overlap, oldEntryRange;
ItemIndexRange[] added, removed;
CacheEntryBlock<T> oldBlock = this.cacheBlocks[j];
oldEntryRange = new ItemIndexRange(oldBlock.FirstIndex, oldBlock.Length);
bool hasOverlap = oldEntryRange.DiffRanges(range, out overlap, out removed, out added);
if (hasOverlap)
{
Array.Copy(oldBlock.Items, overlap.FirstIndex - oldBlock.FirstIndex, newBlock.Items, overlap.FirstIndex - range.FirstIndex, (int)overlap.Length);
#if TRACE_DATASOURCE
Debug.WriteLine("│ Transfering cache items " + overlap.FirstIndex + "->" + overlap.LastIndex);
#endif
}
j++;
if (ranges.Length > i + 1 && oldBlock.lastIndex < ranges[i + 1].FirstIndex) { lastTransferred = j; }
}
}
//swap over to the new cache
this.cacheBlocks = newCacheBlocks;
//figure out what items need to be fetched because we don't have them in the cache
this.requests = new ItemIndexRangeList(ranges);
ItemIndexRangeList newCachedResults = new ItemIndexRangeList();
// Use the previous knowlege of what we have cached to form the new list
foreach (ItemIndexRange range in ranges)
{
foreach (ItemIndexRange cached in this.cachedResults)
{
ItemIndexRange overlap;
ItemIndexRange[] added, removed;
bool hasOverlap = cached.DiffRanges(range, out overlap, out removed, out added);
if (hasOverlap) { newCachedResults.Add(overlap); }
}
}
// remove the data we know we have cached from the results
foreach (ItemIndexRange range in newCachedResults)
{
this.requests.Subtract(range);
}
this.cachedResults = newCachedResults;
startFetchData();
#if TRACE_DATASOURCE
s = "└ Pending requests: ";
foreach (ItemIndexRange range in this.requests)
{
s += range.FirstIndex + "->" + range.LastIndex + " ";
}
Debug.WriteLine(s);
#endif
}
// Compares the new ranges against the previous ones to see if they have changed
private bool HasRangesChanged(ItemIndexRange[] ranges)
{
if (ranges.Length != cacheBlocks.Count)
{
return true;
}
for (int i = 0; i < ranges.Length; i++)
{
ItemIndexRange r = ranges[i];
CacheEntryBlock<T> block = this.cacheBlocks[i];
if (r.FirstIndex != block.FirstIndex || r.LastIndex != block.lastIndex)
{
return true;
}
}
return false;
}
// Gets the first block of items that we don't have values for
public ItemIndexRange GetFirstRequestBlock(int maxsize = 50)
{
if (this.requests.Count > 0)
{
ItemIndexRange range = this.requests[0];
if (range.Length > 50) range = new ItemIndexRange(range.FirstIndex, 50);
return range;
}
return null;
}
// Throttling function for fetching data. Forces a wait of 20ms before making the request.
// If another fetch is requested in that time, it will reset the timer, so we don't fetch data if the view is actively scrolling
public void startFetchData()
{
// Verify if an active request is still needed
if (this.requestInProgress != null)
{
if (this.requests.Intersects(requestInProgress))
{
return;
}
else
{
//cancel the existing request
#if TRACE_DATASOURCE
Debug.WriteLine("> " + debugName + " Cancelling request: " + requestInProgress.FirstIndex + "->" + requestInProgress.LastIndex);
#endif
cancelTokenSource.Cancel();
}
}
//Using a timer to delay fetching data by 20ms, if another range comes in that time, then the timer is reset.
timer.Stop();
timer.Start();
}
public delegate Task<T[]> fetchDataCallbackHandler(ItemIndexRange range, CancellationToken ct);
// Called by the timer to make a request for data
public async void fetchData()
{
//Stop the timer so we don't get fired again unless data is requested
timer.Stop();
if (this.requestInProgress != null)
{
// Verify if an active request is still needed
if (this.requests.Intersects(requestInProgress))
{
return;
}
else
{
// Cancel the existing request
Debug.WriteLine(">" + debugName + " Cancelling request: " + requestInProgress.FirstIndex + "->" + requestInProgress.LastIndex);
cancelTokenSource.Cancel();
}
}
ItemIndexRange nextRequest = GetFirstRequestBlock(maxBatchFetchSize);
if (nextRequest != null)
{
cancelTokenSource = new CancellationTokenSource();
CancellationToken ct = cancelTokenSource.Token;
requestInProgress = nextRequest;
T[] data = null;
try
{
#if TRACE_DATASOURCE
Debug.WriteLine(">" + debugName + " Fetching items " + nextRequest.FirstIndex + "->" + nextRequest.LastIndex);
#endif
// Use the callback to get the data, passing in a cancellation token
data = await fetchDataCallback(nextRequest, ct);
if (!ct.IsCancellationRequested)
{
#if TRACE_DATASOURCE
Debug.WriteLine(">" + debugName + " Inserting items into cache at: " + nextRequest.FirstIndex + "->" + (nextRequest.FirstIndex + data.Length - 1));
#endif
for (int i = 0; i < data.Length; i++)
{
int cacheIndex = (int)(nextRequest.FirstIndex + i);
T oldItem = this[cacheIndex];
T newItem = data[i];
if (!newItem.Equals(oldItem))
{
this[cacheIndex] = newItem;
// Fire CacheChanged so that the datasource can fire its INCC event, and do other work based on the item having data
if (CacheChanged != null)
{
CacheChanged(this, new CacheChangedEventArgs<T>() { oldItem = oldItem, newItem = newItem, itemIndex = cacheIndex });
}
}
}
requests.Subtract(new ItemIndexRange(nextRequest.FirstIndex, (uint)data.Length));
}
}
// Try/Catch is needed as cancellation is via an exception
catch (OperationCanceledException) { }
finally
{
requestInProgress = null;
// Start another request if required
fetchData();
}
}
}
/// <summary>
/// Merges a set of ranges to form a new set of non-contiguous ranges
/// </summary>
/// <param name="ranges">The list of ranges to merge</param>
/// <returns>A smaller set of merged ranges</returns>
private ItemIndexRange[] NormalizeRanges(ItemIndexRange[] ranges)
{
List<ItemIndexRange> results = new List<ItemIndexRange>();
foreach (ItemIndexRange range in ranges)
{
bool handled = false;
for (int i = 0; i < results.Count; i++)
{
ItemIndexRange existing = results[i];
if (range.ContiguousOrOverlaps(existing))
{
results[i] = existing.Combine(range);
handled = true;
break;
}
else if (range.FirstIndex < existing.FirstIndex)
{
results.Insert(i, range);
handled = true;
break;
}
}
if (!handled) { results.Add(range); }
}
return results.ToArray();
}
// Sees if the value is in our cache if so it returns the index
public int IndexOf(T value)
{
foreach (CacheEntryBlock<T> entry in cacheBlocks)
{
int index = Array.IndexOf<T>(entry.Items, value);
if (index != -1) return index + entry.FirstIndex;
}
return -1;
}
// Type for the cache blocks
class CacheEntryBlock<ITEMTYPE>
{
public int FirstIndex;
public uint Length;
public ITEMTYPE[] Items;
public int lastIndex { get { return FirstIndex + (int)Length - 1; } }
}
}
}

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

@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media.Imaging;
using System.Diagnostics;
using Windows.Storage.Search;
using Windows.Storage.FileProperties;
using Windows.UI.Core;
namespace DataVirtualizationSample
{
// Extension methods for ItemIndexRange
public static class ItemIndexRangeExtensions
{
public static bool Equals(this ItemIndexRange This, ItemIndexRange range)
{
return (This.FirstIndex == range.FirstIndex && This.Length == range.Length);
}
public static bool ContiguousOrOverlaps(this ItemIndexRange This, ItemIndexRange range)
{
return (range.FirstIndex >= This.FirstIndex && range.FirstIndex <= This.LastIndex + 1) || (range.LastIndex + 1 >= This.FirstIndex && range.LastIndex <= This.LastIndex);
}
public static bool Intersects(this ItemIndexRange This, ItemIndexRange range)
{
return (range.FirstIndex >= This.FirstIndex && range.FirstIndex <= This.LastIndex) || (range.LastIndex >= This.FirstIndex && range.LastIndex <= This.LastIndex);
}
public static bool Intersects(this ItemIndexRange This, int FirstIndex, uint Length)
{
int LastIndex = FirstIndex + (int)Length - 1;
return (FirstIndex >= This.FirstIndex && FirstIndex <= This.LastIndex) || (LastIndex >= This.FirstIndex && LastIndex <= This.LastIndex);
}
public static ItemIndexRange Combine(this ItemIndexRange This, ItemIndexRange range)
{
int start = Math.Min(This.FirstIndex, range.FirstIndex);
int end = Math.Max(This.LastIndex, range.LastIndex);
return new ItemIndexRange(start, 1 + (uint)Math.Abs(end - start));
}
public static bool DiffRanges(this ItemIndexRange RangeA, ItemIndexRange RangeB, out ItemIndexRange InBothAandB, out ItemIndexRange[] OnlyInRangeA, out ItemIndexRange[] OnlyInRangeB)
{
List<ItemIndexRange> exA = new List<ItemIndexRange>();
List<ItemIndexRange> exB = new List<ItemIndexRange>();
int i, j;
i = Math.Max(RangeA.FirstIndex, RangeB.FirstIndex);
j = Math.Min(RangeA.LastIndex, RangeB.LastIndex);
if (i <= j)
{
// Ranges intersect
InBothAandB = new ItemIndexRange(i, (uint)(1 + j - i));
if (RangeA.FirstIndex < i) exA.Add(new ItemIndexRange(RangeA.FirstIndex, (uint)(i - RangeA.FirstIndex)));
if (RangeA.LastIndex > j) exA.Add(new ItemIndexRange(j + 1, (uint)(RangeA.LastIndex - j)));
if (RangeB.FirstIndex < i) exB.Add(new ItemIndexRange(RangeB.FirstIndex, (uint)(i - RangeB.FirstIndex)));
if (RangeB.LastIndex > j) exB.Add(new ItemIndexRange(j + 1, (uint)(RangeB.LastIndex - j)));
OnlyInRangeA = exA.ToArray();
OnlyInRangeB = exB.ToArray();
return true;
}
else
{
InBothAandB = default(ItemIndexRange);
OnlyInRangeA = new ItemIndexRange[] { RangeA };
OnlyInRangeB = new ItemIndexRange[] { RangeB };
return false;
}
}
public static ItemIndexRange Overlap(this ItemIndexRange RangeA, ItemIndexRange RangeB)
{
int i, j;
i = Math.Max(RangeA.FirstIndex, RangeB.FirstIndex);
j = Math.Min(RangeA.LastIndex, RangeB.LastIndex);
if (i <= j)
{
// Ranges intersect
return new ItemIndexRange(i, (uint)(1 + j - i));
}
else
{
return null;
}
}
}
}

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

@ -0,0 +1,238 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Windows.UI.Xaml.Data;
namespace DataVirtualizationSample
{
/// <summary>
/// Represents a sorted collection of discontiguous ItemIndexRanges
///
/// </summary>
class ItemIndexRangeList : IList<ItemIndexRange>
{
private List<ItemIndexRange> _ranges;
public ItemIndexRangeList()
{
this._ranges = new List<ItemIndexRange>();
}
public ItemIndexRangeList(List<ItemIndexRange> ranges)
{
this._ranges = NormalizeRanges(ranges);
}
public ItemIndexRangeList(ItemIndexRange[] ranges)
{
this._ranges = NormalizeRanges(ranges);
}
public List<ItemIndexRange> ToList()
{
return this._ranges;
}
public ItemIndexRange[] ToArray()
{
return this._ranges.ToArray();
}
/// <summary>
/// Merges the range into the rangelist, combining with existing ranges if necessary
/// </summary>
/// <param name="newrange">Range to merge into the collection</param>
public void Add(ItemIndexRange newrange)
{
for (int i = 0; i < this._ranges.Count; i++)
{
ItemIndexRange existing = this._ranges[i];
if (newrange.ContiguousOrOverlaps(existing))
{
existing = existing.Combine(newrange);
for (int j = i + 1; j < this._ranges.Count; j++)
{
ItemIndexRange next = this._ranges[j];
if (existing.ContiguousOrOverlaps(next))
{
existing = existing.Combine(next);
this._ranges.RemoveAt(i + 1);
}
}
this._ranges[i] = existing;
return;
}
else if (newrange.LastIndex < existing.FirstIndex)
{
this._ranges.Insert(i, newrange);
return;
}
}
this._ranges.Add(newrange);
}
/// <summary>
/// Merges the range into the rangelist, combining with existing ranges if necessary
/// </summary>
public void Add(uint FirstIndex, uint Length)
{
this.Add(new ItemIndexRange((int)FirstIndex, Length));
}
/// <summary>
/// Removes a range from the collection, splitting existing ranges if necessary
/// </summary>
public void Subtract(ItemIndexRange range)
{
for (int idx = 0; idx < this._ranges.Count; idx++)
{
ItemIndexRange existing = this._ranges[idx];
if (existing.FirstIndex > range.LastIndex) return;
int i, j;
i = Math.Max(existing.FirstIndex, range.FirstIndex);
j = Math.Min(existing.LastIndex, range.LastIndex);
if (i <= j)
{
if (existing.FirstIndex < i && existing.LastIndex > j)
{
//range is in the middle of existing range, so split existing into two
this._ranges[idx] = (new ItemIndexRange(existing.FirstIndex, (uint)(i - existing.FirstIndex)));
this._ranges.Insert(idx + 1, new ItemIndexRange(j + 1, (uint)(existing.LastIndex - j)));
return;
}
else if (existing.LastIndex > j)
{
//range ends before existing so trim existing to be the remainder
this._ranges[idx] = new ItemIndexRange(j + 1, (uint)(existing.LastIndex - j));
return;
}
else if (existing.FirstIndex < i)
{
//range starts after existing so trim existing to the part before range
this._ranges[idx] = new ItemIndexRange(existing.FirstIndex, (uint)(i - existing.FirstIndex));
}
else
{
//existing is overlapped by range, so remove it.
this._ranges.RemoveAt(idx);
}
//trim the subtracted range to the remainder, and exit if complete
if (range.LastIndex > j)
{
range = new ItemIndexRange(j + 1, (uint)(range.LastIndex - j));
}
else { return; }
}
}
}
public void Subtract(uint FirstIndex, uint Length)
{
this.Subtract(new ItemIndexRange((int)FirstIndex, Length));
}
public bool Intersects(ItemIndexRange range)
{
foreach (ItemIndexRange r in this._ranges)
{
if (r.Intersects(range))
{
return true;
}
}
return false;
}
// Merges contiguous or overlapping ranges to ensure the collection is discontiguous
// Also sorts the ranges so they start in index order
private List<ItemIndexRange> NormalizeRanges(IEnumerable<ItemIndexRange> ranges)
{
List<ItemIndexRange> results = new List<ItemIndexRange>();
foreach (ItemIndexRange range in ranges)
{
bool handled = false;
for (int i = 0; i < results.Count; i++)
{
ItemIndexRange existing = results[i];
if (range.ContiguousOrOverlaps(existing))
{
results[i] = existing.Combine(range);
handled = true;
break;
}
else if (range.FirstIndex < existing.FirstIndex)
{
results.Insert(i, range);
handled = true;
break;
}
}
if (!handled) results.Add(range);
}
return results;
}
#region IList implementation
public int Count { get { return ((IList<ItemIndexRange>)_ranges).Count; } }
public bool IsReadOnly { get { return ((IList<ItemIndexRange>)_ranges).IsReadOnly; } }
public ItemIndexRange this[int index]
{
get { return ((IList<ItemIndexRange>)_ranges)[index]; }
set { ((IList<ItemIndexRange>)_ranges)[index] = value; }
}
public IEnumerator<ItemIndexRange> GetEnumerator()
{
return ((IEnumerable<ItemIndexRange>)_ranges).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<ItemIndexRange>)_ranges).GetEnumerator();
}
public int IndexOf(ItemIndexRange item)
{
return ((IList<ItemIndexRange>)_ranges).IndexOf(item);
}
public void Insert(int index, ItemIndexRange item)
{
((IList<ItemIndexRange>)_ranges).Insert(index, item);
}
public void RemoveAt(int index)
{
((IList<ItemIndexRange>)_ranges).RemoveAt(index);
}
public void Clear()
{
((IList<ItemIndexRange>)_ranges).Clear();
}
public bool Contains(ItemIndexRange item)
{
return ((IList<ItemIndexRange>)_ranges).Contains(item);
}
public void CopyTo(ItemIndexRange[] array, int arrayIndex)
{
((IList<ItemIndexRange>)_ranges).CopyTo(array, arrayIndex);
}
public bool Remove(ItemIndexRange item)
{
return ((IList<ItemIndexRange>)_ranges).Remove(item);
}
#endregion
}
}

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

@ -0,0 +1,64 @@
<!--
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
-->
<Page
x:Class="DataVirtualizationSample.Scenario1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DataVirtualizationSample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="RootGrid" Margin="12,10,12,12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Margin="0,0,0,10">
<TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
<TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap">
This scenario demonstartes data virtualization with a custom datasource over the contents of the default pictures folder. The datasource implements IItemsRangeInfo.RangesChanged to get notifications of the items the grid control is displaying. It will fetch and the cache the items the view needs, and update the cache as the view is changed.
</TextBlock>
</StackPanel>
<Grid Grid.Row="1">
<GridView x:Name="Grid1" SelectionMode="Single" ShowsScrollingPlaceholders="False">
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:FileItem">
<Grid Width="200" Height="80">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image Grid.RowSpan="3" Source="{x:Bind ImageData}" Width="70" Height="70" Margin="0,0,5,0" />
<TextBlock Text="{x:Bind Filename}" Grid.Column="1" />
<TextBlock Text="{x:Bind Size}" Grid.Column="1" Grid.Row="1"/>
<TextBlock x:Name="idx" Grid.Column="1" Grid.Row="2"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
<!-- Status Block for providing messages to the user. Use the
NotifyUser() method to populate the message -->
<Border x:Name="ErrorBorder" Background="Red" Grid.Row="2"/>
<TextBlock x:Name="StatusBlock" Grid.Row="2" Margin="12, 10, 12, 10" Visibility="Collapsed"/>
</Grid>
</Page>

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

@ -0,0 +1,66 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using SDKTemplate;
using Windows.Storage;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace DataVirtualizationSample
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Scenario1 : Page
{
public Scenario1()
{
this.InitializeComponent();
Grid1.ContainerContentChanging += Grid1_ContainerContentChanging;
initdata();
}
private void Grid1_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (!args.InRecycleQueue)
{
// Sets a textblock in each item indicating its index
FrameworkElement ctr = (FrameworkElement)args.ItemContainer.ContentTemplateRoot;
if (ctr != null)
{
TextBlock t = (TextBlock)ctr.FindName("idx");
t.Text = args.ItemIndex.ToString();
}
}
}
async void initdata()
{
StorageLibrary pictures = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
string path = pictures.SaveFolder.Path;
FileDataSource ds = await FileDataSource.GetDataSoure(path);
if (ds.Count > 0)
{
Grid1.ItemsSource = ds;
}
else
{
MainPage.Current.NotifyUser("Error: The pictures folder doesn't contain any files", NotifyType.ErrorMessage);
}
}
}
}

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

@ -0,0 +1,405 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Search;
using Windows.UI.Core;
using Windows.UI.Xaml.Data;
namespace DataVirtualizationSample
{
//********************************************************************************************
//*
//* Note: This sample uses a custom compiler constant to enable tracing. If you add
//* TRACE_DATASOURCE to the Conditional compilation symbols of the Build tab of the
//* Project Properties window, then the application will spit out trace data to the
//* Output window while debugging.
//*
//********************************************************************************************
/// <summary>
/// A custom datasource over the file system that supports data virtualization
/// </summary>
class FileDataSource2 : INotifyCollectionChanged, System.Collections.IList, IItemsRangeInfo, ISelectionInfo
{
// Folder that we are browsing
private StorageFolder _folder;
// Query object that will tell us if the folder content changed
private StorageFileQueryResult _queryResult;
// Dispatcher so we can marshal calls back to the UI thread
private CoreDispatcher _dispatcher;
// Cache for the file data that is currently being used
private ItemCacheManager<FileItem> itemCache;
// Total number of files available
private int _count = 1;
public event NotifyCollectionChangedEventHandler CollectionChanged;
private FileDataSource2()
{
//Setup the dispatcher for the UI thread
_dispatcher = Windows.UI.Xaml.Window.Current.Dispatcher;
// The ItemCacheManager does most of the heavy lifting. We pass it a callback that it will use to actually fetch data, and the max size of a request
this.itemCache = new ItemCacheManager<FileItem>(fetchDataCallback, 50);
this.itemCache.CacheChanged += ItemCache_CacheChanged;
// Create another ItemCacheManager for the keys for selection
this.selectionCache = new ItemCacheManager<string>(fetchSelectionDataCallback, 50, "selectionCache");
}
// Handles a change notification for the list of files from the OS
public async void ResetCollection()
{
// Update the selection cache to match the filesystem after the updates
await RemapSelection();
// Unhook the old change notification
if (itemCache != null)
{
this.itemCache.CacheChanged -= ItemCache_CacheChanged;
}
// Create a new instance of the cache manager
this.itemCache = new ItemCacheManager<FileItem>(fetchDataCallback, 50);
this.itemCache.CacheChanged += ItemCache_CacheChanged;
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
//
// Implementation of ISelectionInfo
//
// Storage for the keys of the selected items
private ItemCacheManager<string> selectionCache;
// List of ranges that form the selection
private ItemIndexRangeList selection = new ItemIndexRangeList();
// Called when an item (or items) are selected
public void SelectRange(ItemIndexRange range)
{
selection.Add(range);
selectionCache.UpdateRanges(selection.ToArray());
}
// Called when an item (or items) are deselected
public void DeselectRange(ItemIndexRange range)
{
selection.Subtract(range);
selectionCache.UpdateRanges(selection.ToArray());
}
// Called to determine if an item is selected
public bool IsSelected(int index)
{
foreach (ItemIndexRange range in selection)
{
if (index >= range.FirstIndex && index <= range.LastIndex) return true;
}
return false;
}
// Called to get the selected ranges
public IReadOnlyList<ItemIndexRange> GetSelectedRanges()
{
return selection.ToList();
}
// Callback from the selection cache manager
// Retrieves the keys for selected items
private async Task<string[]> fetchSelectionDataCallback(ItemIndexRange batch, CancellationToken ct)
{
#if TRACE_DATASOURCE
Debug.WriteLine("# SelectionDataCallback: " + batch.FirstIndex + "->" + batch.LastIndex);
#endif
// See if we already have the item in the data cache, if so get the key from there so we don't need to go to the filesystem
var file = itemCache[batch.FirstIndex];
if (file != null)
{
return new string[] { file.Key };
}
// Go get the keys from the file system if necessary
IReadOnlyList<StorageFile> results = await _queryResult.GetFilesAsync((uint)batch.FirstIndex, batch.Length).AsTask(ct);
List<string> keys = new List<string>();
if (results != null)
{
for (int i = 0; i < results.Count; i++)
{
ct.ThrowIfCancellationRequested();
keys.Add(results[i].FolderRelativeId);
}
}
return keys.ToArray();
}
// Called after a reset to figure out the new indexes for the selected items
private async Task RemapSelection()
{
ItemIndexRangeList oldSelection = selection;
ItemCacheManager<string> oldSelectionCache = selectionCache;
ItemIndexRangeList newSelection = new ItemIndexRangeList();
ItemCacheManager<string> newSelectionCache = new ItemCacheManager<string>(fetchSelectionDataCallback, 50, "newSelectionCache");
foreach (ItemIndexRange r in oldSelection)
{
IReadOnlyList<StorageFile> results = null;
int lastResultOffset = 0, lastResultsItemIndex = 0;
for (int i = 0; i < r.Length; i++)
{
int origIndex = r.FirstIndex + i;
string fileid = oldSelectionCache[origIndex];
bool matched = false;
// Optimization to be able to work in batches. Once we get a batch of files from the filesystem we use that to hunt
// for matches rather than having to go ask for the index of each file
if (results != null)
{
for (int j = lastResultOffset + 1; j < results.Count; j++)
{
if (results[j].FolderRelativeId == fileid)
{
lastResultOffset = j;
int itemIndex = lastResultsItemIndex + j;
newSelection.Add((uint)itemIndex, 1);
newSelectionCache[itemIndex] = oldSelectionCache[origIndex];
matched = true;
break;
}
}
}
if (!matched)
{
// Get a starting point for the index of the file
lastResultsItemIndex = (int)(await _queryResult.FindStartIndexAsync(fileid.Substring(fileid.LastIndexOf('\\') + 1)));
lastResultOffset = 0;
// Get the files at that point and see if the keys actually match
results = await _queryResult.GetFilesAsync((uint)lastResultsItemIndex, 50);
if (results[lastResultOffset].FolderRelativeId == fileid)
{
newSelection.Add((uint)lastResultsItemIndex, 1);
newSelectionCache[lastResultsItemIndex] = oldSelectionCache[origIndex];
}
else
{
// We can't find the item, so its no longer part of the selection
}
}
}
}
// Update the fields for the new selection
selection = newSelection;
selectionCache = newSelectionCache;
}
#region Filesystem specific implementation details
// Factory method to create the datasource
// Requires async work which is why it needs a factory rather than being part of the constructor
public static async Task<FileDataSource2> GetDataSoure(string path)
{
FileDataSource2 ds = new FileDataSource2();
StorageFolder f = await StorageFolder.GetFolderFromPathAsync(path);
await ds.SetFolder(f);
return ds;
}
// Set functionality for the folder
public async Task SetFolder(StorageFolder folder)
{
//unhook the old contents changed event if applicable
if (_queryResult != null)
{
_queryResult.ContentsChanged -= QueryResult_ContentsChanged;
}
// Initialize the query and register for changes
_folder = folder;
QueryOptions options = new QueryOptions();
// options.IndexerOption = IndexerOption.DoNotUseIndexer;
_queryResult = _folder.CreateFileQueryWithOptions(options);
_queryResult.ContentsChanged += QueryResult_ContentsChanged;
await UpdateCount();
}
// Handler for when the filesystem notifies us of a change to the file list
private void QueryResult_ContentsChanged(IStorageQueryResultBase sender, object args)
{
// This callback can occur on a different thread so we need to marshal it back to the UI thread
if (!_dispatcher.HasThreadAccess)
{
var t = _dispatcher.RunAsync(CoreDispatcherPriority.Normal, ResetCollection);
}
else
{
ResetCollection();
}
}
async Task UpdateCount()
{
_count = (int)await _queryResult.GetItemCountAsync();
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
//Event fired when items are inserted in the cache
//Used to fire our collection changed event
private void ItemCache_CacheChanged(object sender, CacheChangedEventArgs<FileItem> args)
{
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, args.oldItem, args.newItem, args.itemIndex));
}
}
#endregion
#region IList Implementation
public bool Contains(object value)
{
return IndexOf(value) != -1;
}
public int IndexOf(object value)
{
return (value != null) ? itemCache.IndexOf((FileItem)value) : -1;
}
public object this[int index]
{
get
{
// The cache will return null if it doesn't have the item. Once the item is fetched it will fire a changed event so that we can inform the list control
return itemCache[index];
}
set
{
throw new NotImplementedException();
}
}
public int Count
{
get { return _count; }
}
#endregion
#region IItemsRangeInfo Implementation
//Required for the IItemsRangeInfo interface
public void Dispose()
{
itemCache = null;
}
/// <summary>
/// Primary method for IItemsRangeInfo interface
/// Is called when the list control's view is changed
/// </summary>
/// <param name="visibleRange">The range of items that are actually visible</param>
/// <param name="trackedItems">Additional set of ranges that the list is using, for example the buffer regions and focussed element</param>
public void RangesChanged(ItemIndexRange visibleRange, IReadOnlyList<ItemIndexRange> trackedItems)
{
#if TRACE_DATASOURCE
string s = string.Format("* RangesChanged fired: Visible {0}->{1}", visibleRange.FirstIndex, visibleRange.LastIndex);
foreach (ItemIndexRange r in trackedItems) { s += string.Format(" {0}->{1}", r.FirstIndex, r.LastIndex); }
Debug.WriteLine(s);
#endif
// We know that the visible range is included in the broader range so don't need to hand it to the UpdateRanges call
// Update the cache of items based on the new set of ranges. It will callback for additional data if required
itemCache.UpdateRanges(trackedItems.ToArray());
}
// Callback from itemcache that it needs items to be retrieved
private async Task<FileItem[]> fetchDataCallback(ItemIndexRange batch, CancellationToken ct)
{
// Fetch file objects from filesystem
IReadOnlyList<StorageFile> results = await _queryResult.GetFilesAsync((uint)batch.FirstIndex, Math.Max(batch.Length, 20)).AsTask(ct);
List<FileItem> files = new List<FileItem>();
if (results != null)
{
for (int i = 0; i < results.Count; i++)
{
ct.ThrowIfCancellationRequested();
// Create our FileItem object with the file data and thumbnail
FileItem newItem = await FileItem.fromStorageFile(results[i], ct);
files.Add(newItem);
}
}
return files.ToArray();
}
#endregion
#region Parts of IList Not Implemented
public int Add(object value)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public void Insert(int index, object value)
{
throw new NotImplementedException();
}
public bool IsFixedSize
{
get { return false; }
}
public bool IsReadOnly
{
get { return false; }
}
public void Remove(object value)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public bool IsSynchronized
{
get { throw new NotImplementedException(); }
}
public object SyncRoot
{
get { throw new NotImplementedException(); }
}
public System.Collections.IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
#endregion
}
}

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

@ -0,0 +1,65 @@
<!--
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
-->
<Page
x:Class="DataVirtualizationSample.Scenario2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DataVirtualizationSample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="RootGrid" Margin="12,10,12,12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Margin="0,0,0,10">
<TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
<TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap">
This scenario demonstrates selection with data virtualization with a custom datasource over the contents of the default pictures folder. The datasource implements ISelectionInfo to provide custom handling of selection. The datasource builds on top of the functionality in Scenario 1 implementing the IItemsRangeInfo interface.
</TextBlock>
<Button x:Name="ForceReset" Click="ForceReset_Click">Force a reset</Button>
</StackPanel>
<Grid Grid.Row="1">
<GridView x:Name="Grid1" SelectionMode="Extended" ShowsScrollingPlaceholders="False">
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:FileItem">
<Grid Width="200" Height="80">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image Grid.RowSpan="3" Source="{x:Bind ImageData}" Width="70" Height="70" Margin="0,0,5,0" />
<TextBlock Text="{x:Bind Filename}" Grid.Column="1" />
<TextBlock Text="{x:Bind Size}" Grid.Column="1" Grid.Row="1"/>
<TextBlock x:Name="idx" Grid.Column="1" Grid.Row="2"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
<!-- Status Block for providing messages to the user. Use the
NotifyUser() method to populate the message -->
<Border x:Name="ErrorBorder" Background="Red" Grid.Row="2"/>
<TextBlock x:Name="StatusBlock" Grid.Row="2" Margin="12, 10, 12, 10" Visibility="Collapsed"/>
</Grid>
</Page>

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

@ -0,0 +1,65 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using SDKTemplate;
using Windows.Storage;
namespace DataVirtualizationSample
{
public sealed partial class Scenario2 : Page
{
public Scenario2()
{
this.InitializeComponent();
Grid1.ContainerContentChanging += Grid1_ContainerContentChanging;
initdata();
}
private void Grid1_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (!args.InRecycleQueue)
{
FrameworkElement ctr = (FrameworkElement)args.ItemContainer.ContentTemplateRoot;
if (ctr != null)
{
TextBlock t = (TextBlock)ctr.FindName("idx");
t.Text = args.ItemIndex.ToString();
}
}
}
async void initdata()
{
StorageLibrary pictures = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
string path = pictures.SaveFolder.Path;
FileDataSource2 ds = await FileDataSource2.GetDataSoure(path);
if (ds.Count > 0)
{
Grid1.ItemsSource = ds;
}
else
{
MainPage.Current.NotifyUser("Error: The pictures folder doesn't contain any files", NotifyType.ErrorMessage);
}
}
private void ForceReset_Click(object sender, RoutedEventArgs e)
{
FileDataSource2 ds = Grid1.ItemsSource as FileDataSource2;
if (ds != null) ds.ResetCollection();
}
}
}

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

@ -0,0 +1,16 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}