Merge branch 'master' into muxtestinfra

This commit is contained in:
Alexandre Zollinger Chohfi 2020-09-14 09:48:34 -07:00
Родитель a13fe1f48a 1b08bd6f0a
Коммит 514a419172
91 изменённых файлов: 3 добавлений и 7148 удалений

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

@ -8,10 +8,8 @@
Markdown: Allows you to parse a Markdown String into a Markdown Document, and then Render it with a Markdown Renderer.
RSS: Allows you to parse an RSS content String into an RSS Schema.
</Description>
<PackageTags>UWP Toolkit Windows Parsers Parsing Markdown RSS</PackageTags>
<PackageTags>UWP Toolkit Windows Parsers Parsing Markdown</PackageTags>
</PropertyGroup>
<ItemGroup>

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

@ -1,136 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Toolkit.Extensions;
namespace Microsoft.Toolkit.Parsers.Rss
{
/// <summary>
/// Parser for Atom endpoints.
/// </summary>
internal class AtomParser : BaseRssParser
{
/// <summary>
/// Atom reader implementation to parse Atom content.
/// </summary>
/// <param name="doc">XDocument to parse.</param>
/// <returns>Strong typed response.</returns>
public override IEnumerable<RssSchema> LoadFeed(XDocument doc)
{
Collection<RssSchema> feed = new Collection<RssSchema>();
if (doc.Root == null)
{
return feed;
}
var items = doc.Root.Elements(doc.Root.GetDefaultNamespace() + "entry").Select(item => GetRssSchema(item)).ToList<RssSchema>();
feed = new Collection<RssSchema>(items);
return feed;
}
/// <summary>
/// Retrieves strong type for passed item.
/// </summary>
/// <param name="item">XElement to parse.</param>
/// <returns>Strong typed object.</returns>
private static RssSchema GetRssSchema(XElement item)
{
RssSchema rssItem = new RssSchema
{
Author = GetItemAuthor(item),
Title = item.GetSafeElementString("title").Trim().DecodeHtml(),
ImageUrl = GetItemImage(item),
PublishDate = item.GetSafeElementDate("published"),
FeedUrl = item.GetLink("alternate"),
};
var content = GetItemContent(item);
// Removes scripts from html
if (!string.IsNullOrEmpty(content))
{
rssItem.Summary = ProcessHtmlSummary(content);
rssItem.Content = ProcessHtmlContent(content);
}
string id = item.GetSafeElementString("guid").Trim();
if (string.IsNullOrEmpty(id))
{
id = item.GetSafeElementString("id").Trim();
if (string.IsNullOrEmpty(id))
{
id = rssItem.FeedUrl;
}
}
rssItem.InternalID = id;
return rssItem;
}
/// <summary>
/// Retrieves item author from XElement.
/// </summary>
/// <param name="item">XElement item.</param>
/// <returns>String of Item Author.</returns>
private static string GetItemAuthor(XElement item)
{
var content = string.Empty;
if (item != null && item.Element(item.GetDefaultNamespace() + "author") != null)
{
content = item.Element(item.GetDefaultNamespace() + "author").GetSafeElementString("name");
}
if (string.IsNullOrEmpty(content))
{
content = item.GetSafeElementString("author");
}
return content;
}
/// <summary>
/// Returns item image from XElement item.
/// </summary>
/// <param name="item">XElement item.</param>
/// <returns>String pointing to item image.</returns>
private static string GetItemImage(XElement item)
{
if (!string.IsNullOrEmpty(item.GetSafeElementString("image")))
{
return item.GetSafeElementString("image");
}
return item.GetImage();
}
/// <summary>
/// Returns item content from XElement item.
/// </summary>
/// <param name="item">XElement item.</param>
/// <returns>String of item content.</returns>
private static string GetItemContent(XElement item)
{
var content = item.GetSafeElementString("description");
if (string.IsNullOrEmpty(content))
{
content = item.GetSafeElementString("content");
}
if (string.IsNullOrEmpty(content))
{
content = item.GetSafeElementString("summary");
}
return content;
}
}
}

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

@ -1,59 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Xml.Linq;
using Microsoft.Toolkit.Extensions;
namespace Microsoft.Toolkit.Parsers.Rss
{
/// <summary>
/// Base class for RSS Parser(s).
/// </summary>
internal abstract class BaseRssParser
{
/// <summary>
/// Retrieve feed type from XDocument.
/// </summary>
/// <param name="doc">XDocument doc.</param>
/// <returns>Return feed type.</returns>
public static RssType GetFeedType(XDocument doc)
{
if (doc.Root == null)
{
return RssType.Unknown;
}
XNamespace defaultNamespace = doc.Root.GetDefaultNamespace();
return defaultNamespace.NamespaceName.EndsWith("Atom") ? RssType.Atom : RssType.Rss;
}
/// <summary>
/// Abstract method to be override by specific implementations of the reader.
/// </summary>
/// <param name="doc">XDocument doc.</param>
/// <returns>Returns list of strongly typed results.</returns>
public abstract IEnumerable<RssSchema> LoadFeed(XDocument doc);
/// <summary>
/// Fix up the HTML content.
/// </summary>
/// <param name="htmlContent">Content to be fixed up.</param>
/// <returns>Fixed up content.</returns>
protected internal static string ProcessHtmlContent(string htmlContent)
{
return htmlContent.FixHtml().SanitizeString();
}
/// <summary>
/// Create a summary of the HTML content.
/// </summary>
/// <param name="htmlContent">Content to be processed.</param>
/// <returns>Summary of the content.</returns>
protected internal static string ProcessHtmlSummary(string htmlContent)
{
return htmlContent.DecodeHtml().Trim().Truncate(500).SanitizeString();
}
}
}

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

@ -1,27 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Parsers.Rss
{
/// <summary>
/// Type of RSS.
/// </summary>
internal enum RssType
{
/// <summary>
/// Atom
/// </summary>
Atom,
/// <summary>
/// RSS
/// </summary>
Rss,
/// <summary>
/// Unknown
/// </summary>
Unknown
}
}

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

@ -1,214 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Toolkit.Extensions;
namespace Microsoft.Toolkit.Parsers.Rss
{
/// <summary>
/// RSS reader implementation to parse RSS content.
/// </summary>
internal class Rss2Parser : BaseRssParser
{
/// <summary>
/// RDF Namespace Uri.
/// </summary>
private static readonly XNamespace NsRdfNamespaceUri = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
/// <summary>
/// RDF Elements Namespace Uri.
/// </summary>
private static readonly XNamespace NsRdfElementsNamespaceUri = "http://purl.org/dc/elements/1.1/";
/// <summary>
/// RDF Content Namespace Uri.
/// </summary>
private static readonly XNamespace NsRdfContentNamespaceUri = "http://purl.org/rss/1.0/modules/content/";
/// <summary>
/// This override load and parses the document and return a list of RssSchema values.
/// </summary>
/// <param name="doc">XDocument to be loaded.</param>
/// <returns>Strongly typed list of feeds.</returns>
public override IEnumerable<RssSchema> LoadFeed(XDocument doc)
{
bool isRDF = false;
var feed = new Collection<RssSchema>();
XNamespace defaultNamespace = string.Empty;
if (doc.Root != null)
{
isRDF = doc.Root.Name == (NsRdfNamespaceUri + "RDF");
defaultNamespace = doc.Root.GetDefaultNamespace();
}
foreach (var item in doc.Descendants(defaultNamespace + "item"))
{
var rssItem = isRDF ? ParseRDFItem(item) : ParseRssItem(item);
feed.Add(rssItem);
}
return feed;
}
/// <summary>
/// Parses XElement item into strong typed object.
/// </summary>
/// <param name="item">XElement item to parse.</param>
/// <returns>Strong typed object.</returns>
private static RssSchema ParseItem(XElement item)
{
var rssItem = new RssSchema();
rssItem.Title = item.GetSafeElementString("title").Trim().DecodeHtml();
rssItem.FeedUrl = item.GetSafeElementString("link");
rssItem.Author = GetItemAuthor(item);
string content = item.GetSafeElementString("encoded", NsRdfContentNamespaceUri);
if (string.IsNullOrEmpty(content))
{
content = item.GetSafeElementString("description");
if (string.IsNullOrEmpty(content))
{
content = item.GetSafeElementString("content");
}
}
var summary = item.GetSafeElementString("description");
if (string.IsNullOrEmpty(summary))
{
summary = item.GetSafeElementString("encoded", NsRdfContentNamespaceUri);
}
// Removes scripts from html
if (!string.IsNullOrEmpty(summary))
{
rssItem.Summary = ProcessHtmlSummary(summary);
}
if (!string.IsNullOrEmpty(content))
{
rssItem.Content = ProcessHtmlContent(content);
}
string id = item.GetSafeElementString("guid").Trim();
if (string.IsNullOrEmpty(id))
{
id = item.GetSafeElementString("id").Trim();
if (string.IsNullOrEmpty(id))
{
id = rssItem.FeedUrl;
}
}
rssItem.InternalID = id;
return rssItem;
}
/// <summary>
/// Parses RSS version 1.0 objects.
/// </summary>
/// <param name="item">XElement item.</param>
/// <returns>Strong typed object.</returns>
private static RssSchema ParseRDFItem(XElement item)
{
XNamespace ns = "http://search.yahoo.com/mrss/";
var rssItem = ParseItem(item);
rssItem.PublishDate = item.GetSafeElementDate("date", NsRdfElementsNamespaceUri);
string image = item.GetSafeElementString("image");
if (string.IsNullOrEmpty(image) && item.Elements(ns + "thumbnail").LastOrDefault() != null)
{
var element = item.Elements(ns + "thumbnail").Last();
image = element.Attribute("url").Value;
}
if (string.IsNullOrEmpty(image) && item.ToString().Contains("thumbnail"))
{
image = item.GetSafeElementString("thumbnail");
}
if (string.IsNullOrEmpty(image))
{
image = item.GetImage();
}
rssItem.ImageUrl = image;
return rssItem;
}
/// <summary>
/// Parses RSS version 2.0 objects.
/// </summary>
/// <param name="item">XElement item.</param>
/// <returns>Strong typed object.</returns>
private static RssSchema ParseRssItem(XElement item)
{
XNamespace ns = "http://search.yahoo.com/mrss/";
var rssItem = ParseItem(item);
rssItem.PublishDate = item.GetSafeElementDate("pubDate");
string image = item.GetSafeElementString("image");
if (string.IsNullOrEmpty(image))
{
image = item.GetImageFromEnclosure();
}
if (string.IsNullOrEmpty(image) && item.Elements(ns + "content").LastOrDefault() != null)
{
var element = item.Elements(ns + "content").Last();
if (element.Attribute("type") != null && element.Attribute("type").Value.Contains("image/"))
{
image = element.Attribute("url").Value;
}
}
if (string.IsNullOrEmpty(image) && item.Elements(ns + "thumbnail").LastOrDefault() != null)
{
var element = item.Elements(ns + "thumbnail").Last();
image = element.Attribute("url").Value;
}
if (string.IsNullOrEmpty(image) && item.ToString().Contains("thumbnail"))
{
image = item.GetSafeElementString("thumbnail");
}
if (string.IsNullOrEmpty(image))
{
image = item.GetImage();
}
rssItem.Categories = item.GetSafeElementsString("category");
rssItem.ImageUrl = image;
return rssItem;
}
/// <summary>
/// Retrieve item author from item.
/// </summary>
/// <param name="item">XElement item.</param>
/// <returns>String of item author.</returns>
private static string GetItemAuthor(XElement item)
{
var content = item.GetSafeElementString("creator", NsRdfElementsNamespaceUri).Trim();
if (string.IsNullOrEmpty(content))
{
content = item.GetSafeElementString("author");
}
return content;
}
}
}

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

@ -1,460 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace Microsoft.Toolkit.Parsers.Rss
{
/// <summary>
/// Class with utilities for RSS related works.
/// </summary>
internal static class RssHelper
{
/// <summary>
/// String for regular expression for image pattern.
/// </summary>
private const string ImagePattern = @"<img.*?src=[\""'](.+?)[\""'].*?>";
/// <summary>
/// String for regular expression for hyperlink pattern.
/// </summary>
private const string HyperlinkPattern = @"<a\s+(?:[^>]*?\s+)?href=""([^ ""]*)""";
/// <summary>
/// String for regular expression for height pattern.
/// </summary>
private const string HeightPattern = @"height=(?:(['""])(?<height>(?:(?!\1).)*)\1|(?<height>\S+))";
/// <summary>
/// String for regular expression for width pattern.
/// </summary>
private const string WidthPattern = @"width=(?:(['""])(?<width>(?:(?!\1).)*)\1|(?<width>\S+))";
/// <summary>
/// Regular expression for image pattern.
/// </summary>
private static readonly Regex RegexImages = new Regex(ImagePattern, RegexOptions.IgnoreCase);
/// <summary>
/// Regular expression for hyperlink pattern.
/// </summary>
private static readonly Regex RegexLinks = new Regex(HyperlinkPattern, RegexOptions.IgnoreCase);
/// <summary>
/// Regular expression for height pattern.
/// </summary>
private static readonly Regex RegexHeight = new Regex(HeightPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
/// <summary>
/// Regular expression for width pattern.
/// </summary>
private static readonly Regex RegexWidth = new Regex(WidthPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
/// <summary>
/// Removes \t characters in the string and trim additional space and carriage returns.
/// </summary>
/// <param name="text">Text string.</param>
/// <returns>Sanitized string.</returns>
public static string SanitizeString(this string text)
{
if (string.IsNullOrEmpty(text))
{
return string.Empty;
}
var textArray = text.Split(new[] { "\t" }, StringSplitOptions.RemoveEmptyEntries);
string sanitizedText = string.Empty;
foreach (var item in textArray.ToList())
{
sanitizedText += item.Trim();
}
sanitizedText = string.Join(" ", Regex.Split(sanitizedText, @"(?:\r\n|\n|\r)"));
return sanitizedText;
}
/// <summary>
/// Get item date from <see cref="XElement"/> and element name.
/// </summary>
/// <param name="item">XElement item.</param>
/// <param name="elementName">Name of element.</param>
/// <returns>Item date.</returns>
public static DateTime GetSafeElementDate(this XElement item, string elementName)
{
return GetSafeElementDate(item, elementName, item.GetDefaultNamespace());
}
/// <summary>
/// Get item date from <see cref="XElement"/>, element name and <see cref="XNamespace"/>.
/// </summary>
/// <param name="item">XElement item.</param>
/// <param name="elementName">Name of element.</param>
/// <param name="xNamespace">XNamespace namespace.</param>
/// <returns>Item date.</returns>
public static DateTime GetSafeElementDate(this XElement item, string elementName, XNamespace xNamespace)
{
DateTime date;
XElement element = item.Element(xNamespace + elementName);
if (element == null)
{
return DateTime.Now;
}
if (TryParseDateTime(element.Value, out date))
{
return date;
}
return DateTime.Now;
}
/// <summary>
/// Get item string value for <see cref="XElement"/> and element name.
/// </summary>
/// <param name="item">XElement item.</param>
/// <param name="elementName">Name of element.</param>
/// <returns>Safe string.</returns>
public static string GetSafeElementString(this XElement item, string elementName)
{
if (item == null)
{
return string.Empty;
}
return GetSafeElementString(item, elementName, item.GetDefaultNamespace());
}
/// <summary>
/// Get item string values for <see cref="XElement"/> and element name.
/// </summary>
/// <param name="item">XElement item.</param>
/// <param name="elementName">Name of the element.</param>
/// <returns>Safe list of string values.</returns>
public static IEnumerable<string> GetSafeElementsString(this XElement item, string elementName)
{
return GetSafeElementsString(item, elementName, item.GetDefaultNamespace());
}
/// <summary>
/// Get item string values for <see cref="XElement"/>, element name and namespace.
/// </summary>
/// <param name="item">XElement item.</param>
/// <param name="elementName">Name of element.</param>
/// <param name="xNamespace">XNamespace namespace.</param>
/// <returns>Safe list of string values.</returns>
public static IEnumerable<string> GetSafeElementsString(this XElement item, string elementName, XNamespace xNamespace)
{
if (item != null)
{
IEnumerable<XElement> values = item.Elements(xNamespace + elementName);
return values.Where(f => !string.IsNullOrEmpty(f.Value))
.Select(f => f.Value);
}
return Enumerable.Empty<string>();
}
/// <summary>
/// Get item string value for <see cref="XElement"/>, element name and namespace.
/// </summary>
/// <param name="item">XElement item.</param>
/// <param name="elementName">Name of element.</param>
/// <param name="xNamespace">XNamespace namespace.</param>
/// <returns>Safe string.</returns>
public static string GetSafeElementString(this XElement item, string elementName, XNamespace xNamespace)
{
if (item == null)
{
return string.Empty;
}
XElement value = item.Element(xNamespace + elementName);
if (value != null)
{
return value.Value;
}
return string.Empty;
}
/// <summary>
/// Get feed url to see full original information.
/// </summary>
/// <param name="item">XElement item.</param>
/// <param name="rel">rel attribute value.</param>
/// <returns>String link.</returns>
public static string GetLink(this XElement item, string rel)
{
IEnumerable<XElement> links = item.Elements(item.GetDefaultNamespace() + "link");
var xElements = links as XElement[] ?? links.ToArray();
IEnumerable<string> link = from l in xElements
let xAttribute = l.Attribute("rel")
where xAttribute != null && xAttribute.Value == rel
let attribute = l.Attribute("href")
where attribute != null
select attribute.Value;
var enumerable = link as string[] ?? link.ToArray();
if (!enumerable.Any() && xElements.Any())
{
return xElements.FirstOrDefault().Attributes().First().Value;
}
return enumerable.FirstOrDefault();
}
/// <summary>
/// Get feed image.
/// </summary>
/// <param name="item">XElement item.</param>
/// <returns>Feed data image.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The general catch is intended to avoid breaking the Data Provider by a Html decode exception")]
public static string GetImage(this XElement item)
{
string feedDataImage = null;
try
{
feedDataImage = GetImagesInHTMLString(item.Value).FirstOrDefault();
if (!string.IsNullOrEmpty(feedDataImage) && feedDataImage.EndsWith("'"))
{
feedDataImage = feedDataImage.Remove(feedDataImage.Length - 1);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
return feedDataImage;
}
/// <summary>
/// Get the item image from the enclosure element http://www.w3schools.com/rss/rss_tag_enclosure.asp
/// </summary>
/// <param name="item">XElement item.</param>
/// <returns>Feed data image.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The general catch is intended to avoid breaking the Data Provider by a Html decode exception")]
public static string GetImageFromEnclosure(this XElement item)
{
string feedDataImage = null;
try
{
XElement element = item.Element(item.GetDefaultNamespace() + "enclosure");
if (element == null)
{
return string.Empty;
}
var typeAttribute = element.Attribute("type");
if (!string.IsNullOrEmpty(typeAttribute?.Value) && typeAttribute.Value.StartsWith("image"))
{
var urlAttribute = element.Attribute("url");
feedDataImage = (!string.IsNullOrEmpty(urlAttribute?.Value)) ?
urlAttribute.Value : string.Empty;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
return feedDataImage;
}
/// <summary>
/// Tries to parse the original string to a datetime format.
/// </summary>
/// <param name="s">Input string.</param>
/// <param name="result">Parsed datetime.</param>
/// <returns>True if success</returns>
public static bool TryParseDateTime(string s, out DateTime result)
{
if (DateTime.TryParse(s, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowWhiteSpaces, out result))
{
return true;
}
int tzIndex = s.LastIndexOf(" ");
if (tzIndex >= 0)
{
string tz = s.Substring(tzIndex, s.Length - tzIndex);
string offset = TimeZoneToOffset(tz);
if (offset != null)
{
string offsetDate = string.Format("{0} {1}", s.Substring(0, tzIndex), offset);
return TryParseDateTime(offsetDate, out result);
}
}
result = default(DateTime);
return false;
}
/// <summary>
/// Calculate and return timezone.
/// </summary>
/// <param name="tz">Input string.</param>
/// <returns>Parsed timezone.</returns>
public static string TimeZoneToOffset(string tz)
{
if (tz == null)
{
return null;
}
tz = tz.ToUpper().Trim();
if (TimeZones.ContainsKey(tz))
{
return TimeZones[tz].First();
}
return null;
}
/// <summary>
/// Retrieve images from HTML string.
/// </summary>
/// <param name="htmlString">String of HTML.</param>
/// <returns>List of images.</returns>
private static IEnumerable<string> GetImagesInHTMLString(string htmlString)
{
var images = new List<string>();
foreach (Match match in RegexImages.Matches(htmlString))
{
bool include = true;
string tag = match.Value;
// Ignores images with low size
var matchHeight = RegexHeight.Match(tag);
if (matchHeight.Success)
{
var heightValue = matchHeight.Groups["height"].Value;
if (int.TryParse(heightValue, out var heightIntValue) && heightIntValue < 10)
{
include = false;
}
}
var matchWidth = RegexWidth.Match(tag);
if (matchWidth.Success)
{
var widthValue = matchWidth.Groups["width"].Value;
if (int.TryParse(widthValue, out var widthIntValue) && widthIntValue < 10)
{
include = false;
}
}
if (include)
{
images.Add(match.Groups[1].Value);
}
}
foreach (Match match in RegexLinks.Matches(htmlString))
{
var value = match.Groups[1].Value;
if (value.Contains(".jpg") || value.Contains(".png"))
{
images.Add(value);
}
}
return images;
}
/// <summary>
/// Dictionary of timezones.
/// </summary>
private static readonly Dictionary<string, string[]> TimeZones = new Dictionary<string, string[]>
{
{ "ACDT", new[] { "-1030", "Australian Central Daylight" } },
{ "ACST", new[] { "-0930", "Australian Central Standard" } },
{ "ADT", new[] { "+0300", "(US) Atlantic Daylight" } },
{ "AEDT", new[] { "-1100", "Australian East Daylight" } },
{ "AEST", new[] { "-1000", "Australian East Standard" } },
{ "AHDT", new[] { "+0900", string.Empty } },
{ "AHST", new[] { "+1000", string.Empty } },
{ "AST", new[] { "+0400", "(US) Atlantic Standard" } },
{ "AT", new[] { "+0200", "Azores" } },
{ "AWDT", new[] { "-0900", "Australian West Daylight" } },
{ "AWST", new[] { "-0800", "Australian West Standard" } },
{ "BAT", new[] { "-0300", "Baghdad" } },
{ "BDST", new[] { "-0200", "British Double Summer" } },
{ "BET", new[] { "+1100", "Bering Standard" } },
{ "BST", new[] { "+0300", "Brazil Standard" } },
{ "BT", new[] { "-0300", "Baghdad" } },
{ "BZT2", new[] { "+0300", "Brazil Zone 2" } },
{ "CADT", new[] { "-1030", "Central Australian Daylight" } },
{ "CAST", new[] { "-0930", "Central Australian Standard" } },
{ "CAT", new[] { "+1000", "Central Alaska" } },
{ "CCT", new[] { "-0800", "China Coast" } },
{ "CDT", new[] { "+0500", "(US) Central Daylight" } },
{ "CED", new[] { "-0200", "Central European Daylight" } },
{ "CET", new[] { "-0100", "Central European" } },
{ "CST", new[] { "+0600", "(US) Central Standard" } },
{ "EAST", new[] { "-1000", "Eastern Australian Standard" } },
{ "EDT", new[] { "+0400", "(US) Eastern Daylight" } },
{ "EED", new[] { "-0300", "Eastern European Daylight" } },
{ "EET", new[] { "-0200", "Eastern Europe" } },
{ "EEST", new[] { "-0300", "Eastern Europe Summer" } },
{ "EST", new[] { "+0500", "(US) Eastern Standard" } },
{ "FST", new[] { "-0200", "French Summer" } },
{ "FWT", new[] { "-0100", "French Winter" } },
{ "GMT", new[] { "+0000", "Greenwich Mean" } },
{ "GST", new[] { "-1000", "Guam Standard" } },
{ "HDT", new[] { "+0900", "Hawaii Daylight" } },
{ "HST", new[] { "+1000", "Hawaii Standard" } },
{ "IDLE", new[] { "-1200", "International Date Line East" } },
{ "IDLW", new[] { "+1200", "International Date Line West" } },
{ "IST", new[] { "-0530", "Indian Standard" } },
{ "IT", new[] { "-0330", "Iran" } },
{ "JST", new[] { "-0900", "Japan Standard" } },
{ "JT", new[] { "-0700", "Java" } },
{ "MDT", new[] { "+0600", "(US) Mountain Daylight" } },
{ "MED", new[] { "-0200", "Middle European Daylight" } },
{ "MET", new[] { "-0100", "Middle European" } },
{ "MEST", new[] { "-0200", "Middle European Summer" } },
{ "MEWT", new[] { "-0100", "Middle European Winter" } },
{ "MST", new[] { "+0700", "(US) Mountain Standard" } },
{ "MT", new[] { "-0800", "Moluccas" } },
{ "NDT", new[] { "+0230", "Newfoundland Daylight" } },
{ "NFT", new[] { "+0330", "Newfoundland" } },
{ "NT", new[] { "+1100", "Nome" } },
{ "NST", new[] { "-0630", "North Sumatra" } },
{ "NZ", new[] { "-1100", "New Zealand " } },
{ "NZST", new[] { "-1200", "New Zealand Standard" } },
{ "NZDT", new[] { "-1300", "New Zealand Daylight" } },
{ "NZT", new[] { "-1200", "New Zealand" } },
{ "PDT", new[] { "+0700", "(US) Pacific Daylight" } },
{ "PST", new[] { "+0800", "(US) Pacific Standard" } },
{ "ROK", new[] { "-0900", "Republic of Korea" } },
{ "SAD", new[] { "-1000", "South Australia Daylight" } },
{ "SAST", new[] { "-0900", "South Australia Standard" } },
{ "SAT", new[] { "-0900", "South Australia Standard" } },
{ "SDT", new[] { "-1000", "South Australia Daylight" } },
{ "SST", new[] { "-0200", "Swedish Summer" } },
{ "SWT", new[] { "-0100", "Swedish Winter" } },
{ "USZ3", new[] { "-0400", "Volga Time (Russia)" } },
{ "USZ4", new[] { "-0500", "Ural Time (Russia)" } },
{ "USZ5", new[] { "-0600", "West-Siberian Time (Russia) " } },
{ "USZ6", new[] { "-0700", "Yenisei Time (Russia)" } },
{ "UT", new[] { "+0000", "Universal Coordinated" } },
{ "UTC", new[] { "+0000", "Universal Coordinated" } },
{ "UZ10", new[] { "-1100", "Okhotsk Time (Russia)" } },
{ "WAT", new[] { "+0100", "West Africa" } },
{ "WET", new[] { "+0000", "West European" } },
{ "WST", new[] { "-0800", "West Australian Standard" } },
{ "YDT", new[] { "+0800", "Yukon Daylight" } },
{ "YST", new[] { "+0900", "Yukon Standard" } }
};
}
}

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

@ -1,43 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Xml.Linq;
namespace Microsoft.Toolkit.Parsers.Rss
{
/// <summary>
/// The RSS Parser allows you to parse an RSS content String into RSS Schema.
/// </summary>
public class RssParser : IParser<RssSchema>
{
/// <summary>
/// Parse an RSS content string into RSS Schema.
/// </summary>
/// <param name="data">Input string.</param>
/// <returns>Strong type.</returns>
public IEnumerable<RssSchema> Parse(string data)
{
if (string.IsNullOrEmpty(data))
{
return null;
}
var doc = XDocument.Parse(data);
var type = BaseRssParser.GetFeedType(doc);
BaseRssParser rssParser;
if (type == RssType.Rss)
{
rssParser = new Rss2Parser();
}
else
{
rssParser = new AtomParser();
}
return rssParser.LoadFeed(doc);
}
}
}

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

@ -1,65 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Parsers.Rss
{
/// <summary>
/// Implementation of the RssSchema class.
/// </summary>
public class RssSchema : SchemaBase
{
/// <summary>
/// Gets or sets title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets summary.
/// </summary>
public string Summary { get; set; }
/// <summary>
/// Gets or sets content.
/// </summary>
public string Content { get; set; }
/// <summary>
/// Gets or sets image Url.
/// </summary>
public string ImageUrl { get; set; }
/// <summary>
/// Gets or sets extra Image Url.
/// </summary>
public string ExtraImageUrl { get; set; }
/// <summary>
/// Gets or sets media Url.
/// </summary>
public string MediaUrl { get; set; }
/// <summary>
/// Gets or sets feed Url.
/// </summary>
public string FeedUrl { get; set; }
/// <summary>
/// Gets or sets author.
/// </summary>
public string Author { get; set; }
/// <summary>
/// Gets or sets publish Date.
/// </summary>
public DateTime PublishDate { get; set; }
/// <summary>
/// Gets or sets item's categories.
/// </summary>
public IEnumerable<string> Categories { get; set; }
}
}

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

@ -5,9 +5,6 @@
<Title>Windows Community Toolkit .NET Standard Services</Title>
<Description>
This .NET standard library enables access to different data sources such as Microsoft Graph, OneDrive, Twitter, Microsoft Translator, and LinkedIn. It is part of the Windows Community Toolkit.
Namespace:
- Facebook: Album, DataConfig, DataHost, OAuthTokens, Permissions, Photo, Picture, PictureData, PlatformImageSource, Post, RequestSource, Service.
</Description>
<PackageTags>UWP Community Toolkit Windows Microsoft Graph OneDrive Twitter Translator LinkedIn service login OAuth</PackageTags>

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

@ -154,17 +154,6 @@ namespace Microsoft.Toolkit.Services.LinkedIn
return false;
}
/// <summary>
/// Log user out of LinkedIn.
/// </summary>
[Obsolete("Logout is deprecated, please use LogoutAsync instead.", true)]
public void Logout()
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
LogoutAsync();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
/// <summary>
/// Log user out of LinkedIn.
/// </summary>

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

@ -92,15 +92,6 @@ namespace Microsoft.Toolkit.Services.LinkedIn
return Provider.ShareDataAsync<LinkedInShareRequest, LinkedInShareResponse>(shareRequest);
}
/// <summary>
/// Log user out of LinkedIn.
/// </summary>
[Obsolete("Logout is deprecated, please use LogoutAsync instead.", true)]
public void Logout()
{
Provider.Logout();
}
/// <summary>
/// Log user out of LinkedIn.
/// </summary>

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

@ -273,17 +273,6 @@ namespace Microsoft.Toolkit.Services.Twitter
return false;
}
/// <summary>
/// Log user out of Twitter.
/// </summary>
[Obsolete("Logout is deprecated, please use LogoutAsync instead.", true)]
public void Logout()
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
LogoutAsync();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
/// <summary>
/// Log user out of Twitter.
/// </summary>

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

@ -400,15 +400,6 @@ namespace Microsoft.Toolkit.Services.Twitter
return Provider.LoginAsync();
}
/// <summary>
/// Log user out of Twitter.
/// </summary>
[Obsolete("Logout is deprecated, please use LogoutAsync instead.", true)]
public void Logout()
{
Provider.Logout();
}
/// <summary>
/// Log user out of Twitter.
/// </summary>

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

@ -163,17 +163,6 @@ namespace Microsoft.Toolkit.Services.Weibo
return false;
}
/// <summary>
/// Log user out of Weibo.
/// </summary>
[Obsolete("Logout is deprecated, please use LogoutAsync instead.", true)]
public void Logout()
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
LogoutAsync();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
/// <summary>
/// Log user out of Weibo.
/// </summary>

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

@ -183,15 +183,6 @@ namespace Microsoft.Toolkit.Services.Weibo
return Provider.LoginAsync();
}
/// <summary>
/// Log user out of Weibo.
/// </summary>
[Obsolete("Logout is deprecated, please use LogoutAsync instead.", true)]
public void Logout()
{
Provider.Logout();
}
/// <summary>
/// Log user out of Weibo.
/// </summary>

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

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>

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

@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" 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)' == '' ">AnyCPU</Platform>
<ProjectGuid>{292D34E8-0F01-4FA8-951D-8232F75A88D5}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>DifferencesGen</RootNamespace>
<AssemblyName>DifferencesGen</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\DifferencesGen.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json">
<Version>10.0.3</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="Pack">
<!-- No-op to avoid build error when packing solution from commandline -->
</Target>
</Project>

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

@ -1,256 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
namespace DifferencesGen
{
public class Program
{
private static HashSet<string> enumTypes = new HashSet<string>();
private static HashSet<string> typeEvents = new HashSet<string>();
public static void Main(string[] args)
{
string min = null;
string max = null;
foreach (var arg in args)
{
if (arg.StartsWith("/min:"))
{
min = arg.Replace("/min:", string.Empty);
}
else if (arg.StartsWith("/max:"))
{
max = arg.Replace("/max:", string.Empty);
}
}
Version.TryParse(min, out Version minVersion);
Version.TryParse(max, out Version maxVersion);
if (minVersion == null || maxVersion == null)
{
Console.WriteLine("The differences generator needs to be run as follows:");
Console.WriteLine("DifferencesGen /min:4.0.0.0 /max:5.0.0.0");
return;
}
string folderPath = @"C:\Program Files (x86)\Windows Kits\10\References";
string universalApiFile = "Windows.Foundation.UniversalApiContract.winmd";
string universalApiDifferencesCompressedFile = "Differences-{0}.gz";
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (sender, eventArgs) => Assembly.ReflectionOnlyLoad(eventArgs.Name);
WindowsRuntimeMetadata.ReflectionOnlyNamespaceResolve += (sender, eventArgs) =>
{
string path =
WindowsRuntimeMetadata.ResolveNamespace(eventArgs.NamespaceName, Enumerable.Empty<string>())
.FirstOrDefault();
if (path == null)
{
return;
}
eventArgs.ResolvedAssemblies.Add(Assembly.ReflectionOnlyLoadFrom(path));
};
DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
FileInfo[] files = directoryInfo.GetFiles(universalApiFile, SearchOption.AllDirectories);
List<Tuple<Version, Assembly>> assemblyList = new List<Tuple<Version, Assembly>>();
if (files.Length > 0)
{
foreach (var file in files)
{
var assembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);
var nameParts = assembly.FullName.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries);
var versionParts = nameParts[1].Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
var version = Version.Parse(versionParts[1]);
if (version >= minVersion && version <= maxVersion)
{
assemblyList.Add(new Tuple<Version, Assembly>(version, assembly));
}
}
}
if (assemblyList.Count >= 2)
{
var orderedList = assemblyList.OrderBy(t => t.Item1).ToList();
for (int i = 1; i < orderedList.Count; i++)
{
var previousVersionAssembly = orderedList[i - 1].Item2;
var newerVersionAssembly = orderedList[i].Item2;
var version = orderedList[i].Item1;
var previousVersionTypes = ProcessAssembly(previousVersionAssembly);
var newerVersionTypes = ProcessAssembly(newerVersionAssembly);
var addedTypes = new Dictionary<string, List<string>>();
foreach (var type in newerVersionTypes)
{
if (!previousVersionTypes.ContainsKey(type.Key))
{
addedTypes.Add(type.Key, null);
if (enumTypes.Contains(type.Key))
{
System.Diagnostics.Debug.WriteLine($"New enum {type.Key}");
}
continue;
}
HashSet<string> previousVersionTypeMembers = new HashSet<string>(previousVersionTypes[type.Key]);
HashSet<string> newerVersionTypeMembers = new HashSet<string>(type.Value);
newerVersionTypeMembers.ExceptWith(previousVersionTypeMembers);
if (newerVersionTypeMembers.Count == 0)
{
continue;
}
if (enumTypes.Contains(type.Key))
{
System.Diagnostics.Debug.WriteLine($"Enum {type.Key} has new members: {string.Join(",", newerVersionTypeMembers)}");
}
foreach (var member in newerVersionTypeMembers)
{
if (typeEvents.Contains($"{type.Key}-{member}"))
{
System.Diagnostics.Debug.WriteLine($"Type {type.Key} has new event: {member}");
}
}
addedTypes.Add(type.Key, newerVersionTypeMembers.ToList());
}
StringBuilder stringBuilder = new StringBuilder();
using (var compressedFS = File.Create(Path.Combine(AssemblyDirectory, string.Format(universalApiDifferencesCompressedFile, version.ToString()))))
{
using (var compressionFS = new GZipStream(compressedFS, CompressionMode.Compress))
{
using (var writer = new StreamWriter(compressionFS))
{
foreach (var addedType in addedTypes)
{
stringBuilder.Clear();
stringBuilder.Append(addedType.Key);
if (addedType.Value != null && addedType.Value.Count > 0)
{
stringBuilder.Append(':');
stringBuilder.Append(string.Join(",", addedType.Value));
}
writer.WriteLine(stringBuilder.ToString());
}
}
}
}
stringBuilder.Length = 0;
}
}
}
public static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
private static Dictionary<string, List<string>> ProcessAssembly(Assembly assembly)
{
var types = new Dictionary<string, List<string>>();
foreach (var exportedType in assembly.ExportedTypes)
{
var members = new List<string>();
if (exportedType.IsEnum)
{
if (!enumTypes.Contains(exportedType.FullName))
{
enumTypes.Add(exportedType.FullName);
}
foreach (var member in exportedType.GetFields())
{
if (member.Name.Equals("value__"))
{
continue;
}
members.Add(member.Name);
}
}
else
{
foreach (var methodInfo in exportedType.GetMethods())
{
if (!methodInfo.IsPublic)
{
continue;
}
if (methodInfo.Name.StartsWith("get_") ||
methodInfo.Name.StartsWith("set_") ||
methodInfo.Name.StartsWith("put_") ||
methodInfo.Name.StartsWith("add_") ||
methodInfo.Name.StartsWith("remove_"))
{
continue;
}
members.Add($"{methodInfo.Name}#{methodInfo.GetParameters().Length}");
}
foreach (var propertyInfo in exportedType.GetProperties())
{
members.Add(propertyInfo.Name);
}
foreach (var eventInfo in exportedType.GetEvents())
{
typeEvents.Add($"{exportedType.FullName}-{eventInfo.Name}");
members.Add(eventInfo.Name);
}
}
types.Add(exportedType.FullName, members);
}
return types;
}
}
}

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

@ -1,357 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// This class offers loads platform differences for use by Code Analyzer and Code Fixer.
/// </summary>
public static class Analyzer
{
internal enum TypePresenceIndicator
{
New,
Changes,
NotFound,
}
private static Dictionary<string, Dictionary<string, List<NewMember>>> _differencesDictionary = null;
/// <summary>
/// Embedded differences between API contract version 4 and 5.
/// </summary>
public const string N1DifferencesRes = "Differences-5.0.0.0.gz";
/// <summary>
/// Embedded differences between API contract version 5 and 6.
/// </summary>
public const string N0DifferencesRes = "Differences-6.0.0.0.gz";
/// <summary>
/// Earliest supported SDK version.
/// </summary>
public const string N2SDKVersion = "15063";
/// <summary>
/// Intermediate SDK version.
/// </summary>
public const string N1SDKVersion = "16299";
/// <summary>
/// Latest SDK version.
/// </summary>
public const string N0SDKVersion = "17134";
/// <summary>
/// Platform related diagnostic descriptor
/// </summary>
public static readonly DiagnosticDescriptor PlatformRule = new DiagnosticDescriptor("UWP001", "Platform-specific", "Platform-specific code detected. Consider using ApiInformation.IsTypePresent to guard against failure", "Safety", DiagnosticSeverity.Warning, true);
/// <summary>
/// Version related diagnostic descriptor
/// </summary>
public static readonly DiagnosticDescriptor VersionRule = new DiagnosticDescriptor("UWP002", "Version-specific", "Version-specific code detected. Consider using ApiInformation.IsTypePresent / ApiInformation.IsMethodPresent / ApiInformation.IsPropertyPresent to guard against failure", "Safety", DiagnosticSeverity.Warning, true);
private static char[] typeMemberSeparator = { ':' };
private static char[] memberSeparator = { ',' };
static Analyzer()
{
_differencesDictionary = new Dictionary<string, Dictionary<string, List<NewMember>>>();
_differencesDictionary.Add(N0DifferencesRes, GetApiAdditions(N0DifferencesRes));
_differencesDictionary.Add(N1DifferencesRes, GetApiAdditions(N1DifferencesRes));
}
/// <summary>
/// Gets the API differences from specified resource.
/// </summary>
/// <param name="resourceName">name of embedded resource</param>
/// <returns>Dictionary with Fully qualified name of type as key and list of new members as value</returns>
public static Dictionary<string, List<NewMember>> GetUniversalApiAdditions(string resourceName)
{
return _differencesDictionary[resourceName];
}
private static Dictionary<string, List<NewMember>> GetApiAdditions(string resourceName)
{
Dictionary<string, List<NewMember>> apiAdditionsDictionary = new Dictionary<string, List<NewMember>>();
Assembly assembly = typeof(Analyzer).GetTypeInfo().Assembly;
var resource = assembly.GetManifestResourceStream("Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer." + resourceName);
if (resource == null)
{
System.Diagnostics.Debug.WriteLine($"Resource {resourceName} not found.");
return new Dictionary<string, List<NewMember>>();
}
System.Diagnostics.Debug.WriteLine($"Resource {resourceName} found.");
Dictionary<string, List<string>> differencesDictionary = new Dictionary<string, List<string>>();
using (GZipStream decompressionStream = new GZipStream(resource, CompressionMode.Decompress))
{
using (StreamReader reader = new StreamReader(decompressionStream))
{
while (!reader.EndOfStream)
{
var typeDetails = reader.ReadLine();
var typeMemberParts = typeDetails.Split(typeMemberSeparator, StringSplitOptions.RemoveEmptyEntries);
if (typeMemberParts.Length == 1)
{
differencesDictionary.Add(typeMemberParts[0], null);
continue;
}
var membersAddedToType = typeMemberParts[1].Split(memberSeparator, StringSplitOptions.RemoveEmptyEntries);
differencesDictionary.Add(typeMemberParts[0], new List<string>(membersAddedToType));
}
}
}
if (differencesDictionary == null)
{
return apiAdditionsDictionary;
}
foreach (var kvp in differencesDictionary)
{
var list = new List<NewMember>();
if (kvp.Value != null)
{
list.AddRange(kvp.Value.Select(v => new NewMember(v)));
}
apiAdditionsDictionary.Add(kvp.Key, list);
}
return apiAdditionsDictionary;
}
/// <summary>
/// This function tells which version/platform the symbol is from.
/// </summary>
/// <param name="symbol">represents a compiler <see cref="ISymbol"/></param>
/// <returns>instance of <see cref="Platform"/></returns>
public static Platform GetPlatformForSymbol(ISymbol symbol)
{
if (symbol == null)
{
return new Platform(PlatformKind.Unchecked);
}
if (symbol.ContainingNamespace != null && symbol.ContainingNamespace.ToDisplayString().StartsWith("Windows."))
{
var assembly = symbol.ContainingAssembly.Name;
var version = symbol.ContainingAssembly.Identity.Version.Major;
// Any call to ApiInformation.* is allowed without warning
if (symbol.ContainingType?.Name == "ApiInformation")
{
return new Platform(PlatformKind.Uwp, Analyzer.N2SDKVersion);
}
// Don't want to give warning when analyzing code in an PCL project.
// In those two targets, every Windows type is found in Windows.winmd, so that's how we'll suppress it:
if (assembly == "Windows")
{
return new Platform(PlatformKind.Unchecked);
}
// Some WinRT types like Windows.UI.Color get projected to come from .NET assemblies, always present:
if (assembly.StartsWith("System.Runtime."))
{
return new Platform(PlatformKind.Uwp, Analyzer.N2SDKVersion);
}
// Some things are emphatically part of UWP.10240
if (assembly == "Windows.Foundation.FoundationContract" || (assembly == "Windows.Foundation.UniversalApiContract" && version == 1))
{
return new Platform(PlatformKind.Uwp, Analyzer.N2SDKVersion);
}
if (assembly == "Windows.Foundation.UniversalApiContract")
{
var isType = symbol.Kind == SymbolKind.NamedType;
var typeName = isType ? symbol.ToDisplayString() : symbol.ContainingType.ToDisplayString();
TypePresenceIndicator presentInN0ApiDiff = CheckCollectionForType(Analyzer.GetUniversalApiAdditions(Analyzer.N0DifferencesRes), typeName, symbol);
if (presentInN0ApiDiff == TypePresenceIndicator.New)
{
// the entire type was found in Target Version
return new Platform(PlatformKind.Uwp, Analyzer.N0SDKVersion);
}
else if (presentInN0ApiDiff == TypePresenceIndicator.Changes)
{
// the entire type was found in Target Version with matching parameter lengths
return new Platform(PlatformKind.Uwp, Analyzer.N0SDKVersion, true);
}
else
{
TypePresenceIndicator presentInN1ApiDiff = CheckCollectionForType(Analyzer.GetUniversalApiAdditions(Analyzer.N1DifferencesRes), typeName, symbol);
if (presentInN1ApiDiff == TypePresenceIndicator.New)
{
// the entire type was found in Target Version
return new Platform(PlatformKind.Uwp, Analyzer.N1SDKVersion);
}
else if (presentInN1ApiDiff == TypePresenceIndicator.Changes)
{
// the entire type was found in Target Version with matching parameter lengths
return new Platform(PlatformKind.Uwp, Analyzer.N1SDKVersion, true);
}
else
{
// the type was in Min version
return new Platform(PlatformKind.Uwp, Analyzer.N2SDKVersion);
}
}
}
// All other Windows.* types come from platform-specific extensions
return new Platform(PlatformKind.ExtensionSDK);
}
else
{
return new Platform(PlatformKind.Unchecked);
}
}
/// <summary>
/// returns instance of <see cref="HowToGuard"/> for <see cref="ISymbol"/>
/// </summary>
/// <param name="target">instance of <see cref="ISymbol"/></param>
/// <returns>instance of <see cref="HowToGuard"/></returns>
public static HowToGuard GetGuardForSymbol(ISymbol target)
{
var plat = Analyzer.GetPlatformForSymbol(target);
switch (plat.Kind)
{
case PlatformKind.ExtensionSDK:
return new HowToGuard()
{
TypeToCheck = target.Kind == SymbolKind.NamedType ? target.ToDisplayString() : target.ContainingType.ToDisplayString(),
KindOfCheck = "IsTypePresent"
};
case PlatformKind.Uwp:
if (target.Kind == SymbolKind.NamedType)
{
return new HowToGuard()
{
TypeToCheck = target.ToDisplayString(),
KindOfCheck = "IsTypePresent"
};
}
else
{
var g = new HowToGuard
{
TypeToCheck = target.ContainingType.ToDisplayString()
};
var d0 = Analyzer.GetUniversalApiAdditions(Analyzer.N0DifferencesRes);
var d1 = Analyzer.GetUniversalApiAdditions(Analyzer.N1DifferencesRes);
if (!d0.TryGetValue(g.TypeToCheck, out List<NewMember> newMembers))
{
d1.TryGetValue(g.TypeToCheck, out newMembers);
}
if (newMembers == null)
{
throw new InvalidOperationException("oops! expected this UWP version API to be in the dictionary of new things");
}
g.MemberToCheck = target.Name;
if (target.Kind == SymbolKind.Field)
{
// the only fields in WinRT are enum fields
g.KindOfCheck = "IsEnumNamedValuePresent";
}
else if (target.Kind == SymbolKind.Event)
{
g.KindOfCheck = "IsEventPresent";
}
else if (target.Kind == SymbolKind.Property)
{
// TODO: if SDK starts introducing additional accessors on properties, we'll have to change this
g.KindOfCheck = "IsPropertyPresent";
}
else if (target.Kind == SymbolKind.Method)
{
g.KindOfCheck = "IsMethodPresent";
if (target.Kind == SymbolKind.Method && plat.ByParameterCount)
{
g.ParameterCountToCheck = (target as IMethodSymbol).Parameters.Length;
}
}
return g;
}
default:
throw new InvalidOperationException("oops! don't know why I was asked to check something that's fine");
}
}
private static TypePresenceIndicator CheckCollectionForType(Dictionary<string, List<NewMember>> collection, string typeName, ISymbol symbol)
{
if (!collection.TryGetValue(typeName, out var newMembers))
{
return TypePresenceIndicator.NotFound;
}
if (newMembers == null || newMembers.Count == 0)
{
return TypePresenceIndicator.New;
}
if (symbol.Kind == SymbolKind.NamedType)
{
return TypePresenceIndicator.NotFound;
}
var memberName = symbol.Name;
foreach (var newMember in newMembers)
{
if (memberName == newMember.Name && !newMember.ParameterCount.HasValue)
{
return TypePresenceIndicator.New;
}
// this member was new in collection
if (symbol.Kind != SymbolKind.Method)
{
// TODO: Continue For... Warning!!! not translated
}
if (memberName == newMember.Name && ((IMethodSymbol)symbol).Parameters.Length == newMember.ParameterCount)
{
return TypePresenceIndicator.Changes;
}
}
// this member existed in a different collection
return TypePresenceIndicator.NotFound;
}
}
}

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

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

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

@ -1,32 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// The struct provides guard related info.
/// </summary>
public struct HowToGuard
{
/// <summary>
/// Type being checked
/// </summary>
public string TypeToCheck;
/// <summary>
/// Member being checked
/// </summary>
public string MemberToCheck;
/// <summary>
/// Whether parameter count will be used for the check
/// </summary>
public int? ParameterCountToCheck;
/// <summary>
/// Type of check
/// </summary>
public string KindOfCheck;
}
}

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

@ -1,36 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Title>Windows Community Toolkit UWP Platform Specific Analyzer</Title>
<Description>This standard library provides code analysis and code fixers (on CS and VB) to ensure that version / platform specific code is well guarded.</Description>
<PackageTags>UWP Toolkit Windows Platform Specific Analyzer</PackageTags>
<IncludeBuildOutput>false</IncludeBuildOutput>
</PropertyGroup>
<ItemGroup>
<None Remove="Differences-6.0.0.0.gz" />
<None Remove="Differences-7.0.0.0.gz" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Differences-6.0.0.0.gz" />
<EmbeddedResource Include="Differences-7.0.0.0.gz" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="NETStandard.Library" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<None Update="tools\*.ps1" CopyToOutputDirectory="Always" Pack="true" PackagePath="" />
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/vb" Visible="false" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.8.2" PrivateAssets="All" />
</ItemGroup>
</Project>

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

@ -1,46 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// This class wraps a new data members
/// </summary>
public struct NewMember
{
private static char[] methodCountSeparator = { '#' };
/// <summary>
/// Member name
/// </summary>
public string Name;
/// <summary>
/// Parameter count (if its a method)
/// </summary>
public int? ParameterCount;
/// <summary>
/// Initializes a new instance of the <see cref="NewMember"/> struct.
/// </summary>
/// <param name="s">data containing name and optionally parameter count</param>
public NewMember(string s)
{
string[] parts = s.Split(methodCountSeparator, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 2)
{
Name = parts[0];
ParameterCount = int.Parse(parts[1]);
}
else
{
Name = s;
ParameterCount = null;
}
}
}
}

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

@ -1,69 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// Simple struct to hold platform / version / param count info for given symbol
/// </summary>
public struct Platform
{
/// <summary>
/// Platform Kind
/// </summary>
public PlatformKind Kind;
/// <summary>
/// For UWP, this is version 15063 or 16299etc. For User, the fully qualified name of the attribute in use
/// </summary>
public string Version;
/// <summary>
/// For UWP only
/// </summary>
public bool ByParameterCount;
/// <summary>
/// Initializes a new instance of the <see cref="Platform"/> struct.
/// </summary>
/// <param name="kind"><see cref="PlatformKind"/></param>
/// <param name="version">version</param>
/// <param name="byParameterCount">boolean</param>
public Platform(PlatformKind kind, string version = null, bool byParameterCount = false)
{
Kind = kind;
Version = version;
ByParameterCount = byParameterCount;
switch (kind)
{
case PlatformKind.Unchecked:
if (version != null)
{
throw new ArgumentException("No version expected");
}
break;
case PlatformKind.Uwp:
break;
case PlatformKind.ExtensionSDK:
if (version != null)
{
throw new ArgumentException("Don't specify versions for extension SDKs");
}
break;
}
if (byParameterCount && kind != PlatformKind.Uwp)
{
throw new ArgumentException("Only UWP can be distinguished by parameter count");
}
}
}
}

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

@ -1,27 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// Platform kind enum
/// </summary>
public enum PlatformKind
{
/// <summary>
/// .NET and Pre-UWP WinRT
/// </summary>
Unchecked,
/// <summary>
/// Core UWP platform
/// </summary>
Uwp,
/// <summary>
/// Desktop, Mobile, IOT, Xbox extension SDK
/// </summary>
ExtensionSDK
}
}

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

@ -1,230 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// This class is a Roslyn code analyzer that checks for types / members that should be guarded against.
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class PlatformSpecificAnalyzerCS : DiagnosticAnalyzer
{
/// <summary>
/// Gets supported diagnostics
/// </summary>
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(Analyzer.PlatformRule, Analyzer.VersionRule); }
}
/// <summary>
/// Gets instance of symbol from syntax node
/// </summary>
/// <param name="node">instance of <see cref="SyntaxNode"/></param>
/// <param name="semanticModel"><see cref="SemanticModel"/></param>
/// <returns><see cref="ISymbol"/></returns>
public static ISymbol GetTargetOfNode(SyntaxNode node, SemanticModel semanticModel)
{
var parentKind = node.Parent.Kind();
if (parentKind == SyntaxKind.InvocationExpression && node == ((InvocationExpressionSyntax)node.Parent).Expression)
{
// <target>(...)
// points to the method after overload resolution
return semanticModel.GetSymbolInfo((InvocationExpressionSyntax)node.Parent).Symbol;
}
else if (parentKind == SyntaxKind.ObjectCreationExpression && node == ((ObjectCreationExpressionSyntax)node.Parent).Type)
{
// New <target>
var objectCreationExpression = (ObjectCreationExpressionSyntax)node.Parent;
var target = semanticModel.GetSymbolInfo(objectCreationExpression).Symbol;
// points to the constructor after overload resolution
return target;
}
else
{
// f<target>(...)
// <target> x = ...
// Action x = <target> -- note that following code does pick the right overload
// <target> += delegate -- the following code does recognize events
// nameof(<target>) -- I think it's nicer to report on this, even if not technically needed
// Field access? I'll disallow it for enum values, and allow it for everything else
var target = semanticModel.GetSymbolInfo(node).Symbol;
if (target == null)
{
return null;
}
var targetKind = target.Kind;
if (targetKind == SymbolKind.Method || targetKind == SymbolKind.Event || targetKind == SymbolKind.Property || targetKind == SymbolKind.NamedType)
{
return target;
}
if (targetKind == SymbolKind.Field && target.ContainingType.TypeKind == TypeKind.Enum)
{
return target;
}
return null;
}
}
/// <summary>
/// Initializes the analyzer, registering for code analysis.
/// </summary>
/// <param name="context"><see cref="AnalysisContext"/></param>
public override void Initialize(AnalysisContext context)
{
ConcurrentDictionary<int, Diagnostic> reportsDictionary = new ConcurrentDictionary<int, Diagnostic>();
context.RegisterSyntaxNodeAction((c) => AnalyzeExpression(c, reportsDictionary), SyntaxKind.VariableDeclaration, SyntaxKind.FieldDeclaration, SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.QualifiedName);
}
private static IEnumerable<ISymbol> GetGuards(SyntaxNode node, SemanticModel semanticModel)
{
foreach (var condition in GetConditions(node))
{
// First check for invocations of ApiInformation.IsTypePresent
foreach (var invocation in condition.DescendantNodesAndSelf(i => i is InvocationExpressionSyntax))
{
var targetMethod = semanticModel.GetSymbolInfo(invocation).Symbol;
if (targetMethod?.ContainingType?.Name == "ApiInformation")
{
yield return targetMethod;
}
}
// Next check for any property/field access
var accesses1 = condition.DescendantNodesAndSelf(d => d is MemberAccessExpressionSyntax).Select(n => semanticModel.GetSymbolInfo(n).Symbol);
var accesses2 = condition.DescendantNodesAndSelf(d => d is IdentifierNameSyntax).Select(n => semanticModel.GetSymbolInfo(n).Symbol);
foreach (var symbol in accesses1.Concat(accesses2))
{
var symbolKind = symbol.Kind;
if (symbolKind == SymbolKind.Field || symbolKind == SymbolKind.Property)
{
yield return symbol;
}
}
}
}
private static IEnumerable<ExpressionSyntax> GetConditions(SyntaxNode node)
{
var check = node.FirstAncestorOrSelf<IfStatementSyntax>();
while (check != null)
{
yield return check.Condition;
check = check.Parent.FirstAncestorOrSelf<IfStatementSyntax>();
}
}
private void AnalyzeExpression(SyntaxNodeAnalysisContext context, ConcurrentDictionary<int, Diagnostic> reports)
{
var parentKind = context.Node.Parent.Kind();
// will be handled at higher level
if (parentKind == SyntaxKind.SimpleMemberAccessExpression || parentKind == SyntaxKind.QualifiedName)
{
return;
}
var target = GetTargetOfNode(context.Node, context.SemanticModel);
if (target == null)
{
return;
}
var platform = Analyzer.GetPlatformForSymbol(target);
// Some quick escapes
if (platform.Kind == PlatformKind.Unchecked)
{
return;
}
if (platform.Kind == PlatformKind.Uwp && platform.Version == Analyzer.N2SDKVersion)
{
return;
}
// Is this expression inside a method/constructor/property that claims to be specific?
var containingBlock = context.Node.FirstAncestorOrSelf<BlockSyntax>();
// for constructors and methods
MemberDeclarationSyntax containingMember = containingBlock?.FirstAncestorOrSelf<BaseMethodDeclarationSyntax>();
if (containingBlock == null || containingBlock?.Parent is AccessorDeclarationSyntax)
{
containingMember = context.Node.FirstAncestorOrSelf<PropertyDeclarationSyntax>();
}
// Is this invocation properly guarded? See readme.md for explanations.
if (IsProperlyGuarded(context.Node, context.SemanticModel))
{
return;
}
if (containingBlock != null)
{
foreach (var ret in containingBlock.DescendantNodes().OfType<ReturnStatementSyntax>())
{
if (IsProperlyGuarded(ret, context.SemanticModel))
{
return;
}
}
}
// We'll report only a single diagnostic per line, the first.
var loc = context.Node.GetLocation();
if (!loc.IsInSource)
{
return;
}
var line = loc.GetLineSpan().StartLinePosition.Line;
if (reports.TryGetValue(line, out var diagnostic) && diagnostic.Location.SourceSpan.Start <= loc.SourceSpan.Start)
{
return;
}
diagnostic = Diagnostic.Create(platform.Kind == PlatformKind.Uwp ? Analyzer.VersionRule : Analyzer.PlatformRule, loc);
reports[line] = diagnostic;
context.ReportDiagnostic(diagnostic);
}
private bool IsProperlyGuarded(SyntaxNode node, SemanticModel semanticModel)
{
foreach (var symbol in GetGuards(node, semanticModel))
{
if (symbol.ContainingType?.Name == "ApiInformation")
{
return true;
}
}
return false;
}
}
}

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

@ -1,254 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.CodeAnalysis.VisualBasic.Syntax;
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// This class is a Roslyn code analyzer that checks for types / members that should be guarded against.
/// </summary>
[DiagnosticAnalyzer(LanguageNames.VisualBasic)]
public class PlatformSpecificAnalyzerVB : DiagnosticAnalyzer
{
/// <summary>
/// Gets supported diagnostics
/// </summary>
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(Analyzer.PlatformRule, Analyzer.VersionRule); }
}
/// <summary>
/// Gets instance of symbol from syntax node
/// </summary>
/// <param name="node">instance of <see cref="SyntaxNode"/></param>
/// <param name="semanticModel"><see cref="SemanticModel"/></param>
/// <returns><see cref="ISymbol"/></returns>
public static ISymbol GetTargetOfNode(SyntaxNode node, SemanticModel semanticModel)
{
var parentKind = node.Parent.Kind();
if (parentKind == SyntaxKind.InvocationExpression && node == ((InvocationExpressionSyntax)node.Parent).Expression)
{
// <target>(...)
// points to the method after overload resolution
return semanticModel.GetSymbolInfo((InvocationExpressionSyntax)node.Parent).Symbol;
}
else if (parentKind == SyntaxKind.AddressOfExpression)
{
// AddressOf <target>
return semanticModel.GetSymbolInfo(node).Symbol; // points to the method after overload resolution
}
else if (parentKind == SyntaxKind.ObjectCreationExpression && node == ((ObjectCreationExpressionSyntax)node.Parent).Type)
{
// New <target>
var objectCreationExpression = (ObjectCreationExpressionSyntax)node.Parent;
var target = semanticModel.GetSymbolInfo(objectCreationExpression).Symbol;
// points to the constructor after overload resolution
return target;
}
else if (parentKind == SyntaxKind.AddHandlerStatement && node == ((AddRemoveHandlerStatementSyntax)node.Parent).EventExpression)
{
// AddHandler <target>, delegate
return semanticModel.GetSymbolInfo(node).Symbol; // points to the event
}
else if (parentKind == SyntaxKind.NameOfExpression)
{
// NameOf(<target>)
return null;
}
else
{
// f(Of <target>)(...) -- no warning
// Dim x As <target> = ... -- no warning
// property access -- warning
// field access -- only warning on enum fields
// method access without arguments -- warning
var target = semanticModel.GetSymbolInfo(node).Symbol;
if (target == null)
{
return null;
}
var targetKind = target.Kind;
if (targetKind == SymbolKind.Method || targetKind == SymbolKind.Property || targetKind == SymbolKind.NamedType)
{
return target;
}
if (targetKind == SymbolKind.Field && target.ContainingType.TypeKind == TypeKind.Enum)
{
return target;
}
return null;
}
}
/// <summary>
/// Initializes the analyzer, registering for code analysis.
/// </summary>
/// <param name="context"><see cref="AnalysisContext"/></param>
public override void Initialize(AnalysisContext context)
{
ConcurrentDictionary<int, Diagnostic> reportsDictionary = new ConcurrentDictionary<int, Diagnostic>();
context.RegisterSyntaxNodeAction((c) => AnalyzeExpression(c, reportsDictionary), SyntaxKind.LocalDeclarationStatement, SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.QualifiedName);
}
private static IEnumerable<ISymbol> GetGuards(SyntaxNode node, SemanticModel semanticModel)
{
foreach (var condition in GetConditions(node))
{
// First check for invocations of ApiInformation.IsTypePresent
foreach (var invocation in condition.DescendantNodesAndSelf(i => i is InvocationExpressionSyntax))
{
var targetMethod = semanticModel.GetSymbolInfo(invocation).Symbol;
if (targetMethod?.ContainingType?.Name == "ApiInformation")
{
yield return targetMethod;
}
}
// Next check for any property/field access
var accesses1 = condition.DescendantNodesAndSelf(d => d is MemberAccessExpressionSyntax).Select(n => semanticModel.GetSymbolInfo(n).Symbol);
var accesses2 = condition.DescendantNodesAndSelf(d => d is IdentifierNameSyntax).Select(n => semanticModel.GetSymbolInfo(n).Symbol);
foreach (var symbol in accesses1.Concat(accesses2))
{
if (symbol == null)
{
continue;
}
var symbolKind = symbol.Kind;
if (symbolKind == SymbolKind.Field || symbolKind == SymbolKind.Property)
{
yield return symbol;
}
}
}
}
private static IEnumerable<ExpressionSyntax> GetConditions(SyntaxNode node)
{
var check1 = node.FirstAncestorOrSelf<MultiLineIfBlockSyntax>();
while (check1 != null)
{
yield return check1.IfStatement.Condition;
check1 = check1.Parent.FirstAncestorOrSelf<MultiLineIfBlockSyntax>();
}
var check2 = node.FirstAncestorOrSelf<SingleLineIfStatementSyntax>();
while (check2 != null)
{
yield return check2.Condition;
check2 = check2.Parent.FirstAncestorOrSelf<SingleLineIfStatementSyntax>();
}
}
private void AnalyzeExpression(SyntaxNodeAnalysisContext context, ConcurrentDictionary<int, Diagnostic> reports)
{
var parentKind = context.Node.Parent.Kind();
// will be handled at higher level
if (parentKind == SyntaxKind.SimpleMemberAccessExpression || parentKind == SyntaxKind.QualifiedName)
{
return;
}
var target = GetTargetOfNode(context.Node, context.SemanticModel);
if (target == null)
{
return;
}
var platform = Analyzer.GetPlatformForSymbol(target);
// Some quick escapes
if (platform.Kind == PlatformKind.Unchecked)
{
return;
}
if (platform.Kind == PlatformKind.Uwp && platform.Version == Analyzer.N2SDKVersion)
{
return;
}
// Is this expression inside a method/constructor/property that claims to be specific?
DeclarationStatementSyntax containingMember = context.Node.FirstAncestorOrSelf<MethodBlockBaseSyntax>();
if (containingMember is AccessorBlockSyntax)
{
containingMember = containingMember.FirstAncestorOrSelf<PropertyBlockSyntax>();
}
// Is this invocation properly guarded? See readme.md for explanations.
if (IsProperlyGuarded(context.Node, context.SemanticModel))
{
return;
}
if (containingMember != null)
{
foreach (var ret in containingMember.DescendantNodes().OfType<ReturnStatementSyntax>())
{
if (IsProperlyGuarded(ret, context.SemanticModel))
{
return;
}
}
}
// We'll report only a single diagnostic per line, the first.
var loc = context.Node.GetLocation();
if (!loc.IsInSource)
{
return;
}
var line = loc.GetLineSpan().StartLinePosition.Line;
if (reports.TryGetValue(line, out var diagnostic) && diagnostic.Location.SourceSpan.Start <= loc.SourceSpan.Start)
{
return;
}
diagnostic = Diagnostic.Create(platform.Kind == PlatformKind.Uwp ? Analyzer.VersionRule : Analyzer.PlatformRule, loc);
reports[line] = diagnostic;
context.ReportDiagnostic(diagnostic);
}
private bool IsProperlyGuarded(SyntaxNode node, SemanticModel semanticModel)
{
foreach (var symbol in GetGuards(node, semanticModel))
{
if (symbol.ContainingType?.Name == "ApiInformation")
{
return true;
}
}
return false;
}
}
}

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

@ -1,168 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// This class provides guard suggestion and can make the suggested changes.
/// </summary>
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(PlatformSpecificFixerCS))]
[Shared]
public class PlatformSpecificFixerCS : CodeFixProvider
{
/// <summary>
/// Gets the list of Diagnostics that can be fixed.
/// </summary>
public sealed override ImmutableArray<string> FixableDiagnosticIds
{
get { return ImmutableArray.Create(Analyzer.PlatformRule.Id, Analyzer.VersionRule.Id); }
}
/// <summary>
/// Gets the Fix All provider
/// </summary>
/// <returns><see cref="WellKnownFixAllProviders"/></returns>
public sealed override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
/// <summary>
/// Registers for code fix.
/// </summary>
/// <param name="context"><see cref="CodeFixContext"/></param>
/// <returns>awaitable <see cref="Task"/></returns>
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
try
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
// Which node are we interested in? -- if the squiggle is over A.B().C,
// then we need the largest IdentifierName/SimpleMemberAccess/QualifiedName
// that encompasses "C" itself
var diagnostic = context.Diagnostics.First();
var span = new TextSpan(diagnostic.Location.SourceSpan.End - 1, 1);
var node = root.FindToken(span.Start).Parent;
SyntaxKind nodeKind = node.Kind();
while (nodeKind != SyntaxKind.IdentifierName && nodeKind != SyntaxKind.SimpleMemberAccessExpression && nodeKind != SyntaxKind.QualifiedName)
{
node = node.Parent;
if (node == null)
{
return;
}
nodeKind = node.Kind();
}
while (true)
{
if (node.Parent?.Kind() == SyntaxKind.SimpleMemberAccessExpression)
{
node = node.Parent;
continue;
}
if (node.Parent?.Kind() == SyntaxKind.QualifiedName)
{
node = node.Parent;
continue;
}
break;
}
var target = PlatformSpecificAnalyzerCS.GetTargetOfNode(node, semanticModel);
var g = Analyzer.GetGuardForSymbol(target);
// Introduce a guard? (only if it is a method/accessor/constructor, i.e. somewhere that allows code)
var containingBlock = node.FirstAncestorOrSelf<BlockSyntax>();
if (containingBlock != null)
{
var act1 = CodeAction.Create($"Add 'If ApiInformation.{g.KindOfCheck}'", (c) => IntroduceGuardAsync(context.Document, node, g, c), "PlatformSpecificGuard");
context.RegisterCodeFix(act1, diagnostic);
}
}
catch
{
}
}
private async Task<Document> IntroduceGuardAsync(Document document, SyntaxNode node, HowToGuard g, CancellationToken cancellationToken)
{
// + if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent(targetContainingType))
// {
// old-statement
// + }
try
{
var oldStatement = node.FirstAncestorOrSelf<StatementSyntax>();
var oldLeadingTrivia = oldStatement.GetLeadingTrivia();
var conditionReceiver = SyntaxFactory.ParseName($"Windows.Foundation.Metadata.ApiInformation.{g.KindOfCheck}").WithAdditionalAnnotations(Simplifier.Annotation);
ArgumentListSyntax conditionArgument = null;
if (g.MemberToCheck == null)
{
var conditionString1 = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(g.TypeToCheck));
conditionArgument = SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(conditionString1)));
}
else
{
var conditionString1 = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(g.TypeToCheck));
var conditionString2 = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(g.MemberToCheck));
var conditionInt3 = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(g.ParameterCountToCheck ?? 0));
IEnumerable<ArgumentSyntax> conditions = null;
if (g.ParameterCountToCheck.HasValue)
{
conditions = new ArgumentSyntax[] { SyntaxFactory.Argument(conditionString1), SyntaxFactory.Argument(conditionString2), SyntaxFactory.Argument(conditionInt3) };
}
else
{
conditions = new ArgumentSyntax[] { SyntaxFactory.Argument(conditionString1), SyntaxFactory.Argument(conditionString2) };
}
conditionArgument = SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(conditions));
}
var condition = SyntaxFactory.InvocationExpression(conditionReceiver, conditionArgument);
var thenStatements = SyntaxFactory.Block(oldStatement.WithoutLeadingTrivia());
var ifStatement = SyntaxFactory.IfStatement(condition, thenStatements).WithLeadingTrivia(oldLeadingTrivia).WithAdditionalAnnotations(Formatter.Annotation);
var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var newRoot = oldRoot.ReplaceNode(oldStatement, ifStatement);
return document.WithSyntaxRoot(newRoot);
}
catch
{
}
return document;
}
}
}

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

@ -1,168 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.CodeAnalysis.VisualBasic.Syntax;
namespace Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer
{
/// <summary>
/// This class provides guard suggestion and can make the suggested changes.
/// </summary>
[ExportCodeFixProvider(LanguageNames.VisualBasic, Name = nameof(PlatformSpecificFixerCS))]
[Shared]
public class PlatformSpecificFixerVB : CodeFixProvider
{
/// <summary>
/// Gets the list of Diagnostics that can be fixed.
/// </summary>
public sealed override ImmutableArray<string> FixableDiagnosticIds
{
get { return ImmutableArray.Create(Analyzer.PlatformRule.Id, Analyzer.VersionRule.Id); }
}
/// <summary>
/// Gets the Fix All provider
/// </summary>
/// <returns><see cref="WellKnownFixAllProviders"/></returns>
public sealed override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
/// <summary>
/// Registers for code fix.
/// </summary>
/// <param name="context"><see cref="CodeFixContext"/></param>
/// <returns>awaitable <see cref="Task"/></returns>
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
try
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
// Which node are we interested in? -- if the squiggle is over A.B().C,
// then we need the largest IdentifierName/SimpleMemberAccess/QualifiedName
// that encompasses "C" itself
var diagnostic = context.Diagnostics.First();
var span = new TextSpan(diagnostic.Location.SourceSpan.End - 1, 1);
var node = root.FindToken(span.Start).Parent;
SyntaxKind nodeKind = node.Kind();
while (nodeKind != SyntaxKind.IdentifierName && nodeKind != SyntaxKind.SimpleMemberAccessExpression && nodeKind != SyntaxKind.QualifiedName)
{
node = node.Parent;
if (node == null)
{
return;
}
nodeKind = node.Kind();
}
while (true)
{
if (node.Parent?.Kind() == SyntaxKind.SimpleMemberAccessExpression)
{
node = node.Parent;
continue;
}
if (node.Parent?.Kind() == SyntaxKind.QualifiedName)
{
node = node.Parent;
continue;
}
break;
}
var target = PlatformSpecificAnalyzerVB.GetTargetOfNode(node, semanticModel);
var g = Analyzer.GetGuardForSymbol(target);
// Introduce a guard? (only if it is a method/accessor/constructor, i.e. somewhere that allows code)
var containingBlock = node.FirstAncestorOrSelf<MethodBlockBaseSyntax>();
if (containingBlock != null)
{
var act1 = CodeAction.Create($"Add 'If ApiInformation.{g.KindOfCheck}'", (c) => IntroduceGuardAsync(context.Document, node, g, c), "PlatformSpecificGuard");
context.RegisterCodeFix(act1, diagnostic);
}
}
catch
{
}
}
private async Task<Document> IntroduceGuardAsync(Document document, SyntaxNode node, HowToGuard g, CancellationToken cancellationToken)
{
// + If Windows.Foundation.Metadata.ApiInformation.IsTypePresent(targetContainingType) Then
// old-statement
// + End If
try
{
var oldStatement = node.FirstAncestorOrSelf<StatementSyntax>();
var oldLeadingTrivia = oldStatement.GetLeadingTrivia();
var conditionReceiver = SyntaxFactory.ParseName($"Windows.Foundation.Metadata.ApiInformation.{g.KindOfCheck}").WithAdditionalAnnotations(Simplifier.Annotation);
ArgumentListSyntax conditionArgument = null;
if (g.MemberToCheck == null)
{
var conditionString1 = SyntaxFactory.StringLiteralExpression(SyntaxFactory.StringLiteralToken($"\"{g.TypeToCheck}\"", g.TypeToCheck));
conditionArgument = SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList<ArgumentSyntax>(SyntaxFactory.SimpleArgument(conditionString1)));
}
else
{
var conditionString1 = SyntaxFactory.StringLiteralExpression(SyntaxFactory.StringLiteralToken($"\"{g.TypeToCheck}\"", g.TypeToCheck));
var conditionString2 = SyntaxFactory.StringLiteralExpression(SyntaxFactory.StringLiteralToken($"\"{g.MemberToCheck}\"", g.MemberToCheck));
var conditionInt3 = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(g.ParameterCountToCheck ?? 0));
IEnumerable<ArgumentSyntax> conditions = null;
if (g.ParameterCountToCheck.HasValue)
{
conditions = new ArgumentSyntax[] { SyntaxFactory.SimpleArgument(conditionString1), SyntaxFactory.SimpleArgument(conditionString2), SyntaxFactory.SimpleArgument(conditionInt3) };
}
else
{
conditions = new ArgumentSyntax[] { SyntaxFactory.SimpleArgument(conditionString1), SyntaxFactory.SimpleArgument(conditionString2) };
}
conditionArgument = SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(conditions));
}
var condition = SyntaxFactory.InvocationExpression(conditionReceiver, conditionArgument);
var ifStatement = SyntaxFactory.IfStatement(condition);
var thenStatements = SyntaxFactory.SingletonList(oldStatement.WithoutLeadingTrivia());
var ifBlock = SyntaxFactory.MultiLineIfBlock(ifStatement).WithStatements(thenStatements).WithLeadingTrivia(oldLeadingTrivia).WithAdditionalAnnotations(Formatter.Annotation);
var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var newRoot = oldRoot.ReplaceNode(oldStatement, ifBlock);
return document.WithSyntaxRoot(newRoot);
}
catch
{
}
return document;
}
}
}

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

@ -1,58 +0,0 @@
param($installPath, $toolsPath, $package, $project)
if($project.Object.SupportsPackageDependencyResolution)
{
if($project.Object.SupportsPackageDependencyResolution())
{
# Do not install analyzers via install.ps1, instead let the project system handle it.
return
}
}
$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve
foreach($analyzersPath in $analyzersPaths)
{
if (Test-Path $analyzersPath)
{
# Install the language agnostic analyzers.
foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll)
{
if($project.Object.AnalyzerReferences)
{
$project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)
}
}
}
}
# $project.Type gives the language name like (C# or VB.NET)
$languageFolder = ""
if($project.Type -eq "C#")
{
$languageFolder = "cs"
}
if($project.Type -eq "VB.NET")
{
$languageFolder = "vb"
}
if($languageFolder -eq "")
{
return
}
foreach($analyzersPath in $analyzersPaths)
{
# Install language specific analyzers.
$languageAnalyzersPath = join-path $analyzersPath $languageFolder
if (Test-Path $languageAnalyzersPath)
{
foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll)
{
if($project.Object.AnalyzerReferences)
{
$project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)
}
}
}
}

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

@ -1,65 +0,0 @@
param($installPath, $toolsPath, $package, $project)
if($project.Object.SupportsPackageDependencyResolution)
{
if($project.Object.SupportsPackageDependencyResolution())
{
# Do not uninstall analyzers via uninstall.ps1, instead let the project system handle it.
return
}
}
$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve
foreach($analyzersPath in $analyzersPaths)
{
# Uninstall the language agnostic analyzers.
if (Test-Path $analyzersPath)
{
foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll)
{
if($project.Object.AnalyzerReferences)
{
$project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)
}
}
}
}
# $project.Type gives the language name like (C# or VB.NET)
$languageFolder = ""
if($project.Type -eq "C#")
{
$languageFolder = "cs"
}
if($project.Type -eq "VB.NET")
{
$languageFolder = "vb"
}
if($languageFolder -eq "")
{
return
}
foreach($analyzersPath in $analyzersPaths)
{
# Uninstall language specific analyzers.
$languageAnalyzersPath = join-path $analyzersPath $languageFolder
if (Test-Path $languageAnalyzersPath)
{
foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll)
{
if($project.Object.AnalyzerReferences)
{
try
{
$project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)
}
catch
{
}
}
}
}
}

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

@ -280,7 +280,6 @@
<Content Include="SamplePages\RemoteDeviceHelper\RemoteDeviceHelper.png" />
<Content Include="SamplePages\ImageCropper\ImageCropper.png" />
<Content Include="SamplePages\StaggeredLayout\StaggeredLayout.png" />
<Content Include="SamplePages\TabView\TabView.png" />
<Content Include="SamplePages\PeoplePicker\PeoplePicker.png" />
<Content Include="SamplePages\PersonView\PersonView.png" />
<Content Include="SamplePages\TokenizingTextBox\TokenizingTextBox.png" />
@ -301,7 +300,6 @@
<Content Include="SamplePages\DataGrid\DataGrid.png" />
<Content Include="SamplePages\DispatcherQueueHelper\DispatchQueueHelper.png" />
<Content Include="SamplePages\DockPanel\DockPanel.png" />
<Content Include="SamplePages\Facebook Service\FacebookLogo.png" />
<Content Include="SamplePages\LoginButton\LoginButton.png" />
<Content Include="SamplePages\FadeHeader\FadeHeaderBehavior.png" />
<Content Include="SamplePages\Fade\FadeBehavior.png" />
@ -318,7 +316,6 @@
<Content Include="SamplePages\AlignmentGrid\AlignmentGrid.png" />
<Content Include="SamplePages\HeaderedContentControl\HeaderedContentControl.png" />
<Content Include="SamplePages\HeaderedItemsControl\HeaderedItemsControl.png" />
<Content Include="SamplePages\HeaderedTextBlock\HeaderedTextBlock.png" />
<Content Include="SamplePages\ImageBlendBrush\ImageBlendBrush.png" />
<Content Include="SamplePages\ImageCache\ImageCache.png" />
<Content Include="SamplePages\ImageEx\ImageEx.png" />
@ -368,8 +365,6 @@
<Content Include="SamplePages\Twitter Service\TwitterLogo.png" />
<Content Include="SamplePages\Twitter Service\TwitterCode.bind" />
<Content Include="SamplePages\Twitter Service\icon.png" />
<Content Include="SamplePages\Facebook Service\FacebookCode.bind" />
<Content Include="SamplePages\HeaderedTextBlock\HeaderedTextBlockCode.bind" />
<Content Include="SamplePages\ViewExtensions\ViewExtensions.png" />
<Content Include="SamplePages\ViewportBehavior\ViewportBehavior.png" />
<Content Include="SamplePages\Visual Extensions\VisualExtensions.png" />
@ -512,9 +507,6 @@
<Content Include="SamplePages\RemoteDevicePicker\RemoteDevicePickerCode.bind" />
<Content Include="SamplePages\DataGrid\DataGridCode.bind" />
<Content Include="SamplePages\ViewportBehavior\ViewportBehaviorCode.bind" />
<Content Include="SamplePages\TabView\TabViewXaml.bind">
<SubType>Designer</SubType>
</Content>
<Content Include="SamplePages\Weibo Service\WeiboCode.bind" />
<Compile Include="Common\TextBlockHyperlinkBehavior.cs" />
<Compile Include="SamplePages\AutoFocusBehavior\AutoFocusBehaviorPage.xaml.cs">
@ -664,9 +656,6 @@
<Compile Include="Models\LandingPageResource.cs" />
<Compile Include="Models\LandingPageLink.cs" />
<Compile Include="Models\PaneState.cs" />
<Compile Include="SamplePages\TabView\TabViewPage.xaml.cs">
<DependentUpon>TabViewPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\UniformGrid\UniformGridPage.xaml.cs">
<DependentUpon>UniformGridPage.xaml</DependentUpon>
</Compile>
@ -781,9 +770,6 @@
<Compile Include="SamplePages\RemoteDevicePicker\RemoteDevicePickerControlPage.xaml.cs">
<DependentUpon>RemoteDevicePickerControlPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\RssParser\RssParserPage.xaml.cs">
<DependentUpon>RssParserPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\RadialGradientBrush\RadialGradientBrushPage.xaml.cs">
<DependentUpon>RadialGradientBrushPage.xaml</DependentUpon>
</Compile>
@ -929,9 +915,6 @@
<Compile Include="SamplePages\Fade\FadeBehaviorPage.xaml.cs">
<DependentUpon>FadeBehaviorPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\HeaderedTextBlock\HeaderedTextBlockPage.xaml.cs">
<DependentUpon>HeaderedTextBlockPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\ImageEx\ImageExPage.xaml.cs">
<DependentUpon>ImageExPage.xaml</DependentUpon>
</Compile>
@ -1072,10 +1055,6 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SamplePages\TabView\TabViewPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="SamplePages\PeoplePicker\PeoplePickerPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -1260,10 +1239,6 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SamplePages\RssParser\RssParserPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SamplePages\ScrollViewerExtensions\ScrollViewerExtensionsPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -1440,10 +1415,6 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="SamplePages\HeaderedTextBlock\HeaderedTextBlockPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SamplePages\ImageEx\ImageExPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

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

@ -1,23 +0,0 @@
// Initialize service
FacebookService.Instance.Initialize(AppIDText.Text);
// Login to Facebook
if (!await FacebookService.Instance.LoginAsync())
{
return;
}
// Get user's feed
ListView.ItemsSource = await FacebookService.Instance.RequestAsync(FacebookDataConfig.MyFeed, 50);
// Get current user profile picture
ProfileImage.DataContext = await FacebookService.Instance.GetUserPictureInfoAsync();
// Post a message on your wall using Facebook Dialog
await FacebookService.Instance.PostToFeedWithDialogAsync(TitleText.Text, DescriptionText.Text, UrlText.Text);
// Get current user's photo albums
await FacebookService.Instance.GetUserAlbumsAsync();
// Get current user's photos by album Id
await FacebookService.Instance.GetUserPhotosByAlbumIdAsync(addedItem.Id);

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

До

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

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

До

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

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

До

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

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

@ -1,16 +0,0 @@
<Page
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"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d">
<Grid>
<controls:HeaderedTextBlock
Header="@[Header:String:Name]"
Text="@[Text:String:Windows Community Toolkit]"
Orientation="@[Orientation:Enum:Orientation.Vertical]"
Margin="20,10,0,0" />
</Grid>
</Page>

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

@ -1,9 +0,0 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.HeaderedTextBlockPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
</Page>

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

@ -1,18 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Toolkit.Uwp.SampleApp.Models;
using Windows.UI.Xaml.Navigation;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
public sealed partial class HeaderedTextBlockPage
{
public HeaderedTextBlockPage()
{
InitializeComponent();
}
}
}

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

@ -1,46 +0,0 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.RssParserPage"
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"
xmlns:rss="using:Microsoft.Toolkit.Parsers.Rss"
mc:Ignorable="d">
<Grid Padding="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel>
<TextBox x:Name="UrlBox"
Header="Url"
Text="{x:Bind Url, Mode=TwoWay}" />
<Button
Content="Load"
Margin="0,10,0,0"
Click="{x:Bind ParseRSS}" />
<TextBlock Text="Feed" Margin="0,10,0,0" />
</StackPanel>
<ListView
x:Name="RSSList"
Grid.Row="1"
ItemsSource="{x:Bind RSSFeed}"
SelectionChanged="RSSList_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate x:DataType="rss:RssSchema">
<StackPanel Padding="10">
<TextBlock
Text="{x:Bind Title}"
FontSize="18"
FontWeight="Bold" />
<TextBlock Text="{x:Bind Summary}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>

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

@ -1,70 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.ObjectModel;
using System.Net.Http;
using Microsoft.Toolkit.Parsers.Rss;
using Windows.System;
using Windows.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
public sealed partial class RssParserPage : Page
{
public ObservableCollection<RssSchema> RSSFeed { get; } = new ObservableCollection<RssSchema>();
public RssParserPage()
{
this.InitializeComponent();
ParseRSS();
}
public string Url { get; set; } = "https://visualstudiomagazine.com/rss-feeds/news.aspx";
public async void ParseRSS()
{
string feed = null;
RSSFeed.Clear();
using (var client = new HttpClient())
{
try
{
feed = await client.GetStringAsync(Url);
}
catch
{
}
}
if (feed != null)
{
var parser = new RssParser();
var rss = parser.Parse(feed);
foreach (var element in rss)
{
RSSFeed.Add(element);
}
}
}
private async void RSSList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (RSSList.SelectedItem is RssSchema rssItem)
{
try
{
await Launcher.LaunchUriAsync(new Uri(rssItem.FeedUrl));
}
catch
{
}
}
RSSList.SelectedItem = null;
}
}
}

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

До

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

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

@ -1,19 +0,0 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.TabViewPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid x:Name="XamlRoot"/>
<controls:InAppNotification x:Name="TabViewNotification"
ShowDismissButton="True"
AnimationDuration="00:00:00.1000000"
VerticalOffset="100"
HorizontalOffset="0"
StackMode="Replace" />
</Grid>
</Page>

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

@ -1,73 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.ObjectModel;
using Microsoft.Toolkit.Uwp.UI.Controls;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
public sealed partial class TabViewPage : Page, IXamlRenderListener
{
#pragma warning disable CS0618 // Type or member is obsolete
private TabView _tabs;
private int _counter = 1;
public TabViewPage()
{
this.InitializeComponent();
}
public void OnXamlRendered(FrameworkElement control)
{
_tabs = control.FindChildByName("Tabs") as TabView;
if (_tabs != null)
{
_tabs.TabDraggedOutside += Tabs_TabDraggedOutside;
_tabs.TabClosing += Tabs_TabClosing;
}
var btn = control.FindDescendantByName("AddTabButtonUpper") as Button;
if (btn != null)
{
btn.Click += AddUpperTabClick;
}
}
private void AddUpperTabClick(object sender, RoutedEventArgs e)
{
_tabs.Items.Add(new TabViewItem()
{
Header = "Untitled " + _counter,
Icon = new SymbolIcon(Symbol.Document),
Content = "This is new tab #" + _counter++ + "."
});
}
private void Tabs_TabClosing(object sender, TabClosingEventArgs e)
{
TabViewNotification.Show("You're closing the '" + e.Tab.Header + "' tab.", 2000);
}
private void Tabs_TabDraggedOutside(object sender, TabDraggedOutsideEventArgs e)
{
// The sample app let's you drag items from a static TabView with TabViewItem's pre-defined.
// In the case of data bound scenarios e.Item should be your data item, and e.Tab should always be the TabViewItem.
var str = e.Item.ToString();
if (e.Tab != null)
{
str = e.Tab.Header.ToString();
}
TabViewNotification.Show("Tore Tab '" + str + "' Outside of TabView.", 2000);
}
#pragma warning restore CS0618 // Type or member is obsolete
}
}

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

@ -1,97 +0,0 @@
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ex="using:Microsoft.Toolkit.Uwp.UI.Extensions"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<controls:TabView x:Name="Tabs"
TabWidthBehavior="@[Tab Width Behavior:Enum:TabWidthMode.Actual]"
CanCloseTabs="@[Can Close Tabs:Bool:False]"
IsCloseButtonOverlay="@[Overlay Close Button:Bool:False]"
CanDragItems="@[Drag and Drop Enabled:Bool:False]"
CanReorderItems="@[Drag and Drop Enabled]"
AllowDrop="@[Drag and Drop Enabled]"
SelectedTabWidth="200">
<controls:TabView.Resources>
<x:Double x:Key="TabViewItemHeaderMinHeight">40</x:Double>
<x:Double x:Key="TabViewItemHeaderMinWidth">48</x:Double>
<x:Double x:Key="TabViewItemHeaderMaxWidth">200</x:Double>
</controls:TabView.Resources>
<controls:TabView.Header>
<TextBlock Padding="16,8,0,8" FontSize="16" FontWeight="Bold" Text="TabView Control Header"/>
</controls:TabView.Header>
<controls:TabView.TabStartHeader>
<Button Width="48"
Height="{StaticResource TabViewItemHeaderMinHeight}"
Margin="0,0,-1,0"
BorderThickness="1"
Background="Transparent"
Style="{StaticResource ButtonRevealStyle}"
Padding="2,2,0,0">
<Viewbox MaxWidth="16" MaxHeight="16">
<SymbolIcon Symbol="AddFriend"/>
</Viewbox>
</Button>
</controls:TabView.TabStartHeader>
<!-- Tabs -->
<controls:TabViewItem Header="Home" Icon="Home">
<TextBlock Padding="16">The TabView control has multiple uses.</TextBlock>
</controls:TabViewItem>
<controls:TabViewItem Header="Tab 2 Has Longer Text" Icon="Audio">
<TextBlock Padding="16">It has a lot of versatility out of the box for different scenarios.</TextBlock>
</controls:TabViewItem>
<controls:TabViewItem Header="Tab 3" Icon="Video">
<TextBlock Padding="16">You can enable drag-and-drop and reorder the tabs too.</TextBlock>
</controls:TabViewItem>
<controls:TabViewItem Header="Not Closable" Icon="Calendar" IsClosable="False">
<TextBlock Padding="16">This tab isn't closable because its IsClosable property is set to False, even when CanCloseTabs is True.</TextBlock>
</controls:TabViewItem>
<controls:TabView.TabActionHeader>
<Button x:Name="AddTabButtonUpper"
Width="48"
Height="{StaticResource TabViewItemHeaderMinHeight}"
Margin="-1,0,0,0"
BorderThickness="1"
Background="Transparent"
Style="{StaticResource ButtonRevealStyle}">
<Viewbox MaxWidth="16"
MaxHeight="16">
<FontIcon FontFamily="Segoe MDL2 Assets"
Glyph="&#xE710;" />
</Viewbox>
</Button>
</controls:TabView.TabActionHeader>
<controls:TabView.TabEndHeader>
<Button Width="48"
Height="{StaticResource TabViewItemHeaderMinHeight}"
Margin="-1,0,0,0"
BorderThickness="1"
Background="Transparent"
Style="{StaticResource ButtonRevealStyle}">
<Viewbox MaxWidth="16" MaxHeight="16">
<SymbolIcon Symbol="Setting"/>
</Viewbox>
</Button>
</controls:TabView.TabEndHeader>
<controls:TabView.Footer>
<TextBlock Padding="16,8,16,8"
HorizontalAlignment="Right"
FontSize="16" FontWeight="Bold"
Text="TabView Control Footer" />
</controls:TabView.Footer>
</controls:TabView>
</Grid>
</Page>

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

@ -14,18 +14,6 @@
"Icon": "/SamplePages/TextToolbar/TextToolbar.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/TextToolbar.md"
},
{
"Name": "TabView",
"Type": "TabViewPage",
"Subcategory": "Layout",
"BadgeUpdateVersionRequired": "DEPRECATED",
"DeprecatedWarning": "Please migrate to the TabView control from WinUI, this control will be removed in a future release. https://aka.ms/winui",
"About": "A control for displaying multiple items in the same space and allows a user to easily switch between them.",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TabView",
"XamlCodeFile": "TabViewXaml.bind",
"Icon": "/SamplePages/TabView/TabView.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/TabView.md"
},
{
"Name": "DataGrid",
"Type": "DataGridPage",
@ -86,18 +74,6 @@
"Icon": "/SamplePages/ImageEx/ImageEx.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/ImageEx.md"
},
{
"Name": "HeaderedTextBlock",
"Type": "HeaderedTextBlockPage",
"Subcategory": "Layout",
"About": "The HeaderedTextBlock control is designed to provide a header for read only text. This control is useful for displaying read only forms.",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/HeaderedTextBlock",
"XamlCodeFile": "HeaderedTextBlockCode.bind",
"Icon": "/SamplePages/HeaderedTextBlock/HeaderedTextBlock.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/HeaderedTextBlock.md",
"BadgeUpdateVersionRequired": "DEPRECATED",
"DeprecatedWarning": "The HeaderedTextBlock has been replaced with the HeaderedContentControl and will be removed in a future major release."
},
{
"Name": "MasterDetailsView",
"Type": "MasterDetailsViewPage",
@ -658,16 +634,6 @@
"Name": "Services",
"Icon": "Icons/Services.png",
"Samples": [
{
"Name": "Facebook Service",
"About": "The Facebook Service allows you to retrieve or publish data to Facebook graph.",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Services/Services/Facebook",
"CodeFile": "FacebookCode.bind",
"Icon": "/SamplePages/Facebook Service/FacebookLogo.png",
"BadgeUpdateVersionRequired": "DEPRECATED",
"DeprecatedWarning": "The underlying library, winsdkfb, which the FacebookService relies on is not currently maintained.",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/services/Facebook.md"
},
{
"Name": "Microsoft Graph Service",
"About": "These providers help you easily authenticate and connect to the Microsoft Graph.",
@ -909,14 +875,6 @@
"Icon": "/Assets/Helpers.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/parsers/MarkdownParser.md"
},
{
"Name": "RSS Parser",
"Type": "RssParserPage",
"Subcategory": "Parser",
"About": "The RSS Parser allows you to parse an RSS content String into RSS Schema.",
"Icon": "/Assets/Helpers.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/parsers/RssParser.md"
},
{
"Name": "LiveTile",
"Type": "LiveTilePage",
@ -964,14 +922,6 @@
"Icon": "/Assets/Helpers.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/high-performance/Introduction.md"
},
{
"Name": "PlatformSpecificAnalyzer",
"Subcategory": "Developer",
"About": "Platform Specific Analyzer is a Roslyn analyzer that analyzes and suggests code fixes to ensure that any version / platform specific API are guarded by correct runtime checks",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer",
"Icon": "/Assets/Helpers.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/platform-specific/PlatformSpecificAnalyzer.md"
},
{
"Name": "CompareStateTrigger",
"Type": "CompareStateTriggerPage",

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

@ -1,19 +0,0 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFramework>uap10.0.16299</TargetFramework>
<Title>Windows Community Toolkit Services</Title>
<Description>This library enables access to Facebook. It is part of the Windows Community Toolkit.</Description>
<PackageTags>UWP Toolkit Windows OAuth Facebook</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="winsdkfb" Version="0.12.20161020.4" />
<!-- This is here to prevent a conflict in certain circumstances -->
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<ProjectReference Include="..\Microsoft.Toolkit.Uwp\Microsoft.Toolkit.Uwp.csproj" />
</ItemGroup>
</Project>

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

@ -1,4 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cmicrosoftgraph_005Cmessage/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cmicrosoftgraph_005Cuser/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

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

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="Microsoft.Toolkit.Uwp.Services">
</Library>
</Directives>

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

@ -1,42 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Strongly types Facebook Album object. Partial for extending properties.
/// </summary>
public partial class FacebookAlbum
{
/// <summary>
/// Gets a string description of the strongly typed properties in this model.
/// </summary>
public static string Fields => "id, name, description, cover_photo, picture";
/// <summary>
/// Gets or sets id property.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Gets or sets name property.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets description property.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Gets or sets cover_photo property.
/// </summary>
public FacebookPhoto Cover_Photo { get; set; }
/// <summary>
/// Gets or sets picture property.
/// </summary>
public FacebookPictureData Picture { get; set; }
}
}

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

@ -1,32 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Configuration object for specifying richer query information.
/// </summary>
public class FacebookDataConfig
{
/// <summary>
/// Gets a predefined config to get user feed. The feed of posts (including status updates) and links published by this person, or by others on this person's profile
/// </summary>
public static FacebookDataConfig MyFeed => new FacebookDataConfig { Query = "/me/feed" };
/// <summary>
/// Gets a predefined config to show only the posts that were published by this person
/// </summary>
public static FacebookDataConfig MyPosts => new FacebookDataConfig { Query = "/me/posts" };
/// <summary>
/// Gets a predefined config to show only the posts that this person was tagged in
/// </summary>
public static FacebookDataConfig MyTagged => new FacebookDataConfig { Query = "/me/tagged" };
/// <summary>
/// Gets or sets the query string for filtering service results.
/// </summary>
public string Query { get; set; }
}
}

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

@ -1,18 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Class used to store JSON data response from Facebook
/// </summary>
/// <typeparam name="T">Type of the inner data</typeparam>
internal class FacebookDataHost<T>
{
/// <summary>
/// Gets or sets internal data.
/// </summary>
public T Data { get; set; }
}
}

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

@ -1,22 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Facebook OAuth tokens.
/// </summary>
public class FacebookOAuthTokens
{
/// <summary>
/// Gets or sets facebook AppId.
/// </summary>
public string AppId { get; set; }
/// <summary>
/// Gets or sets Windows Store ID.
/// </summary>
public string WindowsStoreId { get; set; }
}
}

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

@ -1,120 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// List of user related data permissions
/// </summary>
[Flags]
public enum FacebookPermissions
{
/// <summary>
/// Public profile
/// </summary>
PublicProfile = 1,
/// <summary>
/// Email
/// </summary>
Email = 2,
/// <summary>
/// Publish actions
/// </summary>
PublishActions = 4,
/// <summary>
/// About me
/// </summary>
UserAboutMe = 8,
/// <summary>
/// Birthday
/// </summary>
UserBirthday = 16,
/// <summary>
/// Education history
/// </summary>
UserEducationHistory = 32,
/// <summary>
/// Friends
/// </summary>
UserFriends = 64,
/// <summary>
/// Games activity
/// </summary>
UserGamesActivity = 128,
/// <summary>
/// Hometown
/// </summary>
UserHometown = 256,
/// <summary>
/// Likes
/// </summary>
UserLikes = 512,
/// <summary>
/// Location
/// </summary>
UserLocation = 1024,
/// <summary>
/// Photos
/// </summary>
UserPhotos = 2048,
/// <summary>
/// Posts
/// </summary>
UserPosts = 4096,
/// <summary>
/// Relationship details
/// </summary>
UserRelationshipDetails = 8192,
/// <summary>
/// Relationships
/// </summary>
UserRelationships = 16384,
/// <summary>
/// Religion and politics
/// </summary>
UserReligionPolitics = 32768,
/// <summary>
/// Status
/// </summary>
UserStatus = 65536,
/// <summary>
/// Tagged places
/// </summary>
UserTaggedPlaces = 131072,
/// <summary>
/// Videos
/// </summary>
UserVideos = 262144,
/// <summary>
/// Website
/// </summary>
UserWebsite = 524288,
/// <summary>
/// WorkHistory
/// </summary>
UserWorkHistory = 1048576
}
}

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

@ -1,55 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Strongly types Facebook Photo object. Partial for extending properties.
/// </summary>
public partial class FacebookPhoto
{
/// <summary>
/// Gets a string description of the strongly typed properties in this model.
/// </summary>
public static string Fields => "id, album, link, created_time, name, images, picture";
/// <summary>
/// Gets or sets id property.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Gets or sets album property.
/// </summary>
public FacebookAlbum Album { get; set; }
/// <summary>
/// Gets or sets a link to the entity instance.
/// </summary>
public string Link { get; set; }
/// <summary>
/// Gets or sets time the entity instance was created.
/// </summary>
public DateTime Created_Time { get; set; }
/// <summary>
/// Gets or sets name property.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets images property.
/// </summary>
public List<FacebookPlatformImageSource> Images { get; set; }
/// <summary>
/// Gets or sets picture property.
/// </summary>
public string Picture { get; set; }
}
}

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

@ -1,32 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Strongly typed object for presenting picture data returned from service provider.
/// </summary>
public class FacebookPicture
{
/// <summary>
/// Gets or sets a value indicating whether the picture is a silhouette or not.
/// </summary>
public bool Is_Silhouette { get; set; }
/// <summary>
/// Gets or sets an url to the picture.
/// </summary>
public string Url { get; set; }
/// <summary>
/// Gets or sets the ID of the picture.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Gets or sets the url of the page with the picture.
/// </summary>
public string Link { get; set; }
}
}

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

@ -1,17 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Strongly types Facebook Picture object. Partial for extending properties.
/// </summary>
public partial class FacebookPictureData
{
/// <summary>
/// Gets or sets data property.
/// </summary>
public FacebookPicture Data { get; set; }
}
}

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

@ -1,32 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Strongly types Facebook PlatformImageSource object. Partial for extending properties.
/// </summary>
public partial class FacebookPlatformImageSource
{
/// <summary>
/// Gets a string description of the strongly typed properties in this model.
/// </summary>
public static string Fields => "height, source, width";
/// <summary>
/// Gets or sets height property.
/// </summary>
public string Height { get; set; }
/// <summary>
/// Gets or sets source property.
/// </summary>
public string Source { get; set; }
/// <summary>
/// Gets or sets width property.
/// </summary>
public string Width { get; set; }
}
}

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

@ -1,44 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Strongly typed object for presenting post data returned from service provider.
/// </summary>
public class FacebookPost
{
/// <summary>
/// Gets a string description of the strongly typed properties in this model.
/// </summary>
public static string Fields => "id, message, created_time, link, full_picture";
/// <summary>
/// Gets or sets id property.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Gets or sets message or post text.
/// </summary>
public string Message { get; set; }
/// <summary>
/// Gets or sets time the entity instance was created.
/// </summary>
public DateTime Created_Time { get; set; }
/// <summary>
/// Gets or sets a link to the entity instance.
/// </summary>
public string Link { get; set; }
/// <summary>
/// Gets or sets a link to the accompanying image.
/// </summary>
public string Full_Picture { get; set; }
}
}

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

@ -1,121 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Windows.Foundation.Collections;
using winsdkfb;
using winsdkfb.Graph;
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Type to handle paged requests to Facebook Graph.
/// </summary>
/// <typeparam name="T">Strong type to return.</typeparam>
public class FacebookRequestSource<T> : Collections.IIncrementalSource<T>
{
private bool _isFirstCall = true;
private FBPaginatedArray _paginatedArray;
private FacebookDataConfig _config;
private string _fields;
private PropertySet _propertySet;
private FBJsonClassFactory _factory;
private string _limit;
private int _maxPages;
/// <summary>
/// Initializes a new instance of the <see cref="FacebookRequestSource{T}"/> class.
/// </summary>
public FacebookRequestSource()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FacebookRequestSource{T}"/> class.
/// </summary>
/// <param name="config">Config containing query information.</param>
/// <param name="fields">Comma-separated list of properties expected in the JSON response. Accompanying properties must be found on the strong-typed T.</param>
/// <param name="limit">A string representation of the number of records for page - i.e. pageSize.</param>
/// <param name="maxPages">Upper limit of pages to return.</param>
public FacebookRequestSource(FacebookDataConfig config, string fields, string limit, int maxPages)
{
_config = config;
_fields = fields;
_limit = limit;
_maxPages = maxPages;
_propertySet = new PropertySet { { "fields", _fields }, { "limit", _limit } };
_factory = new FBJsonClassFactory(s => JsonConvert.DeserializeObject(s, typeof(T)));
// FBPaginatedArray does not allow us to set page size per request so we must go with first supplied - see https://github.com/Microsoft/winsdkfb/issues/221
_paginatedArray = new FBPaginatedArray(_config.Query, _propertySet, _factory);
}
/// <summary>
/// Returns strong typed page of data.
/// </summary>
/// <param name="pageIndex">Page number.</param>
/// <param name="pageSize">Size of page.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Strong typed page of data.</returns>
public async Task<IEnumerable<T>> GetPagedItemsAsync(int pageIndex, int pageSize, CancellationToken cancellationToken = default(CancellationToken))
{
if (_isFirstCall)
{
var result = await _paginatedArray.FirstAsync();
return ProcessResult(result);
}
else
{
if (cancellationToken.IsCancellationRequested)
{
return null;
}
if (_paginatedArray.HasNext && (pageIndex < _maxPages))
{
var result = await _paginatedArray.NextAsync();
return ProcessResult(result);
}
else
{
return null;
}
}
}
private IEnumerable<T> ProcessResult(FBResult result)
{
List<T> items = new List<T>();
if (result.Succeeded)
{
IReadOnlyList<object> processedResults = (IReadOnlyList<object>)result.Object;
foreach (T processedResult in processedResults)
{
items.Add(processedResult);
}
_isFirstCall = false;
return items;
}
throw new Exception(result.ErrorInfo?.Message);
}
}
}

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

@ -1,515 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Foundation.Metadata;
using Windows.Security.Authentication.Web;
using Windows.Storage.Streams;
using winsdkfb;
using winsdkfb.Graph;
namespace Microsoft.Toolkit.Uwp.Services.Facebook
{
/// <summary>
/// Class for connecting to Facebook.
/// </summary>
[Obsolete("The underlying library, winsdkfb, which the FacebookService relies on is not currently maintained.")]
public class FacebookService
{
/// <summary>
/// Field for tracking initialization status.
/// </summary>
private bool isInitialized;
/// <summary>
/// List of permissions required by the app.
/// </summary>
private FBPermissions permissions;
/// <summary>
/// Gets a Windows Store ID associated with the current app
/// </summary>
public string WindowsStoreId => WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
/// <summary>
/// Initializes a new instance of the <see cref="FacebookService"/> class.
/// </summary>
public FacebookService()
{
}
/// <summary>
/// Initialize underlying provider with relevant token information.
/// </summary>
/// <param name="oAuthTokens">Token instance.</param>
/// <param name="requiredPermissions">List of required permissions. public_profile and user_posts permissions will be used by default.</param>
/// <returns>Success or failure.</returns>
public bool Initialize(FacebookOAuthTokens oAuthTokens, FacebookPermissions requiredPermissions = FacebookPermissions.PublicProfile | FacebookPermissions.UserPosts)
{
if (oAuthTokens == null)
{
throw new ArgumentNullException(nameof(oAuthTokens));
}
return Initialize(oAuthTokens.AppId, requiredPermissions, oAuthTokens.WindowsStoreId);
}
/// <summary>
/// Initialize underlying provider with relevant token information.
/// </summary>
/// <param name="appId">Application ID (Provided by Facebook developer site)</param>
/// <param name="requiredPermissions">List of required permissions. public_profile and user_posts permissions will be used by default.</param>
/// <param name="windowsStoreId">Windows Store SID</param>
/// <returns>Success or failure.</returns>
public bool Initialize(string appId, FacebookPermissions requiredPermissions = FacebookPermissions.PublicProfile | FacebookPermissions.UserPosts, string windowsStoreId = null)
{
if (string.IsNullOrEmpty(appId))
{
throw new ArgumentNullException(nameof(appId));
}
if (string.IsNullOrEmpty(windowsStoreId))
{
windowsStoreId = WindowsStoreId;
}
isInitialized = true;
Provider.FBAppId = appId;
Provider.WinAppId = windowsStoreId;
// Permissions
var permissionList = new List<string>();
foreach (FacebookPermissions value in Enum.GetValues(typeof(FacebookPermissions)))
{
if ((requiredPermissions & value) != 0)
{
var name = value.ToString();
var finalName = new StringBuilder();
foreach (var c in name)
{
if (char.IsUpper(c))
{
if (finalName.Length > 0)
{
finalName.Append('_');
}
finalName.Append(char.ToLower(c));
}
else
{
finalName.Append(c);
}
}
permissionList.Add(finalName.ToString());
}
}
permissions = new FBPermissions(permissionList);
return true;
}
/// <summary>
/// Private singleton field.
/// </summary>
private static FacebookService instance;
/// <summary>
/// Gets public singleton property.
/// </summary>
public static FacebookService Instance => instance ?? (instance = new FacebookService());
/// <summary>
/// Gets a reference to an instance of the underlying data provider.
/// </summary>
public FBSession Provider
{
get
{
if (!isInitialized)
{
throw new InvalidOperationException("Provider not initialized.");
}
return FBSession.ActiveSession;
}
}
/// <summary>
/// Gets the current logged user name.
/// </summary>
public string LoggedUser => !Provider.LoggedIn ? null : FBSession.ActiveSession.User.Name;
/// <summary>
/// Login with set of required requiredPermissions.
/// </summary>
/// <returns>Success or failure.</returns>
public async Task<bool> LoginAsync()
{
if (Provider != null)
{
var result = await Provider.LoginAsync(permissions, SessionLoginBehavior.WebView);
if (result.Succeeded)
{
return true;
}
if (result.ErrorInfo != null)
{
Debug.WriteLine(string.Format("Error logging in: {0}", result.ErrorInfo.Message));
}
return false;
}
Debug.WriteLine("Error logging in - no Active session found");
return false;
}
/// <summary>
/// Log out of the underlying service instance.
/// </summary>
/// <returns>Task to support await of async call.</returns>
public Task LogoutAsync()
{
return Provider.LogoutAsync().AsTask();
}
/// <summary>
/// Request list data from service provider based upon a given config / query.
/// </summary>
/// <param name="config">FacebookDataConfig instance.</param>
/// <param name="maxRecords">Upper limit of records to return.</param>
/// <returns>Strongly typed list of data returned from the service.</returns>
public Task<List<FacebookPost>> RequestAsync(FacebookDataConfig config, int maxRecords = 20)
{
return RequestAsync<FacebookPost>(config, maxRecords, FacebookPost.Fields);
}
/// <summary>
/// Request list data from service provider based upon a given config / query.
/// </summary>
/// <typeparam name="T">Strong type of model.</typeparam>
/// <param name="config">FacebookDataConfig instance.</param>
/// <param name="maxRecords">Upper limit of records to return.</param>
/// <param name="fields">A comma separated string of required fields, which will have strongly typed representation in the model passed in.</param>
/// <returns>Strongly typed list of data returned from the service.</returns>
public async Task<List<T>> RequestAsync<T>(FacebookDataConfig config, int maxRecords = 20, string fields = "id,message,from,created_time,link,full_picture")
{
if (Provider.LoggedIn)
{
var requestSource = new FacebookRequestSource<T>(config, fields, maxRecords.ToString(), 1);
var list = await requestSource.GetPagedItemsAsync(0, maxRecords);
return new List<T>(list);
}
var isLoggedIn = await LoginAsync();
if (isLoggedIn)
{
return await RequestAsync<T>(config, maxRecords, fields);
}
return null;
}
/// <summary>
/// Request list data from service provider based upon a given config / query.
/// </summary>
/// <param name="config">FacebookDataConfig instance.</param>
/// <param name="pageSize">Upper limit of records to return.</param>
/// <param name="maxPages">Upper limit of pages to return.</param>
/// <returns>Strongly typed list of data returned from the service.</returns>
public Task<IncrementalLoadingCollection<FacebookRequestSource<FacebookPost>, FacebookPost>> RequestAsync(FacebookDataConfig config, int pageSize, int maxPages)
{
return RequestAsync<FacebookPost>(config, pageSize, maxPages, FacebookPost.Fields);
}
/// <summary>
/// Request generic list data from service provider based upon a given config / query.
/// </summary>
/// <typeparam name="T">Strong type of model.</typeparam>
/// <param name="config">FacebookDataConfig instance.</param>
/// <param name="pageSize">Upper limit of records to return.</param>
/// <param name="maxPages">Upper limit of pages to return.</param>
/// <param name="fields">A comma separated string of required fields, which will have strongly typed representation in the model passed in.</param>
/// <returns>Strongly typed list of data returned from the service.</returns>
public async Task<IncrementalLoadingCollection<FacebookRequestSource<T>, T>> RequestAsync<T>(FacebookDataConfig config, int pageSize, int maxPages, string fields = "id,message,from,created_time,link,full_picture")
{
if (Provider.LoggedIn)
{
var requestSource = new FacebookRequestSource<T>(config, fields, pageSize.ToString(), maxPages);
return new IncrementalLoadingCollection<FacebookRequestSource<T>, T>(requestSource);
}
var isLoggedIn = await LoginAsync();
if (isLoggedIn)
{
return await RequestAsync<T>(config, pageSize, maxPages, fields);
}
return null;
}
/// <summary>
/// Returns the <see cref="FacebookPicture"/> object associated with the logged user
/// </summary>
/// <returns>A <see cref="FacebookPicture"/> object</returns>
public async Task<FacebookPicture> GetUserPictureInfoAsync()
{
if (Provider.LoggedIn)
{
var factory = new FBJsonClassFactory(JsonConvert.DeserializeObject<FacebookDataHost<FacebookPicture>>);
PropertySet propertySet = new PropertySet { { "redirect", "0" } };
var singleValue = new FBSingleValue("/me/picture", propertySet, factory);
var result = await singleValue.GetAsync();
if (result.Succeeded)
{
return ((FacebookDataHost<FacebookPicture>)result.Object).Data;
}
throw new Exception(result.ErrorInfo?.Message);
}
var isLoggedIn = await LoginAsync();
if (isLoggedIn)
{
return await GetUserPictureInfoAsync();
}
return null;
}
/// <summary>
/// Retrieves list of user photo albums.
/// </summary>
/// <param name="maxRecords">Upper limit of records to return.</param>
/// <param name="fields">Custom list of Album fields to retrieve.</param>
/// <returns>List of User Photo Albums.</returns>
public async Task<List<FacebookAlbum>> GetUserAlbumsAsync(int maxRecords = 20, string fields = null)
{
fields = fields ?? FacebookAlbum.Fields;
var config = new FacebookDataConfig { Query = "/me/albums" };
return await RequestAsync<FacebookAlbum>(config, maxRecords, fields);
}
/// <summary>
/// Retrieves list of user photo albums.
/// </summary>
/// <param name="pageSize">Number of records to retrieve per page.</param>
/// <param name="maxPages">Upper limit of pages to return.</param>
/// <param name="fields">Custom list of Album fields to retrieve.</param>
/// <returns>List of User Photo Albums.</returns>
public async Task<IncrementalLoadingCollection<FacebookRequestSource<FacebookAlbum>, FacebookAlbum>> GetUserAlbumsAsync(int pageSize, int maxPages, string fields = null)
{
fields = fields ?? FacebookAlbum.Fields;
var config = new FacebookDataConfig { Query = "/me/albums" };
return await RequestAsync<FacebookAlbum>(config, pageSize, maxPages, fields);
}
/// <summary>
/// Retrieves list of user photos by album id.
/// </summary>
/// <param name="albumId">Albums Id for photos.</param>
/// <param name="maxRecords">Upper limit of records to return</param>
/// <param name="fields">Custom list of Photo fields to retrieve.</param>
/// <returns>List of User Photos.</returns>
public async Task<List<FacebookPhoto>> GetUserPhotosByAlbumIdAsync(string albumId, int maxRecords = 20, string fields = null)
{
fields = fields ?? FacebookPhoto.Fields;
var config = new FacebookDataConfig { Query = $"/{albumId}/photos" };
return await RequestAsync<FacebookPhoto>(config, maxRecords, fields);
}
/// <summary>
/// Retrieves list of user photos by album id.
/// </summary>
/// <param name="albumId">Albums Id for photos.</param>
/// <param name="pageSize">Number of records to retrieve per page.</param>
/// <param name="maxPages">Upper limit of pages to return.</param>
/// <param name="fields">Custom list of Photo fields to retrieve.</param>
/// <returns>List of User Photos.</returns>
public async Task<IncrementalLoadingCollection<FacebookRequestSource<FacebookPhoto>, FacebookPhoto>> GetUserPhotosByAlbumIdAsync(string albumId, int pageSize, int maxPages, string fields = null)
{
fields = fields ?? FacebookPhoto.Fields;
var config = new FacebookDataConfig { Query = $"/{albumId}/photos" };
return await RequestAsync<FacebookPhoto>(config, pageSize, maxPages, fields);
}
/// <summary>
/// Retrieves a photo by id.
/// </summary>
/// <param name="photoId">Photo Id for the photo.</param>
/// <returns>A single photo.</returns>
public async Task<FacebookPhoto> GetPhotoByPhotoIdAsync(string photoId)
{
if (Provider.LoggedIn)
{
var factory = new FBJsonClassFactory(JsonConvert.DeserializeObject<FacebookPhoto>);
PropertySet propertySet = new PropertySet { { "fields", "images" } };
var singleValue = new FBSingleValue($"/{photoId}", propertySet, factory);
var result = await singleValue.GetAsync();
if (result.Succeeded)
{
return (FacebookPhoto)result.Object;
}
throw new Exception(result.ErrorInfo?.Message);
}
var isLoggedIn = await LoginAsync();
if (isLoggedIn)
{
return await GetPhotoByPhotoIdAsync(photoId);
}
return null;
}
/// <summary>
/// Enables direct posting data to the timeline.
/// </summary>
/// <param name="link">Link contained as part of the post. Cannot be null.</param>
/// <returns>Task to support await of async call.</returns>
[Deprecated("The underlying publish_action permission is no longer supported by Facebook. Please see https://developers.facebook.com/blog/post/2018/04/24/new-facebook-platform-product-changes-policy-updates/ for details.", DeprecationType.Deprecate, 4)]
public async Task<bool> PostToFeedAsync(string link)
{
if (Provider.LoggedIn)
{
var parameters = new PropertySet { { "link", link } };
string path = FBSession.ActiveSession.User.Id + "/feed";
var factory = new FBJsonClassFactory(JsonConvert.DeserializeObject<FacebookPost>);
var singleValue = new FBSingleValue(path, parameters, factory);
var result = await singleValue.PostAsync();
if (result.Succeeded)
{
var postResponse = result.Object as FacebookPost;
if (postResponse != null)
{
return true;
}
}
Debug.WriteLine(string.Format("Could not post. {0}", result.ErrorInfo?.ErrorUserMessage));
return false;
}
var isLoggedIn = await LoginAsync();
if (isLoggedIn)
{
return await PostToFeedAsync(link);
}
return false;
}
/// <summary>
/// Enables posting data to the timeline using Facebook dialog.
/// </summary>
/// <param name="link">Link contained as part of the post. Cannot be null.</param>
/// <returns>Task to support await of async call.</returns>
public async Task<bool> PostToFeedWithDialogAsync(string link)
{
if (Provider.LoggedIn)
{
var parameters = new PropertySet { { "link", link } };
var result = await Provider.ShowFeedDialogAsync(parameters);
if (result.Succeeded)
{
return true;
}
Debug.WriteLine(string.Format("Could not post. {0}", result.ErrorInfo?.ErrorUserMessage));
return false;
}
var isLoggedIn = await LoginAsync();
if (isLoggedIn)
{
return await PostToFeedWithDialogAsync(link);
}
return false;
}
/// <summary>
/// Enables posting a picture to the timeline
/// </summary>
/// <param name="title">Title of the post.</param>
/// <param name="pictureName">Picture name.</param>
/// <param name="pictureStream">Picture stream to upload.</param>
/// <returns>Return ID of the picture</returns>
[Deprecated("The underlying publish_action permission is no longer supported by Facebook. Please see https://developers.facebook.com/blog/post/2018/04/24/new-facebook-platform-product-changes-policy-updates/ for details.", DeprecationType.Deprecate, 4)]
public async Task<string> PostPictureToFeedAsync(string title, string pictureName, IRandomAccessStreamWithContentType pictureStream)
{
if (pictureStream == null)
{
return null;
}
if (Provider.LoggedIn)
{
var facebookPictureStream = new FBMediaStream(pictureName, pictureStream);
var parameters = new PropertySet
{
{ "source", facebookPictureStream },
{ "name", title }
};
string path = FBSession.ActiveSession.User.Id + "/photos";
var factory = new FBJsonClassFactory(JsonConvert.DeserializeObject<FacebookPicture>);
var singleValue = new FBSingleValue(path, parameters, factory);
var result = await singleValue.PostAsync();
if (result.Succeeded)
{
var photoResponse = result.Object as FacebookPicture;
if (photoResponse != null)
{
return photoResponse.Id;
}
}
return null;
}
var isLoggedIn = await LoginAsync();
if (isLoggedIn)
{
return await PostPictureToFeedAsync(title, pictureName, pictureStream);
}
return null;
}
}
}

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

@ -361,22 +361,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
}
}
/// <summary>
/// Sets the object that will be used during next Frame navigation for
/// Connected Animation involving a list control (item must be an element of
/// ListViewBase.ItemsSource collection).
/// Useful if the parameter used during page navigation is different from the
/// data item in the list control. Also useful during back navigation if the
/// item navigating back to is different from the item that was navigated from.
/// </summary>
/// <param name="frame">The Frame handling the navigation</param>
/// <param name="item">The data item from a list control to be animated during next frame navigation</param>
[Obsolete("Method is replaced by SetListDataItemForNextConnectedAnimation")]
public static void SetListDataItemForNextConnectedAnnimation(this Frame frame, object item)
{
GetConnectedAnimationHelper(frame)?.SetParameterForNextFrameNavigation(item);
}
/// <summary>
/// Sets the object that will be used during next Frame navigation for
/// Connected Animation involving a list control (item must be an element of

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

@ -1,49 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Toolkit.Uwp.UI.Controls.Design.Common;
using Microsoft.Windows.Design;
using Microsoft.Windows.Design.Features;
using Microsoft.Windows.Design.Metadata;
using Microsoft.Windows.Design.Model;
using Microsoft.Windows.Design.PropertyEditing;
using System.ComponentModel;
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
{
internal class HeaderedTextBlockDefaults : DefaultInitializer
{
public override void InitializeDefaults(ModelItem item)
{
item.Properties[nameof(HeaderedTextBlock.Header)].SetValue(string.Empty);
item.Properties[nameof(HeaderedTextBlock.Text)].SetValue(string.Empty);
}
}
internal class HeaderedTextBlockMetadata : AttributeTableBuilder
{
public HeaderedTextBlockMetadata()
: base()
{
AddCallback(typeof(Microsoft.Toolkit.Uwp.UI.Controls.HeaderedTextBlock),
b =>
{
b.AddCustomAttributes(new FeatureAttribute(typeof(HeaderedTextBlockDefaults)));
b.AddCustomAttributes(nameof(HeaderedTextBlock.HeaderTemplate),
new CategoryAttribute(Properties.Resources.CategoryAppearance),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(nameof(HeaderedTextBlock.TextStyle),
new CategoryAttribute(Properties.Resources.CategoryAppearance),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(nameof(HeaderedTextBlock.Header), new CategoryAttribute(Properties.Resources.CategoryCommon));
b.AddCustomAttributes(nameof(HeaderedTextBlock.Text), new CategoryAttribute(Properties.Resources.CategoryCommon));
b.AddCustomAttributes(nameof(HeaderedTextBlock.Orientation), new CategoryAttribute(Properties.Resources.CategoryAppearance));
b.AddCustomAttributes(nameof(HeaderedTextBlock.HideTextIfEmpty), new CategoryAttribute(Properties.Resources.CategoryAppearance));
b.AddCustomAttributes(new ToolboxCategoryAttribute(ToolboxCategoryPaths.Toolkit, false));
}
);
}
}
}

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

@ -85,7 +85,6 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="TabViewItemMetadata.cs" />
<Compile Include="BladeItemMetadata.cs" />
<Compile Include="BladeViewMetadata.cs" />
<Compile Include="CarouselMetadata.cs" />
@ -93,7 +92,6 @@
<Compile Include="AdaptiveGridViewMetadata.cs" />
<Compile Include="ExpanderMetadata.cs" />
<Compile Include="GridSplitterMetadata.cs" />
<Compile Include="HeaderedTextBlockMetadata.cs" />
<Compile Include="ImageExMetadata.cs" />
<Compile Include="InAppNotificationMetadata.cs" />
<Compile Include="LayoutTransitionControlMetadata.cs" />
@ -104,7 +102,6 @@
<Compile Include="MetadataRegistration.cs" />
<Compile Include="Common\MetadataRegistrationBase.cs" />
<Compile Include="Common\PlatformTypes.cs" />
<Compile Include="TabViewMetadata.cs" />
<Compile Include="OrbitViewMetadata.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>

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

@ -1,43 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Toolkit.Uwp.UI.Controls.Design.Common;
using Microsoft.Windows.Design;
using Microsoft.Windows.Design.Features;
using Microsoft.Windows.Design.Metadata;
using Microsoft.Windows.Design.Model;
using Microsoft.Windows.Design.PropertyEditing;
using System.ComponentModel;
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
{
internal class TabViewItemMetadata : AttributeTableBuilder
{
public TabViewItemMetadata()
: base()
{
AddCallback(typeof(TabViewItem),
b =>
{
b.AddCustomAttributes(nameof(TabViewItem.Header),
new CategoryAttribute(Properties.Resources.CategoryCommon)
);
b.AddCustomAttributes(nameof(TabViewItem.HeaderTemplate),
new CategoryAttribute(Properties.Resources.CategoryCommon),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(nameof(TabViewItem.IsClosable),
new CategoryAttribute(Properties.Resources.CategoryCommon)
);
b.AddCustomAttributes(nameof(TabViewItem.Icon),
new CategoryAttribute(Properties.Resources.CategoryCommon)
);
b.AddCustomAttributes(new ToolboxCategoryAttribute(ToolboxCategoryPaths.Toolkit, false));
}
);
}
}
}

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

@ -1,54 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Toolkit.Uwp.UI.Controls.Design.Common;
using Microsoft.Windows.Design;
using Microsoft.Windows.Design.Metadata;
using Microsoft.Windows.Design.PropertyEditing;
using System.ComponentModel;
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
{
internal class TabViewMetadata : AttributeTableBuilder
{
public TabViewMetadata()
: base()
{
AddCallback(typeof(Microsoft.Toolkit.Uwp.UI.Controls.TabView),
b =>
{
// Layout
b.AddCustomAttributes(nameof(TabView.TabWidthBehavior), new CategoryAttribute(Properties.Resources.CategoryLayout));
b.AddCustomAttributes(nameof(TabView.SelectedTabWidth), new CategoryAttribute(Properties.Resources.CategoryLayout));
b.AddCustomAttributes(nameof(TabView.IsCloseButtonOverlay), new CategoryAttribute(Properties.Resources.CategoryLayout));
// Interactions
b.AddCustomAttributes(nameof(TabView.CanCloseTabs), new CategoryAttribute(Properties.Resources.CategoryCommon));
// Templates
b.AddCustomAttributes(nameof(TabView.ItemHeaderTemplate),
new CategoryAttribute(Properties.Resources.CategoryCommon),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(nameof(TabView.TabActionHeader), new CategoryAttribute(Properties.Resources.CategoryCommon));
b.AddCustomAttributes(nameof(TabView.TabActionHeaderTemplate),
new CategoryAttribute(Properties.Resources.CategoryCommon),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(nameof(TabView.TabEndHeader), new CategoryAttribute(Properties.Resources.CategoryCommon));
b.AddCustomAttributes(nameof(TabView.TabEndHeaderTemplate),
new CategoryAttribute(Properties.Resources.CategoryCommon),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(nameof(TabView.TabStartHeader), new CategoryAttribute(Properties.Resources.CategoryCommon));
b.AddCustomAttributes(nameof(TabView.TabStartHeaderTemplate),
new CategoryAttribute(Properties.Resources.CategoryCommon),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(new ToolboxCategoryAttribute(ToolboxCategoryPaths.Toolkit, false));
}
);
}
}
}

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

@ -1,172 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Defines the properties for the <see cref="HeaderedTextBlock"/> control.
/// </summary>
public partial class HeaderedTextBlock
{
/// <summary>
/// Defines the <see cref="HeaderTemplate"/> dependency property.
/// </summary>
public static readonly DependencyProperty HeaderTemplateProperty = DependencyProperty.Register(
nameof(HeaderTemplate),
typeof(DataTemplate),
typeof(HeaderedTextBlock),
new PropertyMetadata(null));
/// <summary>
/// Defines the <see cref="TextStyle"/> dependency property.
/// </summary>
public static readonly DependencyProperty TextStyleProperty = DependencyProperty.Register(
nameof(TextStyle),
typeof(Style),
typeof(HeaderedTextBlock),
new PropertyMetadata(null));
/// <summary>
/// Defines the <see cref="Header"/> dependency property.
/// </summary>
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
nameof(Header),
typeof(string),
typeof(HeaderedTextBlock),
new PropertyMetadata(null, (d, e) => { ((HeaderedTextBlock)d).UpdateVisibility(); }));
/// <summary>
/// Defines the <see cref="Text"/> dependency property.
/// </summary>
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
nameof(Text),
typeof(string),
typeof(HeaderedTextBlock),
new PropertyMetadata(null, (d, e) => { ((HeaderedTextBlock)d).UpdateVisibility(); }));
/// <summary>
/// Defines the <see cref="Orientation"/> dependency property.
/// </summary>
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
nameof(Orientation),
typeof(Orientation),
typeof(HeaderedTextBlock),
new PropertyMetadata(Orientation.Vertical, (d, e) => { ((HeaderedTextBlock)d).UpdateForOrientation((Orientation)e.NewValue); }));
/// <summary>
/// Defines the <see cref="HideTextIfEmpty"/> dependency property.
/// </summary>
public static readonly DependencyProperty HideTextIfEmptyProperty = DependencyProperty.Register(
nameof(HideTextIfEmpty),
typeof(bool),
typeof(HeaderedTextBlock),
new PropertyMetadata(false, (d, e) => { ((HeaderedTextBlock)d).UpdateVisibility(); }));
/// <summary>
/// Gets or sets the header style.
/// </summary>
public DataTemplate HeaderTemplate
{
get
{
return (DataTemplate)GetValue(HeaderTemplateProperty);
}
set
{
SetValue(HeaderTemplateProperty, value);
}
}
/// <summary>
/// Gets or sets the text style.
/// </summary>
public Style TextStyle
{
get
{
return (Style)GetValue(TextStyleProperty);
}
set
{
SetValue(TextStyleProperty, value);
}
}
/// <summary>
/// Gets or sets the header.
/// </summary>
public string Header
{
get
{
return (string)GetValue(HeaderProperty);
}
set
{
SetValue(HeaderProperty, value);
}
}
/// <summary>
/// Gets or sets the text.
/// </summary>
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
/// <summary>
/// Gets the collection of inline text elements within a Windows.UI.Xaml.Controls.TextBlock.
/// </summary>
/// <returns>
/// A collection that holds all inline text elements from the Windows.UI.Xaml.Controls.TextBlock. The default is an empty collection.</returns>
public InlineCollectionWrapper Inlines { get; } = new InlineCollectionWrapper();
/// <summary>
/// Gets or sets the orientation.
/// </summary>
public Orientation Orientation
{
get
{
return (Orientation)GetValue(OrientationProperty);
}
set
{
SetValue(OrientationProperty, value);
}
}
/// <summary>
/// Gets or sets a value indicating whether the Text TextBlock is hidden if its value is empty
/// </summary>
public bool HideTextIfEmpty
{
get
{
return (bool)GetValue(HideTextIfEmptyProperty);
}
set
{
SetValue(HideTextIfEmptyProperty, value);
}
}
}
}

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

@ -1,76 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Defines a control for providing a header for read-only text.
/// </summary>
[TemplatePart(Name = "HeaderContentPresenter", Type = typeof(ContentPresenter))]
[ContentProperty(Name = nameof(Inlines))]
[Obsolete("The HeaderedTextBlock has been replaced with the more generic HeaderedContentControl.")]
public partial class HeaderedTextBlock : Control
{
private ContentPresenter _headerContentPresenter;
private TextBlock _textContent;
/// <summary>
/// Initializes a new instance of the <see cref="HeaderedTextBlock"/> class.
/// </summary>
public HeaderedTextBlock()
{
DefaultStyleKey = typeof(HeaderedTextBlock);
}
/// <summary>
/// Called when applying the control template.
/// </summary>
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
_headerContentPresenter = GetTemplateChild("HeaderContentPresenter") as ContentPresenter;
_textContent = GetTemplateChild("TextContent") as TextBlock;
UpdateVisibility();
Inlines.AddItemsToTextBlock(_textContent);
UpdateForOrientation(this.Orientation);
}
private void UpdateVisibility()
{
if (_headerContentPresenter != null)
{
_headerContentPresenter.Visibility = _headerContentPresenter.Content == null
? Visibility.Collapsed
: Visibility.Visible;
}
if (_textContent != null)
{
_textContent.Visibility = string.IsNullOrWhiteSpace(_textContent.Text) && HideTextIfEmpty
? Visibility.Collapsed
: Visibility.Visible;
}
}
private void UpdateForOrientation(Orientation orientationValue)
{
switch (orientationValue)
{
case Orientation.Vertical:
VisualStateManager.GoToState(this, "Vertical", true);
break;
case Orientation.Horizontal:
VisualStateManager.GoToState(this, "Horizontal", true);
break;
}
}
}
}

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

@ -1,60 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls">
<Style x:Key="HeaderedTextBlockTextStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource ApplicationForegroundThemeBrush}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="TextLineBounds" Value="TrimToBaseline" />
<Setter Property="OpticalMarginAlignment" Value="TrimSideBearings" />
<Setter Property="FontSize" Value="18" />
<Setter Property="FontWeight" Value="Light" />
<Setter Property="LineHeight" Value="28" />
</Style>
<Style TargetType="controls:HeaderedTextBlock">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Orientation" Value="Vertical" />
<Setter Property="TextStyle" Value="{ThemeResource HeaderedTextBlockTextStyle}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:HeaderedTextBlock">
<StackPanel x:Name="Panel"
Orientation="{TemplateBinding Orientation}">
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.ColumnSpan="4"
x:DeferLoadStrategy="Lazy"
AutomationProperties.AccessibilityView="Raw"
AutomationProperties.Name="Header content"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
IsHitTestVisible="False"
Visibility="Collapsed" />
<TextBlock x:Name="TextContent"
AutomationProperties.Name="Text content"
Style="{TemplateBinding TextStyle}"
Text="{TemplateBinding Text}" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="OrientationStates">
<VisualState x:Name="Vertical" />
<VisualState x:Name="Horizontal">
<VisualState.Setters>
<Setter Target="TextContent.Margin" Value="10,0,0,0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

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

@ -17,7 +17,6 @@
- GridSplitter: A the control that redistributes space between columns or rows of a Grid control.
- HeaderedContentControl: Provides a header to content.
- HeaderedItemsControl: Provides a header to items.
- HeaderedTextBlock: Provide a header for read-only text.
- ImageCropper: ImageCropper control allows user to crop image freely.
- ImageEx: Images are downloaded asynchronously showing a load indicator and can be stored in a local cache.
- InAppNotification: Show local notifications in your application.

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

@ -5,7 +5,6 @@
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=gridsplitter/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=hamburgermenu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=hamburgermenu_005Cmenuitems/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=headeredtextblock/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=imageex/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=pulltorefreshlistview/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=radialgauge/@EntryIndexedValue">True</s:Boolean>

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

@ -213,14 +213,6 @@
<value>Notification</value>
<comment>The landmark name for the InAppNotification control. It is said by the narrator when using landmark navigation.</comment>
</data>
<data name="WindowsCommunityToolkit_TabView_CloseButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Close tab</value>
<comment>Narrator Resource for TabView Close Button.</comment>
</data>
<data name="WindowsCommunityToolkit_TabView_CloseButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Close tab</value>
<comment>Tooltip for TabView Close Button.</comment>
</data>
<data name="WindowsCommunityToolkit_TokenizingTextBoxItem_MenuFlyout_Remove" xml:space="preserve">
<value>Remove</value>
<comment>Label for TokenizingTextBox MenuFlyout 'Remove' option.</comment>

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

@ -1,36 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.ComponentModel;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Event arguments for <see cref="TabView.TabClosing"/> event.
/// </summary>
public class TabClosingEventArgs : CancelEventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="TabClosingEventArgs"/> class.
/// </summary>
/// <param name="item">Item being closed.</param>
/// <param name="tab"><see cref="TabViewItem"/> container being closed.</param>
public TabClosingEventArgs(object item, TabViewItem tab)
{
Item = item;
Tab = tab;
}
/// <summary>
/// Gets the Item being closed.
/// </summary>
public object Item { get; private set; }
/// <summary>
/// Gets the Tab being closed.
/// </summary>
public TabViewItem Tab { get; private set; }
}
}

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

@ -1,35 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// A class used by the <see cref="TabView"/> TabDraggedOutside Event
/// </summary>
public class TabDraggedOutsideEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="TabDraggedOutsideEventArgs"/> class.
/// </summary>
/// <param name="item">data context of element dragged</param>
/// <param name="tab"><see cref="TabViewItem"/> container being dragged.</param>
public TabDraggedOutsideEventArgs(object item, TabViewItem tab)
{
Item = item;
Tab = tab;
}
/// <summary>
/// Gets or sets the Item/Data Context of the item being dragged outside of the <see cref="TabView"/>.
/// </summary>
public object Item { get; set; }
/// <summary>
/// Gets the Tab being dragged outside of the <see cref="TabView"/>.
/// </summary>
public TabViewItem Tab { get; private set; }
}
}

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

@ -1,221 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Linq;
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// TabView methods related to calculating the width of the <see cref="TabViewItem"/> Headers.
/// </summary>
public partial class TabView
{
// Attached property for storing widths of tabs if set by other means during layout.
private static double GetOriginalWidth(TabViewItem obj)
{
return (double)obj.GetValue(OriginalWidthProperty);
}
private static void SetOriginalWidth(TabViewItem obj, double value)
{
obj.SetValue(OriginalWidthProperty, value);
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
private static readonly DependencyProperty OriginalWidthProperty =
DependencyProperty.RegisterAttached("OriginalWidth", typeof(double), typeof(TabView), new PropertyMetadata(null));
private static void OnLayoutEffectingPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
var tabview = sender as TabView;
if (tabview != null && tabview._hasLoaded)
{
tabview.TabView_SizeChanged(tabview, null);
}
}
private void TabView_SizeChanged(object sender, SizeChangedEventArgs e)
{
// We need to do this calculation here in Size Changed as the
// Columns don't have their Actual Size calculated in Measure or Arrange.
if (_hasLoaded && _tabViewContainer != null)
{
// Look for our special columns to calculate size of other 'stuff'
var taken = _tabViewContainer.ColumnDefinitions.Sum(cd => GetIgnoreColumn(cd) ? 0 : cd.ActualWidth);
// Get the column we want to work on for available space
var tabc = _tabViewContainer.ColumnDefinitions.FirstOrDefault(cd => GetConstrainColumn(cd));
if (tabc != null)
{
var available = ActualWidth - taken;
var required = 0.0;
var mintabwidth = double.MaxValue;
if (TabWidthBehavior == TabWidthMode.Actual)
{
if (_tabScroller != null)
{
// If we have a scroll container, get its size.
required = _tabScroller.ExtentWidth;
}
// Restore original widths
foreach (var item in Items)
{
var tab = ContainerFromItem(item) as TabViewItem;
if (tab == null)
{
continue; // container not generated yet
}
if (tab.ReadLocalValue(OriginalWidthProperty) != DependencyProperty.UnsetValue)
{
tab.Width = GetOriginalWidth(tab);
}
}
}
else if (available > 0)
{
// Calculate the width for each tab from the provider and determine how much space they take.
foreach (var item in Items)
{
var tab = ContainerFromItem(item) as TabViewItem;
if (tab == null)
{
continue; // container not generated yet
}
mintabwidth = Math.Min(mintabwidth, tab.MinWidth);
double width = double.NaN;
switch (TabWidthBehavior)
{
case TabWidthMode.Equal:
width = ProvideEqualWidth(tab, item, available);
break;
case TabWidthMode.Compact:
width = ProvideCompactWidth(tab, item, available);
break;
}
if (tab.ReadLocalValue(OriginalWidthProperty) == DependencyProperty.UnsetValue)
{
SetOriginalWidth(tab, tab.Width);
}
if (width > double.Epsilon)
{
tab.Width = width;
required += Math.Max(Math.Min(width, tab.MaxWidth), tab.MinWidth);
}
else
{
tab.Width = GetOriginalWidth(tab);
required += tab.ActualWidth;
}
}
}
else
{
// Fix negative bounds.
available = 0.0;
// Still need to determine a 'minimum' width (if available)
// TODO: Consolidate this logic with above better?
foreach (var item in Items)
{
var tab = ContainerFromItem(item) as TabViewItem;
if (tab == null)
{
continue; // container not generated yet
}
mintabwidth = Math.Min(mintabwidth, tab.MinWidth);
}
}
if (!(mintabwidth < double.MaxValue))
{
mintabwidth = 0.0; // No Containers, no visual, 0 size.
}
if (available > mintabwidth)
{
// Constrain the column based on our required and available space
tabc.MaxWidth = available;
}
//// TODO: If it's less, should we move the selected tab to only be the one shown by default?
if (available <= mintabwidth || Math.Abs(available - mintabwidth) < double.Epsilon)
{
tabc.Width = new GridLength(mintabwidth);
}
else if (required >= available)
{
// Fix size as we don't have enough space for all the tabs.
tabc.Width = new GridLength(available);
}
else
{
// We haven't filled up our space, so we want to expand to take as much as needed.
tabc.Width = GridLength.Auto;
}
}
}
}
private double ProvideEqualWidth(TabViewItem tab, object item, double availableWidth)
{
if (double.IsNaN(SelectedTabWidth))
{
if (Items.Count <= 1)
{
return availableWidth;
}
return Math.Max(tab.MinWidth, availableWidth / Items.Count);
}
else if (Items.Count() <= 1)
{
// Default case of a single tab, make it full size.
return Math.Min(SelectedTabWidth, availableWidth);
}
else
{
var width = (availableWidth - SelectedTabWidth) / (Items.Count - 1);
// Constrain between Min and Selected (Max)
if (width < tab.MinWidth)
{
width = tab.MinWidth;
}
else if (width > SelectedTabWidth)
{
width = SelectedTabWidth;
}
// If it's selected make it full size, otherwise whatever the size should be.
return tab.IsSelected
? Math.Min(SelectedTabWidth, availableWidth)
: width;
}
}
private double ProvideCompactWidth(TabViewItem tab, object item, double availableWidth)
{
// If we're selected and have a value for that, then just return that.
if (tab.IsSelected && !double.IsNaN(SelectedTabWidth))
{
return SelectedTabWidth;
}
// Otherwise use min size.
return tab.MinWidth;
}
}
}

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

@ -1,115 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Reflection;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls.Primitives;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// TabView methods related to tracking Items and ItemsSource changes.
/// </summary>
public partial class TabView
{
// Temporary tracking of previous collections for removing events.
private MethodInfo _removeItemsSourceMethod;
/// <inheritdoc/>
protected override void OnItemsChanged(object e)
{
IVectorChangedEventArgs args = (IVectorChangedEventArgs)e;
base.OnItemsChanged(e);
if (args.CollectionChange == CollectionChange.ItemRemoved && SelectedIndex == -1)
{
// If we remove the selected item we should select the previous item
int startIndex = (int)args.Index + 1;
if (startIndex > Items.Count)
{
startIndex = 0;
}
SelectedIndex = FindNextTabIndex(startIndex, -1);
}
// Update Sizing (in case there are less items now)
TabView_SizeChanged(this, null);
}
private void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e)
{
var action = (CollectionChange)e.Action;
if (action == CollectionChange.Reset)
{
// Reset collection to reload later.
_hasLoaded = false;
}
}
private void SetInitialSelection()
{
if (SelectedItem == null)
{
// If we have an index, but didn't get the selection, make the selection
if (SelectedIndex >= 0 && SelectedIndex < Items.Count)
{
SelectedItem = Items[SelectedIndex];
}
// Otherwise, select the first item by default
else if (Items.Count >= 1)
{
SelectedItem = Items[0];
}
}
}
// Finds the next visible & enabled tab index.
private int FindNextTabIndex(int startIndex, int direction)
{
int index = startIndex;
if (direction != 0)
{
for (int i = 0; i < Items.Count; i++)
{
index += direction;
if (index >= Items.Count)
{
index = 0;
}
else if (index < 0)
{
index = Items.Count - 1;
}
var tabItem = ContainerFromIndex(index) as TabViewItem;
if (tabItem != null && tabItem.IsEnabled && tabItem.Visibility == Visibility.Visible)
{
break;
}
}
}
return index;
}
private void ItemsSource_PropertyChanged(DependencyObject sender, DependencyProperty dp)
{
// Use reflection to store a 'Remove' method of any possible collection in ItemsSource
// Cache for efficiency later.
if (ItemsSource != null)
{
_removeItemsSourceMethod = ItemsSource.GetType().GetMethod("Remove");
}
else
{
_removeItemsSourceMethod = null;
}
}
}
}

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

@ -1,245 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// TabView properties.
/// </summary>
public partial class TabView
{
/// <summary>
/// Gets or sets the content to appear to the left or above the tab strip.
/// </summary>
public object TabStartHeader
{
get { return (object)GetValue(TabStartHeaderProperty); }
set { SetValue(TabStartHeaderProperty, value); }
}
/// <summary>
/// Identifies the <see cref="TabStartHeader"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="TabStartHeader"/> dependency property.</returns>
public static readonly DependencyProperty TabStartHeaderProperty =
DependencyProperty.Register(nameof(TabStartHeader), typeof(object), typeof(TabView), new PropertyMetadata(null, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets the <see cref="DataTemplate"/> for the <see cref="TabStartHeader"/>.
/// </summary>
public DataTemplate TabStartHeaderTemplate
{
get { return (DataTemplate)GetValue(TabStartHeaderTemplateProperty); }
set { SetValue(TabStartHeaderTemplateProperty, value); }
}
/// <summary>
/// Identifies the <see cref="TabStartHeaderTemplate"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="TabStartHeaderTemplate"/> dependency property.</returns>
public static readonly DependencyProperty TabStartHeaderTemplateProperty =
DependencyProperty.Register(nameof(TabStartHeaderTemplate), typeof(DataTemplate), typeof(TabView), new PropertyMetadata(null, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets the content to appear next to the tab strip.
/// </summary>
public object TabActionHeader
{
get { return (object)GetValue(TabActionHeaderProperty); }
set { SetValue(TabActionHeaderProperty, value); }
}
/// <summary>
/// Identifies the <see cref="TabActionHeader"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="TabActionHeader"/> dependency property.</returns>
public static readonly DependencyProperty TabActionHeaderProperty =
DependencyProperty.Register(nameof(TabActionHeader), typeof(object), typeof(TabView), new PropertyMetadata(null, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets the <see cref="DataTemplate"/> for the <see cref="TabActionHeader"/>.
/// </summary>
public DataTemplate TabActionHeaderTemplate
{
get { return (DataTemplate)GetValue(TabActionHeaderTemplateProperty); }
set { SetValue(TabActionHeaderTemplateProperty, value); }
}
/// <summary>
/// Identifies the <see cref="TabActionHeaderTemplate"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="TabActionHeaderTemplate"/> dependency property.</returns>
public static readonly DependencyProperty TabActionHeaderTemplateProperty =
DependencyProperty.Register(nameof(TabActionHeaderTemplate), typeof(DataTemplate), typeof(TabView), new PropertyMetadata(null, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets the content to appear to the right or below the tab strip.
/// </summary>
public object TabEndHeader
{
get { return (object)GetValue(TabEndHeaderProperty); }
set { SetValue(TabEndHeaderProperty, value); }
}
/// <summary>
/// Identifies the <see cref="TabEndHeader"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="TabEndHeader"/> dependency property.</returns>
public static readonly DependencyProperty TabEndHeaderProperty =
DependencyProperty.Register(nameof(TabEndHeader), typeof(object), typeof(TabView), new PropertyMetadata(null, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets the <see cref="DataTemplate"/> for the <see cref="TabEndHeader"/>.
/// </summary>
public DataTemplate TabEndHeaderTemplate
{
get { return (DataTemplate)GetValue(TabEndHeaderTemplateProperty); }
set { SetValue(TabEndHeaderTemplateProperty, value); }
}
/// <summary>
/// Identifies the <see cref="TabEndHeaderTemplate"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="TabEndHeaderTemplate"/> dependency property.</returns>
public static readonly DependencyProperty TabEndHeaderTemplateProperty =
DependencyProperty.Register(nameof(TabEndHeaderTemplate), typeof(DataTemplate), typeof(TabView), new PropertyMetadata(null, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets the default <see cref="DataTemplate"/> for the <see cref="TabViewItem.HeaderTemplate"/>.
/// </summary>
public DataTemplate ItemHeaderTemplate
{
get { return (DataTemplate)GetValue(ItemHeaderTemplateProperty); }
set { SetValue(ItemHeaderTemplateProperty, value); }
}
/// <summary>
/// Identifies the <see cref="ItemHeaderTemplate"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="TabStartHeaderTemplate"/> dependency property.</returns>
public static readonly DependencyProperty ItemHeaderTemplateProperty =
DependencyProperty.Register(nameof(ItemHeaderTemplate), typeof(DataTemplate), typeof(TabView), new PropertyMetadata(null, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets a value indicating whether by default a Tab can be closed or not if no value to <see cref="TabViewItem.IsClosable"/> is provided.
/// </summary>
public bool CanCloseTabs
{
get { return (bool)GetValue(CanCloseTabsProperty); }
set { SetValue(CanCloseTabsProperty, value); }
}
/// <summary>
/// Identifies the <see cref="CanCloseTabs"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="CanCloseTabs"/> dependency property.</returns>
public static readonly DependencyProperty CanCloseTabsProperty =
DependencyProperty.Register(nameof(CanCloseTabs), typeof(bool), typeof(TabView), new PropertyMetadata(false, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets a value indicating whether a <see cref="TabViewItem"/> Close Button should be included in layout calculations.
/// </summary>
public bool IsCloseButtonOverlay
{
get { return (bool)GetValue(IsCloseButtonOverlayProperty); }
set { SetValue(IsCloseButtonOverlayProperty, value); }
}
/// <summary>
/// Identifies the <see cref="IsCloseButtonOverlay"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="IsCloseButtonOverlay"/> dependency property.</returns>
public static readonly DependencyProperty IsCloseButtonOverlayProperty =
DependencyProperty.Register(nameof(IsCloseButtonOverlay), typeof(bool), typeof(TabView), new PropertyMetadata(false, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets a value indicating the size of the selected tab. By default this is set to Auto and the selected tab size doesn't change.
/// </summary>
public double SelectedTabWidth
{
get { return (double)GetValue(SelectedTabWidthProperty); }
set { SetValue(SelectedTabWidthProperty, value); }
}
/// <summary>
/// Identifies the <see cref="SelectedTabWidth"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="SelectedTabWidth"/> dependency property.</returns>
public static readonly DependencyProperty SelectedTabWidthProperty =
DependencyProperty.Register(nameof(SelectedTabWidth), typeof(double), typeof(TabView), new PropertyMetadata(double.NaN, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets or sets the current <see cref="TabWidthMode"/> which determines how tab headers' width behave.
/// </summary>
public TabWidthMode TabWidthBehavior
{
get { return (TabWidthMode)GetValue(TabWidthBehaviorProperty); }
set { SetValue(TabWidthBehaviorProperty, value); }
}
/// <summary>
/// Identifies the <see cref="TabWidthBehavior"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="TabWidthBehavior"/> dependency property.</returns>
public static readonly DependencyProperty TabWidthBehaviorProperty =
DependencyProperty.Register(nameof(TabWidthBehavior), typeof(TabWidthMode), typeof(TabView), new PropertyMetadata(TabWidthMode.Actual, OnLayoutEffectingPropertyChanged));
/// <summary>
/// Gets the attached property value to indicate if this grid column should be ignored when calculating header sizes.
/// </summary>
/// <param name="obj">Grid Column.</param>
/// <returns>Boolean indicating if this column is ignored by TabViewHeader logic.</returns>
public static bool GetIgnoreColumn(ColumnDefinition obj)
{
return (bool)obj.GetValue(IgnoreColumnProperty);
}
/// <summary>
/// Sets the attached property value for <see cref="IgnoreColumnProperty"/>
/// </summary>
/// <param name="obj">Grid Column.</param>
/// <param name="value">Boolean value</param>
public static void SetIgnoreColumn(ColumnDefinition obj, bool value)
{
obj.SetValue(IgnoreColumnProperty, value);
}
/// <summary>
/// Identifies the <see cref="IgnoreColumnProperty"/> attached property.
/// </summary>
/// <returns>The identifier for the IgnoreColumn attached property.</returns>
public static readonly DependencyProperty IgnoreColumnProperty =
DependencyProperty.RegisterAttached("IgnoreColumn", typeof(bool), typeof(TabView), new PropertyMetadata(false));
/// <summary>
/// Gets the attached value indicating this column should be restricted for the <see cref="TabViewItem"/> headers.
/// </summary>
/// <param name="obj">Grid Column.</param>
/// <returns>True if this column should be constrained.</returns>
public static bool GetConstrainColumn(ColumnDefinition obj)
{
return (bool)obj.GetValue(ConstrainColumnProperty);
}
/// <summary>
/// Sets the attached property value for the <see cref="ConstrainColumnProperty"/>
/// </summary>
/// <param name="obj">Grid Column.</param>
/// <param name="value">Boolean value.</param>
public static void SetConstrainColumn(ColumnDefinition obj, bool value)
{
obj.SetValue(ConstrainColumnProperty, value);
}
/// <summary>
/// Identifies the <see cref="ConstrainColumnProperty"/> attached property.
/// </summary>
/// <returns>The identifier for the ConstrainColumn attached property.</returns>
public static readonly DependencyProperty ConstrainColumnProperty =
DependencyProperty.RegisterAttached("ConstrainColumn", typeof(bool), typeof(TabView), new PropertyMetadata(false));
}
}

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

@ -1,320 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.ComponentModel;
using System.Linq;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Windows.ApplicationModel.DataTransfer;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// TabView is a control for displaying a set of tabs and their content.
/// </summary>
[Obsolete("Please migrate to the TabView control from WinUI, this control will be removed in a future release. https://aka.ms/winui")]
[TemplatePart(Name = TabContentPresenterName, Type = typeof(ContentPresenter))]
[TemplatePart(Name = TabViewContainerName, Type = typeof(Grid))]
[TemplatePart(Name = TabsItemsPresenterName, Type = typeof(ItemsPresenter))]
[TemplatePart(Name = TabsScrollViewerName, Type = typeof(ScrollViewer))]
[TemplatePart(Name = TabsScrollBackButtonName, Type = typeof(ButtonBase))]
[TemplatePart(Name = TabsScrollForwardButtonName, Type = typeof(ButtonBase))]
public partial class TabView : ListViewBase
{
private const int ScrollAmount = 50; // TODO: Should this be based on TabWidthMode
private const string TabContentPresenterName = "TabContentPresenter";
private const string TabViewContainerName = "TabViewContainer";
private const string TabsItemsPresenterName = "TabsItemsPresenter";
private const string TabsScrollViewerName = "ScrollViewer";
private const string TabsScrollBackButtonName = "ScrollBackButton";
private const string TabsScrollForwardButtonName = "ScrollForwardButton";
private ContentPresenter _tabContentPresenter;
private Grid _tabViewContainer;
private ItemsPresenter _tabItemsPresenter;
private ScrollViewer _tabScroller;
private ButtonBase _tabScrollBackButton;
private ButtonBase _tabScrollForwardButton;
private bool _hasLoaded;
private bool _isDragging;
/// <summary>
/// Initializes a new instance of the <see cref="TabView"/> class.
/// </summary>
public TabView()
{
DefaultStyleKey = typeof(TabView);
// Container Generation Hooks
RegisterPropertyChangedCallback(ItemsSourceProperty, ItemsSource_PropertyChanged);
ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
// Drag and Layout Hooks
DragItemsStarting += TabView_DragItemsStarting;
DragItemsCompleted += TabView_DragItemsCompleted;
SizeChanged += TabView_SizeChanged;
// Selection Hook
SelectionChanged += TabView_SelectionChanged;
}
/// <summary>
/// Occurs when a tab is dragged by the user outside of the <see cref="TabView"/>. Generally, this paradigm is used to create a new-window with the torn-off tab.
/// The creation and handling of the new-window is left to the app's developer.
/// </summary>
public event EventHandler<TabDraggedOutsideEventArgs> TabDraggedOutside;
/// <summary>
/// Occurs when a tab's Close button is clicked. Set <see cref="CancelEventArgs.Cancel"/> to true to prevent automatic Tab Closure.
/// </summary>
public event EventHandler<TabClosingEventArgs> TabClosing;
/// <inheritdoc/>
protected override DependencyObject GetContainerForItemOverride() => new TabViewItem();
/// <inheritdoc/>
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is TabViewItem;
}
/// <inheritdoc/>
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (_tabItemsPresenter != null)
{
_tabItemsPresenter.SizeChanged -= TabView_SizeChanged;
}
if (_tabScroller != null)
{
_tabScroller.Loaded -= ScrollViewer_Loaded;
}
_tabContentPresenter = GetTemplateChild(TabContentPresenterName) as ContentPresenter;
_tabViewContainer = GetTemplateChild(TabViewContainerName) as Grid;
_tabItemsPresenter = GetTemplateChild(TabsItemsPresenterName) as ItemsPresenter;
_tabScroller = GetTemplateChild(TabsScrollViewerName) as ScrollViewer;
if (_tabItemsPresenter != null)
{
_tabItemsPresenter.SizeChanged += TabView_SizeChanged;
}
if (_tabScroller != null)
{
_tabScroller.Loaded += ScrollViewer_Loaded;
}
}
private void ScrollViewer_Loaded(object sender, RoutedEventArgs e)
{
_tabScroller.Loaded -= ScrollViewer_Loaded;
if (_tabScrollBackButton != null)
{
_tabScrollBackButton.Click -= ScrollTabBackButton_Click;
}
if (_tabScrollForwardButton != null)
{
_tabScrollForwardButton.Click -= ScrollTabForwardButton_Click;
}
_tabScrollBackButton = _tabScroller.FindDescendantByName(TabsScrollBackButtonName) as ButtonBase;
_tabScrollForwardButton = _tabScroller.FindDescendantByName(TabsScrollForwardButtonName) as ButtonBase;
if (_tabScrollBackButton != null)
{
_tabScrollBackButton.Click += ScrollTabBackButton_Click;
}
if (_tabScrollForwardButton != null)
{
_tabScrollForwardButton.Click += ScrollTabForwardButton_Click;
}
}
private void ScrollTabBackButton_Click(object sender, RoutedEventArgs e)
{
_tabScroller.ChangeView(Math.Max(0, _tabScroller.HorizontalOffset - ScrollAmount), null, null);
}
private void ScrollTabForwardButton_Click(object sender, RoutedEventArgs e)
{
_tabScroller.ChangeView(Math.Min(_tabScroller.ScrollableWidth, _tabScroller.HorizontalOffset + ScrollAmount), null, null);
}
private void TabView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_isDragging)
{
// Skip if we're dragging, we'll reset when we're done.
return;
}
if (_tabContentPresenter != null)
{
if (SelectedItem == null)
{
_tabContentPresenter.Content = null;
_tabContentPresenter.ContentTemplate = null;
}
else
{
if (ContainerFromItem(SelectedItem) is TabViewItem container)
{
_tabContentPresenter.Content = container.Content;
_tabContentPresenter.ContentTemplate = container.ContentTemplate;
}
}
}
// If our width can be effected by the selection, need to run algorithm.
if (!double.IsNaN(SelectedTabWidth))
{
TabView_SizeChanged(sender, null);
}
}
/// <inheritdoc/>
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var tabitem = element as TabViewItem;
tabitem.Loaded -= TabViewItem_Loaded;
tabitem.Closing -= TabViewItem_Closing;
tabitem.Loaded += TabViewItem_Loaded;
tabitem.Closing += TabViewItem_Closing;
if (tabitem.Header == null)
{
tabitem.Header = item;
}
if (tabitem.HeaderTemplate == null)
{
var headertemplatebinding = new Binding()
{
Source = this,
Path = new PropertyPath(nameof(ItemHeaderTemplate)),
Mode = BindingMode.OneWay
};
tabitem.SetBinding(TabViewItem.HeaderTemplateProperty, headertemplatebinding);
}
if (tabitem.IsClosable != true && tabitem.ReadLocalValue(TabViewItem.IsClosableProperty) == DependencyProperty.UnsetValue)
{
var iscloseablebinding = new Binding()
{
Source = this,
Path = new PropertyPath(nameof(CanCloseTabs)),
Mode = BindingMode.OneWay,
};
tabitem.SetBinding(TabViewItem.IsClosableProperty, iscloseablebinding);
}
}
private void TabViewItem_Loaded(object sender, RoutedEventArgs e)
{
var tabitem = sender as TabViewItem;
tabitem.Loaded -= TabViewItem_Loaded;
// Only need to do this once.
if (!_hasLoaded)
{
_hasLoaded = true;
// Need to set a tab's selection on load, otherwise ListView resets to null.
SetInitialSelection();
// Need to make sure ContentPresenter is set to content based on selection.
TabView_SelectionChanged(this, null);
// Need to make sure we've registered our removal method.
ItemsSource_PropertyChanged(this, null);
// Make sure we complete layout now.
TabView_SizeChanged(this, null);
}
}
private void TabViewItem_Closing(object sender, TabClosingEventArgs e)
{
var item = ItemFromContainer(e.Tab);
var args = new TabClosingEventArgs(item, e.Tab);
TabClosing?.Invoke(this, args);
if (!args.Cancel)
{
if (ItemsSource != null)
{
_removeItemsSourceMethod?.Invoke(ItemsSource, new object[] { item });
}
else
{
Items.Remove(item);
}
}
}
private void TabView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
// Keep track of drag so we don't modify content until done.
_isDragging = true;
}
private void TabView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
{
_isDragging = false;
// args.DropResult == None when outside of area (e.g. create new window)
if (args.DropResult == DataPackageOperation.None)
{
var item = args.Items.FirstOrDefault();
var tab = ContainerFromItem(item) as TabViewItem;
if (tab == null && item is FrameworkElement fe)
{
tab = fe.FindParent<TabViewItem>();
}
if (tab == null)
{
// We still don't have a TabViewItem, most likely is a static TabViewItem in the template being dragged and not selected.
// This is a fallback scenario for static tabs.
// Note: This can be wrong if two TabViewItems share the exact same Content (i.e. a string), this should be unlikely in any practical scenario.
for (int i = 0; i < Items.Count; i++)
{
var tabItem = ContainerFromIndex(i) as TabViewItem;
if (ReferenceEquals(tabItem.Content, item))
{
tab = tabItem;
break;
}
}
}
TabDraggedOutside?.Invoke(this, new TabDraggedOutsideEventArgs(item, tab));
}
else
{
// If dragging the active tab, there's an issue with the CP blanking.
TabView_SelectionChanged(this, null);
}
}
}
}

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

@ -1,736 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
xmlns:ex="using:Microsoft.Toolkit.Uwp.UI.Extensions"
xmlns:local="using:Microsoft.Toolkit.Uwp.UI.Controls">
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="TabViewBackground"
Color="{StaticResource SystemChromeLowColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundSelected"
Color="{StaticResource SystemChromeLowColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundPointerOver"
Color="{StaticResource SystemChromeLowColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundPressed"
Color="{StaticResource SystemChromeLowColor}" />
<StaticResource x:Key="TabViewItemHeaderBackground"
ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TabViewSelectionIndicatorForeground"
ResourceKey="SystemControlForegroundAccentBrush" />
<StaticResource x:Key="TabViewItemHeaderForeground"
ResourceKey="SystemControlForegroundBaseMediumBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundPressed"
ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundSelected"
ResourceKey="SystemControlForegroundBaseHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundPointerOver"
ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundDisabled"
ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TabViewItemHeaderRevealBorderBrush"
ResourceKey="SystemControlBackgroundTransparentRevealBorderBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="TabViewBackground"
Color="{StaticResource SystemChromeLowColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundSelected"
Color="{StaticResource SystemChromeLowColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundPointerOver"
Color="{StaticResource SystemChromeLowColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundPressed"
Color="{StaticResource SystemChromeLowColor}" />
<StaticResource x:Key="TabViewItemHeaderBackground"
ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TabViewSelectionIndicatorForeground"
ResourceKey="SystemControlForegroundAccentBrush" />
<StaticResource x:Key="TabViewItemHeaderForeground"
ResourceKey="SystemControlForegroundBaseMediumBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundPressed"
ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundSelected"
ResourceKey="SystemControlForegroundBaseHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundPointerOver"
ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundDisabled"
ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TabViewItemHeaderRevealBorderBrush"
ResourceKey="SystemControlBackgroundTransparentRevealBorderBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="TabViewBackground"
Color="{ThemeResource SystemChromeLowColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundSelected"
Color="{ThemeResource SystemColorHighlightColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundPointerOver"
Color="{ThemeResource SystemColorHighlightColor}" />
<SolidColorBrush x:Key="TabViewItemHeaderBackgroundPressed"
Color="{ThemeResource SystemColorHighlightColor}" />
<StaticResource x:Key="TabViewItemHeaderBackground"
ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TabViewSelectionIndicatorForeground"
ResourceKey="SystemControlForegroundAccentBrush" />
<StaticResource x:Key="TabViewItemHeaderForeground"
ResourceKey="SystemControlForegroundBaseMediumBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundPressed"
ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundSelected"
ResourceKey="SystemControlForegroundBaseHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundPointerOver"
ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<StaticResource x:Key="TabViewItemHeaderForegroundDisabled"
ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TabViewItemHeaderRevealBorderBrush"
ResourceKey="SystemControlBackgroundTransparentRevealBorderBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<Thickness x:Key="TabViewItemHeaderMargin">0</Thickness>
<Thickness x:Key="TabViewItemHeaderIconMargin">0,0,8,0</Thickness>
<Thickness x:Key="TabViewItemHeaderCloseMargin">8,0,-8,0</Thickness>
<Thickness x:Key="TabViewItemHeaderBorderThickness">0,1,1,0</Thickness>
<x:Double x:Key="TabViewItemHeaderIconSize">16</x:Double>
<x:Double x:Key="TabViewItemHeaderMinWidth">48</x:Double>
<x:Double x:Key="TabViewItemHeaderMinHeight">40</x:Double>
<x:Double x:Key="TabViewItemHeaderMaxWidth">NaN</x:Double>
<x:Double x:Key="TabViewItemHeaderCloseWidth">32</x:Double>
<converters:EmptyObjectToObjectConverter x:Key="NullVisibilityConverter"
EmptyValue="Collapsed"
NotEmptyValue="Visible" />
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<!-- 65 is the size of both scroll buttons + 1 for layout rounding. -->
<converters:DoubleToVisibilityConverter x:Key="GreaterThanToleranceVisibilityConverter"
GreaterThan="65.0" />
<converters:BoolToObjectConverter x:Key="CloseCollapsingSizeConverter"
FalseValue="{StaticResource TabViewItemHeaderCloseWidth}"
TrueValue="NaN" />
<!-- Default style for compatibility with WPF migrators. -->
<Style TargetType="local:TabView">
<Setter Property="Background" Value="{ThemeResource TabViewBackground}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="TabNavigation" Value="Local" />
<Setter Property="IsSwipeEnabled" Value="False" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled" />
<Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
<!-- Need UseLayoutRounding as Width being dynamically changed in same cases to fill up an entire space, otherwise gap. -->
<Setter Property="UseLayoutRounding" Value="False" />
<Setter Property="ItemContainerTransitions">
<Setter.Value>
<TransitionCollection>
<AddDeleteThemeTransition />
<ContentThemeTransition />
<ReorderThemeTransition />
<EntranceThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<!-- Note: We have to use StackPanel here due to other issues using ItemsStackPanel or VirtualizingStackPanel -->
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template" Value="{StaticResource TabViewTemplate}" />
</Style>
<ControlTemplate x:Key="TabViewTemplate"
TargetType="local:TabView">
<Grid x:Name="TabViewContainer">
<Grid.RowDefinitions>
<!-- 0 Header -->
<RowDefinition Height="Auto" />
<!-- 1 Tabs -->
<RowDefinition Height="Auto" />
<!-- 2 Content -->
<RowDefinition Height="*" />
<!-- 3 Footer -->
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<!-- 0 TabStartHeader -->
<ColumnDefinition Width="Auto" />
<!-- 1 Tabs -->
<ColumnDefinition Width="Auto"
local:TabView.ConstrainColumn="True"
local:TabView.IgnoreColumn="True" />
<!-- 2 Reserved: Overflow Drop-down -->
<ColumnDefinition Width="Auto" />
<!-- 3 Auto Add Button -->
<ColumnDefinition Width="Auto" />
<!-- 4 Padding -->
<ColumnDefinition Width="*"
local:TabView.IgnoreColumn="True" />
<!-- 5 TabEndHeader -->
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Row="0"
Grid.ColumnSpan="6"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}" />
<ContentPresenter Grid.Row="1"
Grid.Column="0"
Content="{TemplateBinding TabStartHeader}"
ContentTemplate="{TemplateBinding TabStartHeaderTemplate}" />
<ScrollViewer x:Name="ScrollViewer"
Grid.Row="1"
Grid.Column="1"
AutomationProperties.AccessibilityView="Raw"
BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}"
Style="{StaticResource TabViewScrollViewer}"
TabNavigation="{TemplateBinding TabNavigation}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}">
<ItemsPresenter x:Name="TabsItemsPresenter"
Padding="{TemplateBinding Padding}" />
</ScrollViewer>
<ContentPresenter Grid.Row="1"
Grid.Column="3"
HorizontalAlignment="Left"
Content="{TemplateBinding TabActionHeader}"
ContentTemplate="{TemplateBinding TabActionHeaderTemplate}" />
<ContentPresenter Grid.Row="1"
Grid.Column="5"
Content="{TemplateBinding TabEndHeader}"
ContentTemplate="{TemplateBinding TabEndHeaderTemplate}" />
<ContentPresenter x:Name="TabContentPresenter"
Grid.Row="2"
Grid.ColumnSpan="6"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<ContentPresenter Grid.Row="3"
Grid.ColumnSpan="6"
Content="{TemplateBinding Footer}"
ContentTemplate="{TemplateBinding FooterTemplate}" />
</Grid>
</ControlTemplate>
<!-- Based on Style for ListViewItemExpanded Template - https://msdn.microsoft.com/en-us/library/windows/apps/mt299136.aspx -->
<ControlTemplate x:Key="TabViewItemHeaderTemplate"
TargetType="local:TabViewItem">
<Grid x:Name="LayoutRoot"
ex:FrameworkElementExtensions.AncestorType="local:TabView"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Control.IsTemplateFocusTarget="True"
FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<ScaleTransform x:Name="LayoutRootScale" />
</Grid.RenderTransform>
<Rectangle x:Name="SelectionIndicator"
Height="2"
Margin="0,-1"
VerticalAlignment="Top"
Fill="{ThemeResource TabViewSelectionIndicatorForeground}"
Opacity="0" />
<Grid Padding="{TemplateBinding Padding}">
<Grid x:Name="ContentPresenterGrid">
<Grid.RenderTransform>
<TranslateTransform x:Name="ContentPresenterTranslateTransform" />
</Grid.RenderTransform>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Modifications of default ListViewItem Template for our Tab Here -->
<Viewbox x:Name="IconBox"
MaxWidth="{ThemeResource TabViewItemHeaderIconSize}"
MaxHeight="{ThemeResource TabViewItemHeaderIconSize}"
Margin="{ThemeResource TabViewItemHeaderIconMargin}"
Visibility="{Binding Icon, Converter={StaticResource NullVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}}">
<ContentPresenter x:Name="Icon"
Content="{TemplateBinding Icon}"
Foreground="{TemplateBinding Foreground}" />
</Viewbox>
<ContentPresenter x:Name="ContentPresenter"
Grid.Column="1"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
FontWeight="{TemplateBinding FontWeight}"
OpticalMarginAlignment="TrimSideBearings" />
<!-- Use grid to toggle visibility based on IsClosable property and inner border for hover animations. -->
<Border x:Name="CloseButtonContainer"
Grid.Column="2"
Width="{Binding (ex:FrameworkElementExtensions.Ancestor).IsCloseButtonOverlay, Converter={StaticResource CloseCollapsingSizeConverter}, ElementName=LayoutRoot}"
HorizontalAlignment="Right"
Visibility="{Binding IsClosable, Converter={StaticResource BoolToVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}}">
<Border x:Name="CloseButtonBorder"
Width="{StaticResource TabViewItemHeaderCloseWidth}"
Margin="{ThemeResource TabViewItemHeaderCloseMargin}"
Background="{TemplateBinding Background}"
Visibility="Collapsed">
<Button x:Name="CloseButton"
x:Uid="/Microsoft.Toolkit.Uwp.UI.Controls/Resources/WindowsCommunityToolkit_TabView_CloseButton"
Style="{StaticResource TabViewItemCloseButtonStyle}">
&#xE711;
</Button>
</Border>
</Border>
</Grid>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="LayoutRoot.Background" Value="{ThemeResource TabViewItemHeaderBackgroundPointerOver}" />
<Setter Target="Icon.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundPointerOver}" />
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundPointerOver}" />
</VisualState.Setters>
<Storyboard>
<!-- Close Button -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButtonBorder"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButtonBorder"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="LayoutRoot.Background" Value="{ThemeResource TabViewItemHeaderBackgroundPressed}" />
<Setter Target="Icon.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundPressed}" />
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundPressed}" />
<Setter Target="SelectionIndicator.Opacity" Value="0.4" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Target="LayoutRoot.Background" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}" />
<Setter Target="Icon.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundSelected}" />
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundSelected}" />
</VisualState.Setters>
<Storyboard>
<!-- Selected Bar -->
<DoubleAnimation Storyboard.TargetName="SelectionIndicator"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<!-- Close Button -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButtonBorder"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButtonBorder"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOverSelected">
<VisualState.Setters>
<Setter Target="LayoutRoot.Background" Value="{ThemeResource TabViewItemHeaderBackgroundPointerOver}" />
<Setter Target="Icon.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundPointerOver}" />
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundPointerOver}" />
</VisualState.Setters>
<Storyboard>
<!-- Selected Bar -->
<DoubleAnimation Storyboard.TargetName="SelectionIndicator"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<!-- Close Button -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButtonBorder"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButtonBorder"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PressedSelected">
<VisualState.Setters>
<Setter Target="LayoutRoot.Background" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}" />
<Setter Target="Icon.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundPressed}" />
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundPressed}" />
</VisualState.Setters>
<Storyboard>
<!-- Selected Bar -->
<DoubleAnimation Storyboard.TargetName="SelectionIndicator"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<!-- Close Button -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButtonBorder"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButtonBorder"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DisabledStates">
<VisualState x:Name="Enabled" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="Icon.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundDisabled}" />
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundDisabled}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DataVirtualizationStates">
<VisualState x:Name="DataAvailable" />
<VisualState x:Name="DataPlaceholder" />
</VisualStateGroup>
<VisualStateGroup x:Name="ReorderHintStates">
<VisualState x:Name="NoReorderHint" />
<VisualState x:Name="BottomReorderHint">
<Storyboard>
<DragOverThemeAnimation Direction="Bottom"
ToOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
TargetName="LayoutRoot" />
</Storyboard>
</VisualState>
<VisualState x:Name="TopReorderHint">
<Storyboard>
<DragOverThemeAnimation Direction="Top"
ToOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
TargetName="LayoutRoot" />
</Storyboard>
</VisualState>
<VisualState x:Name="RightReorderHint">
<Storyboard>
<DragOverThemeAnimation Direction="Right"
ToOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
TargetName="LayoutRoot" />
</Storyboard>
</VisualState>
<VisualState x:Name="LeftReorderHint">
<Storyboard>
<DragOverThemeAnimation Direction="Left"
ToOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
TargetName="LayoutRoot" />
</Storyboard>
</VisualState>
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2"
To="NoReorderHint" />
</VisualStateGroup.Transitions>
</VisualStateGroup>
<VisualStateGroup x:Name="DragStates">
<VisualState x:Name="NotDragging" />
<VisualState x:Name="Dragging">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="LayoutRoot"
Storyboard.TargetProperty="Opacity"
To="{ThemeResource ListViewItemDragThemeOpacity}"
Duration="0" />
<DragItemThemeAnimation TargetName="LayoutRoot" />
</Storyboard>
</VisualState>
<VisualState x:Name="DraggingTarget" />
<VisualState x:Name="MultipleDraggingPrimary" />
<VisualState x:Name="MultipleDraggingSecondary" />
<VisualState x:Name="DraggedPlaceholder" />
<VisualState x:Name="Reordering">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="LayoutRoot"
Storyboard.TargetProperty="Opacity"
To="{ThemeResource ListViewItemReorderThemeOpacity}"
Duration="0:0:0.240" />
</Storyboard>
</VisualState>
<VisualState x:Name="ReorderingTarget">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="LayoutRoot"
Storyboard.TargetProperty="Opacity"
To="{ThemeResource ListViewItemReorderTargetThemeOpacity}"
Duration="0:0:0.240" />
<DoubleAnimation Storyboard.TargetName="LayoutRootScale"
Storyboard.TargetProperty="ScaleX"
To="{ThemeResource ListViewItemReorderTargetThemeScale}"
Duration="0:0:0.240" />
<DoubleAnimation Storyboard.TargetName="LayoutRootScale"
Storyboard.TargetProperty="ScaleY"
To="{ThemeResource ListViewItemReorderTargetThemeScale}"
Duration="0:0:0.240" />
</Storyboard>
</VisualState>
<VisualState x:Name="MultipleReorderingPrimary" />
<VisualState x:Name="ReorderedPlaceholder">
<Storyboard>
<FadeOutThemeAnimation TargetName="LayoutRoot" />
</Storyboard>
</VisualState>
<VisualState x:Name="DragOver">
<Storyboard>
<DropTargetItemThemeAnimation TargetName="LayoutRoot" />
</Storyboard>
</VisualState>
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2"
To="NotDragging" />
</VisualStateGroup.Transitions>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
<!-- Based on Style for Windows.UI.Xaml.Controls.ListViewItem -->
<Style TargetType="local:TabViewItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="BorderBrush" Value="{ThemeResource TabViewItemHeaderRevealBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TabViewItemHeaderBorderThickness}" />
<Setter Property="Background" Value="{ThemeResource TabViewItemHeaderBackground}" />
<Setter Property="Foreground" Value="{ThemeResource TabViewItemHeaderForeground}" />
<Setter Property="Margin" Value="{ThemeResource TabViewItemHeaderMargin}" />
<Setter Property="TabNavigation" Value="Local" />
<Setter Property="IsHoldingEnabled" Value="True" />
<Setter Property="Padding" Value="14,0" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="MinWidth" Value="{ThemeResource TabViewItemHeaderMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource TabViewItemHeaderMinHeight}" />
<Setter Property="MaxWidth" Value="{ThemeResource TabViewItemHeaderMaxWidth}" />
<Setter Property="UseSystemFocusVisuals" Value="True" />
<Setter Property="FocusVisualMargin" Value="0" />
<Setter Property="IsClosable" Value="False" />
<Setter Property="Template" Value="{StaticResource TabViewItemHeaderTemplate}" />
</Style>
<Style x:Key="TabViewItemCloseButtonStyle"
TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumHighBrush}" />
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="6,0,6,0" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Segoe MDL2 Assets" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="14" />
<Setter Property="UseSystemFocusVisuals" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid"
Background="{TemplateBinding Background}">
<ContentPresenter x:Name="ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>-->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerDownThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlDisabledTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TabViewScrollViewer"
TargetType="ScrollViewer">
<Setter Property="HorizontalScrollMode" Value="Auto" />
<Setter Property="VerticalScrollMode" Value="Auto" />
<Setter Property="IsHorizontalRailEnabled" Value="True" />
<Setter Property="IsVerticalRailEnabled" Value="True" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="ZoomMode" Value="Disabled" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="VerticalScrollBarVisibility" Value="Visible" />
<Setter Property="Padding" Value="0" />
<Setter Property="BorderThickness" Value="1,0,0,0" />
<Setter Property="BorderBrush" Value="{ThemeResource TabViewItemHeaderRevealBorderBrush}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="UseSystemFocusVisuals" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Border x:Name="Root"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<RepeatButton x:Name="ScrollBackButton"
VerticalAlignment="Stretch"
Background="Transparent"
BorderThickness="1"
Delay="50"
FontFamily="Segoe MDL2 Assets"
Interval="100"
Style="{StaticResource RepeatButtonRevealStyle}"
Visibility="{Binding ScrollableWidth, Converter={StaticResource GreaterThanToleranceVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}, FallbackValue=Collapsed, TargetNullValue=Collapsed}">
&#xE76B;
</RepeatButton>
<ScrollContentPresenter x:Name="ScrollContentPresenter"
Grid.Column="1"
TabFocusNavigation="Once"
Margin="{TemplateBinding Padding}" />
<RepeatButton x:Name="ScrollForwardButton"
Grid.Column="2"
VerticalAlignment="Stretch"
Background="Transparent"
BorderThickness="1"
Delay="50"
FontFamily="Segoe MDL2 Assets"
Interval="100"
Style="{StaticResource RepeatButtonRevealStyle}"
Visibility="{Binding ScrollableWidth, Converter={StaticResource GreaterThanToleranceVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}, FallbackValue=Collapsed, TargetNullValue=Collapsed}">
&#xE76C;
</RepeatButton>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

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

@ -1,79 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Item Container for a <see cref="TabView"/>.
/// </summary>
public partial class TabViewItem
{
/// <summary>
/// Gets or sets the header content for the tab.
/// </summary>
public object Header
{
get { return (object)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
/// <summary>
/// Identifies the <see cref="Header"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="Header"/> dependency property.</returns>
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register(nameof(Header), typeof(object), typeof(TabViewItem), new PropertyMetadata(null));
/// <summary>
/// Gets or sets the icon to appear in the tab header.
/// </summary>
public IconElement Icon
{
get { return (IconElement)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
/// <summary>
/// Identifies the <see cref="Icon"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="Icon"/> dependency property.</returns>
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register(nameof(Icon), typeof(IconElement), typeof(TabViewItem), new PropertyMetadata(null));
/// <summary>
/// Gets or sets the template to override for the tab header.
/// </summary>
public DataTemplate HeaderTemplate
{
get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
set { SetValue(HeaderTemplateProperty, value); }
}
/// <summary>
/// Identifies the <see cref="HeaderTemplate"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="HeaderTemplate"/> dependency property.</returns>
public static readonly DependencyProperty HeaderTemplateProperty =
DependencyProperty.Register(nameof(HeaderTemplate), typeof(DataTemplate), typeof(TabViewItem), new PropertyMetadata(null));
/// <summary>
/// Gets or sets a value indicating whether the tab can be closed by the user with the close button.
/// </summary>
public bool IsClosable
{
get { return (bool)GetValue(IsClosableProperty); }
set { SetValue(IsClosableProperty, value); }
}
/// <summary>
/// Identifies the <see cref="IsClosable"/> dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="IsClosable"/> dependency property.</returns>
public static readonly DependencyProperty IsClosableProperty =
DependencyProperty.Register(nameof(IsClosable), typeof(bool), typeof(TabViewItem), new PropertyMetadata(null));
}
}

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

@ -1,116 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Windows.Devices.Input;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Input;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Item Container for a <see cref="TabView"/>.
/// </summary>
[TemplatePart(Name = TabCloseButtonName, Type = typeof(ButtonBase))]
public partial class TabViewItem : ListViewItem
{
private const string TabCloseButtonName = "CloseButton";
private ButtonBase _tabCloseButton;
private bool _isMiddleClick;
/// <summary>
/// Initializes a new instance of the <see cref="TabViewItem"/> class.
/// </summary>
public TabViewItem()
{
DefaultStyleKey = typeof(TabViewItem);
}
/// <summary>
/// Fired when the Tab's close button is clicked.
/// </summary>
public event EventHandler<TabClosingEventArgs> Closing;
/// <inheritdoc/>
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (_tabCloseButton != null)
{
_tabCloseButton.Click -= TabCloseButton_Click;
}
_tabCloseButton = GetTemplateChild(TabCloseButtonName) as ButtonBase;
if (_tabCloseButton != null)
{
_tabCloseButton.Click += TabCloseButton_Click;
}
}
/// <inheritdoc/>
protected override void OnPointerPressed(PointerRoutedEventArgs e)
{
_isMiddleClick = false;
if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
{
PointerPoint pointerPoint = e.GetCurrentPoint(this);
// Record if middle button is pressed
if (pointerPoint.Properties.IsMiddleButtonPressed)
{
_isMiddleClick = true;
}
// Disable unwanted behavior inherited by ListViewItem:
// Disable "Ctrl + Left click" to deselect tab
// Or variant like "Ctrl + Shift + Left click"
// Or "Ctrl + Alt + Left click"
if (pointerPoint.Properties.IsLeftButtonPressed)
{
var ctrl = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control);
if (ctrl.HasFlag(CoreVirtualKeyStates.Down))
{
// return here so the event won't be picked up by the base class
// but keep this event unhandled so it can be picked up further
return;
}
}
}
base.OnPointerPressed(e);
}
/// <inheritdoc/>
protected override void OnPointerReleased(PointerRoutedEventArgs e)
{
base.OnPointerReleased(e);
// Close on Middle-Click
if (_isMiddleClick)
{
TabCloseButton_Click(this, null);
}
_isMiddleClick = false;
}
private void TabCloseButton_Click(object sender, RoutedEventArgs e)
{
if (IsClosable)
{
Closing?.Invoke(this, new TabClosingEventArgs(Content, this));
}
}
}
}

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

@ -1,36 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Possible modes for how to layout a <see cref="TabViewItem"/> Header's Width in the <see cref="TabView"/>.
/// </summary>
public enum TabWidthMode
{
/// <summary>
/// Each tab header takes up as much space as it needs. This is similar to how WPF and Visual Studio Code behave.
/// Suggest to keep <see cref="TabView.IsCloseButtonOverlay"/> set to false.
/// <see cref="TabView.SelectedTabWidth"/> is ignored.
/// In this scenario, tab width behavior is effectively turned off. This can be useful when using custom styling or a custom panel for layout of <see cref="TabViewItem"/> as well.
/// </summary>
Actual,
/// <summary>
/// Each tab header will use the minimal space set by <see cref="FrameworkElement.MinWidth"/> on the <see cref="TabViewItem"/>.
/// Suggest to set the <see cref="TabView.SelectedTabWidth"/> to show more content for the selected item.
/// </summary>
Compact,
/// <summary>
/// Each tab header will fill to fit the available space. If <see cref="TabView.SelectedTabWidth"/> is set, that will be used as a Maximum Width.
/// This is similar to how Microsoft Edge behaves when used with the <see cref="TabView.SelectedTabWidth"/>.
/// Suggest to set <see cref="TabView.IsCloseButtonOverlay"/> to true.
/// Suggest to set <see cref="TabView.SelectedTabWidth"/> to 200 and the TabViewItemHeaderMinWidth Resource to 90.
/// </summary>
Equal,
}
}

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

@ -9,7 +9,6 @@
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/GridSplitter/GridSplitter.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/HeaderedContentControl/HeaderedContentControl.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/HeaderedItemsControl/HeaderedItemsControl.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/HeaderedTextBlock/HeaderedTextBlock.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/ImageCropper/ImageCropper.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/ImageCropper/ImageCropperThumb.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/ImageEx/ImageEx.xaml" />
@ -26,7 +25,6 @@
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/RemoteDevicePicker/RemoteDevicePicker.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/RotatorTile/RotatorTile.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/ScrollHeader/ScrollHeader.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/TabView/TabView.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/ImageCropper/ImageCropperThumb.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/ImageCropper/ImageCropper.xaml" />
<ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/Eyedropper/Eyedropper.xaml" />

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

@ -181,13 +181,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// </summary>
public event EventHandler ImageLoaded;
/// <summary>
/// Gets a value indicating whether the platform supports Composition.
/// </summary>
[Obsolete("This property is now obsolete and will be removed in a future version of the Toolkit.")]
public static bool IsCompositionSupported => !DesignTimeHelpers.IsRunningInLegacyDesignerMode &&
ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3); // SDK >= 14393
/// <summary>
/// Initializes a new instance of the <see cref="TileControl"/> class.
/// </summary>

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

@ -13,7 +13,6 @@
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.GridSplitter" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.HeaderedContentControl" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.HeaderedItemsControl" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.HeaderedTextBlock" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.ImageEx" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.ImageExBase" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.InAppNotification" />
@ -32,8 +31,6 @@
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.RotatorTile" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.ScrollHeader" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.StaggeredPanel" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.TabView" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.TabViewItem" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.TextToolbar" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.TileControl" />
<Item Type="Microsoft.Toolkit.Uwp.UI.Controls.UniformGrid" />

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

@ -86,14 +86,6 @@ namespace Microsoft.Toolkit.Extensions
/// <returns><c>true</c> if the string contains only letters; otherwise, <c>false</c>.</returns>
public static bool IsCharacterString(this string str) => Regex.IsMatch(str, CharactersRegex);
/// <summary>
/// Returns a string representation of an object.
/// </summary>
/// <param name="value">The object to convert.</param>
/// <returns>String representation of the object.</returns>
[Obsolete("Use value?.ToString() instead. This will be removed in the next release of the toolkit.")]
public static string ToSafeString(this object value) => value?.ToString();
/// <summary>
/// Returns a string with HTML comments, scripts, styles, and tags removed.
/// </summary>

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

@ -1,141 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.ComponentModel;
using System.Threading.Tasks;
namespace Microsoft.Toolkit.Helpers
{
/// <summary>
/// Helper class to wrap around a Task to provide more information usable for UI data binding scenarios. As discussed in MSDN Magazine: https://msdn.microsoft.com/magazine/dn605875.
/// </summary>
/// <typeparam name="TResult">Type of result returned by task.</typeparam>
[Obsolete("This helper will be removed in a future release, use the ObservableObject base class from Microsoft.Toolkit.Mvvm and the SetAndNotifyOnCompletion method")]
public sealed class NotifyTaskCompletion<TResult> : INotifyPropertyChanged
{
/// <summary>
/// Initializes a new instance of the <see cref="NotifyTaskCompletion{TResult}"/> class.
/// </summary>
/// <param name="task">Task to wait on.</param>
public NotifyTaskCompletion(Task<TResult> task)
{
Task = task;
if (!task.IsCompleted)
{
TaskCompletion = WatchTaskAsync(task);
}
}
private async Task WatchTaskAsync(Task task)
{
try
{
await task;
}
catch
{
}
if (PropertyChanged == null)
{
return;
}
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Status)));
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(IsCompleted)));
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(IsNotCompleted)));
if (task.IsCanceled)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(IsCanceled)));
}
else if (task.IsFaulted)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(IsFaulted)));
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Exception)));
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(InnerException)));
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(ErrorMessage)));
}
else
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(IsSuccessfullyCompleted)));
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Result)));
}
}
/// <summary>
/// Gets the task that is being waited on.
/// </summary>
public Task<TResult> Task { get; private set; }
/// <summary>
/// Gets the task wrapper task.
/// </summary>
public Task TaskCompletion { get; private set; }
/// <summary>
/// Gets the result of the given task.
/// </summary>
public TResult Result
{
get
{
return (Task.Status == TaskStatus.RanToCompletion) ?
Task.Result :
default(TResult);
}
}
/// <summary>
/// Gets the status of the task.
/// </summary>
public TaskStatus Status => Task.Status;
/// <summary>
/// Gets a value indicating whether the task is completed.
/// </summary>
public bool IsCompleted => Task.IsCompleted;
/// <summary>
/// Gets a value indicating whether the task is not completed.
/// </summary>
public bool IsNotCompleted => !Task.IsCompleted;
/// <summary>
/// Gets a value indicating whether the task was successfully completed.
/// </summary>
public bool IsSuccessfullyCompleted => Task.Status == TaskStatus.RanToCompletion;
/// <summary>
/// Gets a value indicating whether the task was canceled.
/// </summary>
public bool IsCanceled => Task.IsCanceled;
/// <summary>
/// Gets a value indicating whether there was an error with the task.
/// </summary>
public bool IsFaulted => Task.IsFaulted;
/// <summary>
/// Gets the exception which occurred on the task (if one occurred).
/// </summary>
public AggregateException Exception => Task.Exception;
/// <summary>
/// Gets the inner exception of the task.
/// </summary>
public Exception InnerException => Exception?.InnerException;
/// <summary>
/// Gets the error message of the task.
/// </summary>
public string ErrorMessage => InnerException?.Message ?? Exception.Message;
/// <summary>
/// PropertyChanged event.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
}
}

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

@ -1,43 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Concurrent;
namespace Microsoft.Toolkit.Helpers
{
/// <summary>
/// Obsolete see https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/3134.
/// </summary>
/// <typeparam name="T">The type to be used for creating the Singleton instance.</typeparam>
/// <example>
/// Instead of this helper, migrate your code to this pattern instead:
/// <code>
/// // Setup Singleton
/// public class MyClass
/// {
/// public static MyClass Instance { get; } = new MyClass();
/// }
/// </code>
/// </example>
[Obsolete("This helper will be removed in a future release, see example tag for code replacement. https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/3134")]
public static class Singleton<T>
where T : new()
{
// Use ConcurrentDictionary for thread safety.
private static readonly ConcurrentDictionary<Type, T> _instances = new ConcurrentDictionary<Type, T>();
/// <summary>
/// Gets the instance of the Singleton class.
/// </summary>
public static T Instance
{
get
{
// Safely creates the first instance or retrieves the existing instance across threads.
return _instances.GetOrAdd(typeof(T), (t) => new T());
}
}
}
}

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

@ -19,8 +19,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{F1AFFFA7-28FE-
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B30036C4-D514-4E5B-A323-587A061772CE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.Services", "Microsoft.Toolkit.Uwp.Services\Microsoft.Toolkit.Uwp.Services.csproj", "{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.UI.Controls", "Microsoft.Toolkit.Uwp.UI.Controls\Microsoft.Toolkit.Uwp.UI.Controls.csproj", "{E9FAABFB-D726-42C1-83C1-CB46A29FEA81}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.UI.Controls.DataGrid", "Microsoft.Toolkit.Uwp.UI.Controls.DataGrid\Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.csproj", "{DAEB9CEC-C817-33B2-74B2-BC379380DB72}"
@ -78,12 +76,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Toolkit.Uwp.UI.Co
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Parsers", "Microsoft.Toolkit.Parsers\Microsoft.Toolkit.Parsers.csproj", "{42CA4935-54BE-42EA-AC19-992378C08DE6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PlatformSpecific", "PlatformSpecific", "{096ECFD7-7035-4487-9C87-81DCE9389620}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DifferencesGen", "Microsoft.Toolkit.Uwp.PlatformDifferencesGen\DifferencesGen.csproj", "{292D34E8-0F01-4FA8-951D-8232F75A88D5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer", "Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer\Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer.csproj", "{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Toolkit.Uwp.Input.GazeInteraction", "Microsoft.Toolkit.UWP.Input.GazeInteraction\Microsoft.Toolkit.Uwp.Input.GazeInteraction.vcxproj", "{A5E98964-45B1-442D-A07A-298A3221D81E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GazeInputTest", "GazeInputTest\GazeInputTest.csproj", "{A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}"
@ -317,31 +309,6 @@ Global
{B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|x64.Build.0 = Release|Any CPU
{B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|x86.ActiveCfg = Release|Any CPU
{B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|x86.Build.0 = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|ARM.Build.0 = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|ARM64.Build.0 = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|x64.ActiveCfg = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|x64.Build.0 = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|x86.ActiveCfg = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|x86.Build.0 = Debug|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|Any CPU.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|ARM.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|ARM64.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|x64.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|x86.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|Any CPU.Build.0 = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|ARM.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|ARM.Build.0 = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|ARM64.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|ARM64.Build.0 = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|x64.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|x64.Build.0 = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|x86.ActiveCfg = Release|Any CPU
{7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|x86.Build.0 = Release|Any CPU
{E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|ARM.ActiveCfg = Debug|Any CPU
@ -730,55 +697,6 @@ Global
{42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|x64.Build.0 = Release|Any CPU
{42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|x86.ActiveCfg = Release|Any CPU
{42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|x86.Build.0 = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|ARM.ActiveCfg = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|ARM.Build.0 = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|ARM64.Build.0 = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|x64.ActiveCfg = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|x64.Build.0 = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|x86.ActiveCfg = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|x86.Build.0 = Debug|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|Any CPU.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|ARM.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|ARM64.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|x64.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|x86.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|ARM.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|ARM.Build.0 = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|ARM64.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|ARM64.Build.0 = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|x64.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|x64.Build.0 = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|x86.ActiveCfg = Release|Any CPU
{292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|x86.Build.0 = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|ARM.ActiveCfg = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|ARM.Build.0 = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|ARM64.Build.0 = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|x64.ActiveCfg = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|x64.Build.0 = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|x86.ActiveCfg = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|x86.Build.0 = Debug|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|Any CPU.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|ARM.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|ARM64.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|x64.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|x86.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|Any CPU.Build.0 = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|ARM.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|ARM.Build.0 = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|ARM64.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|ARM64.Build.0 = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|x64.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|x64.Build.0 = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|x86.ActiveCfg = Release|Any CPU
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|x86.Build.0 = Release|Any CPU
{A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|Any CPU.ActiveCfg = Debug|Win32
{A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|Any CPU.Build.0 = Debug|Win32
{A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|ARM.ActiveCfg = Debug|ARM
@ -1246,8 +1164,6 @@ Global
{EFA96B3C-857E-4659-B942-6BEF7719F4CA} = {9333C63A-F64F-4797-82B3-017422668A5D}
{7AEFC959-ED7C-4D96-9E92-72609B40FBE0} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC}
{6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC}
{292D34E8-0F01-4FA8-951D-8232F75A88D5} = {096ECFD7-7035-4487-9C87-81DCE9389620}
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF} = {096ECFD7-7035-4487-9C87-81DCE9389620}
{A122EA02-4DE7-413D-BFBF-AF7DFC668DD6} = {B30036C4-D514-4E5B-A323-587A061772CE}
{75F9EE44-3EFA-47BC-AEDD-351B9834A0AF} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC}
{4E9466D1-D5AA-46AC-801B-C8FDAB79F0D4} = {B30036C4-D514-4E5B-A323-587A061772CE}

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

@ -35,12 +35,11 @@ Once you do a search, you should see a list similar to the one below (versions m
| --- | --- |
| Microsoft.Toolkit | .NET Standard NuGet package containing common code |
| Microsoft.Toolkit.HighPerformance | .NET Standard and .NET Core NuGet package with performance oriented helpers, extensions, etc. |
| Microsoft.Toolkit.Parsers | .NET Standard NuGet package containing cross-platform parsers, such as Markdown and RSS |
| Microsoft.Toolkit.Services | .NET Standard NuGet package containing cross-platform services |
| Microsoft.Toolkit.Parsers | .NET Standard NuGet package containing cross-platform parsers, such as Markdown |
| Microsoft.Toolkit.Services | .NET Standard NuGet package containing cross-platform services helpers, such as LinkedIn, Microsoft Graph, Twitter and more |
| Microsoft.Toolkit.Uwp | Main NuGet package includes code only helpers such as Colors conversion tool, Storage file handling, a Stream helper class, etc. |
| Microsoft.Toolkit.Uwp.Notifications | Notifications Package - Generate tile, toast, and badge notifications for Windows 10 via code. Includes intellisense support to avoid having to use the XML syntax |
| Microsoft.Toolkit.Uwp.Notifications.Javascript | Notification Packages for JavaScript |
| Microsoft.Toolkit.Uwp.Services | Services Package - This NuGet package includes the service helpers for Facebook, LinkedIn, Microsoft Graph, Twitter and more |
| Microsoft.Toolkit.Uwp.UI | UI Packages - XAML converters, Visual tree extensions, and other extensions and helpers for your XAML UI |
| Microsoft.Toolkit.Uwp.UI.Animations | Animations and Composition behaviors such as Blur, Fade, Rotate, etc. |
| Microsoft.Toolkit.Uwp.UI.Controls | XAML Controls such as RadialGauge, RangeSelector, etc. |