Add GraphicalHost assembly to enable Out-GridView, Show-Command, and Get-Help -ShowWindow (#10899)

This commit is contained in:
Steve Lee 2019-11-01 10:05:32 -07:00 committed by Aditya Patwardhan
parent 5a76137d14
commit ca68d9dbc5
217 changed files with 31620 additions and 48 deletions

View File

@ -3065,6 +3065,15 @@
<Component Id="cmpEC42F4F98D70437BB0E290A0E0FE1775" Guid="{5483092a-12c2-4e6c-b730-be491b8909c0}">
<File Id="filBE60A48C75214B7B810D695039AC47B5" KeyPath="yes" Source="$(env.ProductSourcePath)\mscordaccore_$(var.FileArchitecture)_$(var.FileArchitecture)_4.700.19.50403.dll" />
</Component>
<Component Id="cmp73A4CC8E2C9E4594A3D8258C9E00D7E6" Guid="{0aba3675-b1b5-4464-b8ed-937d3b9ea9ed}">
<File Id="fil8DBDCAE679714880A535D26FFE95A8F9" KeyPath="yes" Source="$(env.ProductSourcePath)\Microsoft.PowerShell.GraphicalHost.dll.config" />
</Component>
<Component Id="cmpAC984FA3A67247BC996F60290C87D0A1" Guid="{4ecc767e-b16c-45b8-8011-cc7374fccd5d}">
<File Id="fil1B9348FB24ED43DBAF5D977C7342C2B6" KeyPath="yes" Source="$(env.ProductSourcePath)\Microsoft.PowerShell.GraphicalHost.dll" />
</Component>
<Component Id="cmp2E32A6E773F543F0A150B972F8D3E23A" Guid="{a43d0117-1193-4316-a0f6-fef892870f38}">
<File Id="fil66411B8941CA492E93BF262EA72C6BE6" KeyPath="yes" Source="$(env.ProductSourcePath)\Microsoft.PowerShell.GraphicalHost.xml" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
@ -3907,6 +3916,9 @@
<ComponentRef Id="cmp859A3876902946E7B5B4965F90664C5D" />
<ComponentRef Id="cmpEC42F4F98D70437BB0E290A0E0FE1775" />
<ComponentRef Id="cmpF1B0E6DCC3BD4797B206C879EF270062" />
<ComponentRef Id="cmp73A4CC8E2C9E4594A3D8258C9E00D7E6" />
<ComponentRef Id="cmpAC984FA3A67247BC996F60290C87D0A1" />
<ComponentRef Id="cmp2E32A6E773F543F0A150B972F8D3E23A" />
</ComponentGroup>
</Fragment>
</Wix>

View File

@ -2210,7 +2210,7 @@ function Start-CrossGen {
$crossGenRequiredAssemblies = @("mscorlib.dll", "System.Private.CoreLib.dll")
$crossGenRequiredAssemblies += if ($Environment.IsWindows) {
"clrjit.dll"
"clrjit.dll"
} elseif ($Environment.IsLinux) {
"libclrjit.so"
} elseif ($Environment.IsMacOS) {
@ -2269,6 +2269,7 @@ function Start-CrossGen {
"Microsoft.WSMan.Management.dll",
"Microsoft.WSMan.Runtime.dll",
"Microsoft.PowerShell.Commands.Diagnostics.dll",
"Microsoft.PowerShell.GraphicalHost.dll",
"Microsoft.Management.Infrastructure.CimCmdlets.dll"
)
}

View File

@ -0,0 +1,71 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Windows;
// Specifies the location in which theme dictionaries are stored for types in an assembly.
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
namespace Microsoft.Management.UI
{
/// <summary>
/// Utilities in common in this assembly
/// </summary>
internal static class CommonHelper
{
/// <summary>
/// Restore the values from the settings to the actual window position, size and state.
/// </summary>
/// <param name="target">the window we are setting position and size of</param>
/// <param name="userSettingTop">the value for top from the user settings</param>
/// <param name="userSettingLeft">the value for left from the user settings</param>
/// <param name="userSettingWidth">the value for width from the user settings</param>
/// <param name="userSettingHeight">the value for height from the user settings</param>
/// <param name="defaultWidth">the with used if <paramref name="userSettingWidth"/> is not valid</param>
/// <param name="defaultHeight">the height used if <paramref name="userSettingHeight"/> is not valid</param>
/// <param name="userSettingMaximized">true if the window is maximized in the user setting</param>
internal static void SetStartingPositionAndSize(Window target, double userSettingTop, double userSettingLeft, double userSettingWidth, double userSettingHeight, double defaultWidth, double defaultHeight, bool userSettingMaximized)
{
bool leftInvalid = userSettingLeft < System.Windows.SystemParameters.VirtualScreenLeft ||
userSettingWidth > System.Windows.SystemParameters.VirtualScreenLeft +
System.Windows.SystemParameters.VirtualScreenWidth;
bool topInvalid = userSettingTop < System.Windows.SystemParameters.VirtualScreenTop ||
userSettingTop > System.Windows.SystemParameters.VirtualScreenTop +
System.Windows.SystemParameters.VirtualScreenHeight;
bool widthInvalid = userSettingWidth < 0 ||
userSettingWidth > System.Windows.SystemParameters.VirtualScreenWidth;
bool heightInvalid = userSettingHeight < 0 ||
userSettingHeight > System.Windows.SystemParameters.VirtualScreenHeight;
if (leftInvalid || topInvalid)
{
target.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
}
else
{
target.Left = userSettingLeft;
target.Top = userSettingTop;
}
// If any saved coordinate is invalid, we set the window to the default position
if (widthInvalid || heightInvalid)
{
target.Width = defaultWidth;
target.Height = defaultHeight;
}
else
{
target.Width = userSettingWidth;
target.Height = userSettingHeight;
}
if (userSettingMaximized)
{
target.WindowState = WindowState.Maximized;
}
}
}
}

View File

@ -0,0 +1,994 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
using System.Globalization;
using System.Management.Automation;
using System.Text;
using System.Windows.Documents;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Builds a help paragraph for a cmdlet
/// </summary>
internal class HelpParagraphBuilder : ParagraphBuilder
{
/// <summary>
/// Indentation size
/// </summary>
internal const int IndentSize = 4;
/// <summary>
/// new line separators
/// </summary>
private static readonly string[] Separators = new[] { "\r\n", "\n" };
/// <summary>
/// Object with the cmdelt
/// </summary>
private readonly PSObject psObj;
/// <summary>
/// Initializes a new instance of the HelpParagraphBuilder class
/// </summary>
/// <param name="paragraph">paragraph being built</param>
/// <param name="psObj">object with help information</param>
internal HelpParagraphBuilder(Paragraph paragraph, PSObject psObj)
: base(paragraph)
{
this.psObj = psObj;
this.AddTextToParagraphBuilder();
}
/// <summary>
/// Enum for category of Help.
/// </summary>
private enum HelpCategory
{
Default,
DscResource,
Class
}
/// <summary>
/// Gets the string value of a property or null if it could not be retrieved
/// </summary>
/// <param name="psObj">object with the property</param>
/// <param name="propertyName">property name</param>
/// <returns>the string value of a property or null if it could not be retrieved</returns>
internal static string GetPropertyString(PSObject psObj, string propertyName)
{
Debug.Assert(psObj != null, "ensured by caller");
object value = GetPropertyObject(psObj, propertyName);
if (value == null)
{
return null;
}
return value.ToString();
}
/// <summary>
/// Adds the help text to the paragraph
/// </summary>
internal void AddTextToParagraphBuilder()
{
this.ResetAllText();
string strCategory = HelpParagraphBuilder.GetProperty(this.psObj, "Category").Value.ToString();
HelpCategory category = HelpCategory.Default;
if (string.Compare(strCategory, "DscResource", StringComparison.OrdinalIgnoreCase) == 0)
{
category = HelpCategory.DscResource;
}
else if (string.Compare(strCategory, "Class", StringComparison.OrdinalIgnoreCase) == 0)
{
category = HelpCategory.Class;
}
if (HelpParagraphBuilder.GetProperty(this.psObj, "Syntax") == null)
{
if (category == HelpCategory.Default)
{
// if there is no syntax, this is not the standard help
// it might be an about page
this.AddText(this.psObj.ToString(), false);
return;
}
}
switch (category)
{
case HelpCategory.Class:
this.AddDescription(HelpWindowSettings.Default.HelpSynopsysDisplayed, HelpWindowResources.SynopsisTitle, "Introduction");
this.AddMembers(HelpWindowSettings.Default.HelpParametersDisplayed, HelpWindowResources.PropertiesTitle);
this.AddMembers(HelpWindowSettings.Default.HelpParametersDisplayed, HelpWindowResources.MethodsTitle);
break;
case HelpCategory.DscResource:
this.AddStringSection(HelpWindowSettings.Default.HelpSynopsysDisplayed, "Synopsis", HelpWindowResources.SynopsisTitle);
this.AddDescription(HelpWindowSettings.Default.HelpDescriptionDisplayed, HelpWindowResources.DescriptionTitle, "Description");
this.AddParameters(HelpWindowSettings.Default.HelpParametersDisplayed, HelpWindowResources.PropertiesTitle, "Properties", HelpCategory.DscResource);
break;
default:
this.AddStringSection(HelpWindowSettings.Default.HelpSynopsysDisplayed, "Synopsis", HelpWindowResources.SynopsisTitle);
this.AddDescription(HelpWindowSettings.Default.HelpDescriptionDisplayed, HelpWindowResources.DescriptionTitle, "Description");
this.AddParameters(HelpWindowSettings.Default.HelpParametersDisplayed, HelpWindowResources.ParametersTitle, "Parameters", HelpCategory.Default);
this.AddSyntax(HelpWindowSettings.Default.HelpSyntaxDisplayed, HelpWindowResources.SyntaxTitle);
break;
}
this.AddInputOrOutputEntries(HelpWindowSettings.Default.HelpInputsDisplayed, HelpWindowResources.InputsTitle, "inputTypes", "inputType");
this.AddInputOrOutputEntries(HelpWindowSettings.Default.HelpOutputsDisplayed, HelpWindowResources.OutputsTitle, "returnValues", "returnValue");
this.AddNotes(HelpWindowSettings.Default.HelpNotesDisplayed, HelpWindowResources.NotesTitle);
this.AddExamples(HelpWindowSettings.Default.HelpExamplesDisplayed, HelpWindowResources.ExamplesTitle);
this.AddNavigationLink(HelpWindowSettings.Default.HelpRelatedLinksDisplayed, HelpWindowResources.RelatedLinksTitle);
this.AddStringSection(HelpWindowSettings.Default.HelpRemarksDisplayed, "Remarks", HelpWindowResources.RemarksTitle);
}
/// <summary>
/// Gets the object property or null if it could not be retrieved
/// </summary>
/// <param name="psObj">object with the property</param>
/// <param name="propertyName">property name</param>
/// <returns>the object property or null if it could not be retrieved</returns>
private static PSPropertyInfo GetProperty(PSObject psObj, string propertyName)
{
Debug.Assert(psObj != null, "ensured by caller");
return psObj.Properties[propertyName];
}
/// <summary>
/// Gets a PSObject and then a value from it or null if the value could not be retrieved
/// </summary>
/// <param name="psObj">PSObject that contains another PSObject as a property</param>
/// <param name="psObjectName">property name that contains the PSObject</param>
/// <param name="propertyName">property name in thye inner PSObject</param>
/// <returns>the string from the inner psObject property or null if it could not be retrieved</returns>
private static string GetInnerPSObjectPropertyString(PSObject psObj, string psObjectName, string propertyName)
{
Debug.Assert(psObj != null, "ensured by caller");
PSObject innerPsObj = GetPropertyObject(psObj, psObjectName) as PSObject;
if (innerPsObj == null)
{
return null;
}
object value = GetPropertyObject(innerPsObj, propertyName);
if (value == null)
{
return null;
}
return value.ToString();
}
/// <summary>
/// Gets the value of a property or null if the value could not be retrieved
/// </summary>
/// <param name="psObj">object with the property</param>
/// <param name="propertyName">property name</param>
/// <returns>the value of a property or null if the value could not be retrieved</returns>
private static object GetPropertyObject(PSObject psObj, string propertyName)
{
Debug.Assert(psObj != null, "ensured by caller");
PSPropertyInfo property = HelpParagraphBuilder.GetProperty(psObj, propertyName);
if (property == null)
{
return null;
}
object value = null;
try
{
value = property.Value;
}
catch (ExtendedTypeSystemException)
{
// ignore this exception
}
return value;
}
/// <summary>
/// Gets the text from a property of type PSObject[] where the first object has a text property
/// </summary>
/// <param name="psObj">objhect to get text from</param>
/// <param name="propertyText">property with PSObject[] containing text</param>
/// <returns>the text from a property of type PSObject[] where the first object has a text property</returns>
private static string GetTextFromArray(PSObject psObj, string propertyText)
{
PSObject[] introductionObjects = HelpParagraphBuilder.GetPropertyObject(psObj, propertyText) as PSObject[];
if (introductionObjects != null && introductionObjects.Length > 0)
{
return GetPropertyString(introductionObjects[0], "text");
}
return null;
}
/// <summary>
/// Returns the largest size of a group of strings
/// </summary>
/// <param name="strs">strings to evaluate the largest size from</param>
/// <returns>the largest size of a group of strings</returns>
private static int LargestSize(params string[] strs)
{
int returnValue = 0;
foreach (string str in strs)
{
if (str != null && str.Length > returnValue)
{
returnValue = str.Length;
}
}
return returnValue;
}
/// <summary>
/// Splits the string adding indentation before each line
/// </summary>
/// <param name="str">string to add indentation to</param>
/// <returns>the string indented</returns>
private static string AddIndent(string str)
{
return HelpParagraphBuilder.AddIndent(str, 1);
}
/// <summary>
/// Splits the string adding indentation before each line
/// </summary>
/// <param name="str">string to add indentation to</param>
/// <param name="numberOfIdents">number of indentations</param>
/// <returns>the string indented</returns>
private static string AddIndent(string str, int numberOfIdents)
{
StringBuilder indent = new StringBuilder();
indent.Append(' ', numberOfIdents * HelpParagraphBuilder.IndentSize);
return HelpParagraphBuilder.AddIndent(str, indent.ToString());
}
/// <summary>
/// Splits the string adding indentation before each line
/// </summary>
/// <param name="str">string to add indentation to</param>
/// <param name="indentString">indentation string</param>
/// <returns>the string indented</returns>
private static string AddIndent(string str, string indentString)
{
if (str == null)
{
return string.Empty;
}
string[] lines = str.Split(Separators, StringSplitOptions.None);
StringBuilder returnValue = new StringBuilder();
foreach (string line in lines)
{
// Indentation is not localized
returnValue.AppendFormat("{0}{1}\r\n", indentString, line);
}
if (returnValue.Length > 2)
{
// remove the last \r\n
returnValue.Remove(returnValue.Length - 2, 2);
}
return returnValue.ToString();
}
/// <summary>
/// Get the object array value of a property
/// </summary>
/// <param name="obj">object containing the property</param>
/// <param name="propertyName">property with the array value</param>
/// <returns>the object array value of a property</returns>
private static object[] GetPropertyObjectArray(PSObject obj, string propertyName)
{
object innerObject;
if ((innerObject = HelpParagraphBuilder.GetPropertyObject(obj, propertyName)) == null)
{
return null;
}
if (innerObject is PSObject)
{
return new[] { innerObject };
}
object[] innerObjectArray = innerObject as object[];
return innerObjectArray;
}
/// <summary>
/// Adds a section that contains only a string
/// </summary>
/// <param name="setting">true if it should add the segment</param>
/// <param name="sectionName">name of the section to add</param>
/// <param name="sectionTitle">title of the section</param>
private void AddStringSection(bool setting, string sectionName, string sectionTitle)
{
string propertyValue;
if (!setting || (propertyValue = HelpParagraphBuilder.GetPropertyString(this.psObj, sectionName)) == null)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
this.AddText(HelpParagraphBuilder.AddIndent(propertyValue), false);
this.AddText("\r\n\r\n", false);
}
/// <summary>
/// Adds the help syntax segment
/// </summary>
/// <param name="setting">true if it should add the segment</param>
/// <param name="sectionTitle">title of the section</param>
private void AddSyntax(bool setting, string sectionTitle)
{
PSObject syntaxObject;
if (!setting || (syntaxObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "Syntax") as PSObject) == null)
{
return;
}
object[] syntaxItemsObj = HelpParagraphBuilder.GetPropertyObjectArray(syntaxObject, "syntaxItem");
if (syntaxItemsObj == null || syntaxItemsObj.Length == 0)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
foreach (object syntaxItemObj in syntaxItemsObj)
{
PSObject syntaxItem = syntaxItemObj as PSObject;
if (syntaxItem == null)
{
continue;
}
string commandName = GetPropertyString(syntaxItem, "name");
object[] parameterObjs = HelpParagraphBuilder.GetPropertyObjectArray(syntaxItem, "parameter");
if (commandName == null || parameterObjs == null || parameterObjs.Length == 0)
{
continue;
}
string commandStart = string.Format(CultureInfo.CurrentCulture, "{0} ", commandName);
this.AddText(HelpParagraphBuilder.AddIndent(commandStart), false);
foreach (object parameterObj in parameterObjs)
{
PSObject parameter = parameterObj as PSObject;
if (parameter == null)
{
continue;
}
string parameterValue = GetPropertyString(parameter, "parameterValue");
string position = GetPropertyString(parameter, "position");
string required = GetPropertyString(parameter, "required");
string parameterName = GetPropertyString(parameter, "name");
if (position == null || required == null || parameterName == null)
{
continue;
}
string parameterType = parameterValue == null ? string.Empty : string.Format(CultureInfo.CurrentCulture, "<{0}>", parameterValue);
string parameterOptionalOpenBrace, parameterOptionalCloseBrace;
if (string.Equals(required, "true", StringComparison.OrdinalIgnoreCase))
{
parameterOptionalOpenBrace = string.Empty;
parameterOptionalCloseBrace = string.Empty;
}
else
{
parameterOptionalOpenBrace = "[";
parameterOptionalCloseBrace = "]";
}
string parameterNameOptionalOpenBrace, parameterNameOptionalCloseBrace;
if (string.Equals(position, "named", StringComparison.OrdinalIgnoreCase))
{
parameterNameOptionalOpenBrace = parameterNameOptionalCloseBrace = string.Empty;
}
else
{
parameterNameOptionalOpenBrace = "[";
parameterNameOptionalCloseBrace = "]";
}
string paramterPrefix = string.Format(
CultureInfo.CurrentCulture,
"{0}{1}-",
parameterOptionalOpenBrace,
parameterNameOptionalOpenBrace);
this.AddText(paramterPrefix, false);
this.AddText(parameterName, true);
string paramterSuffix = string.Format(
CultureInfo.CurrentCulture,
"{0} {1}{2} ",
parameterNameOptionalCloseBrace,
parameterType,
parameterOptionalCloseBrace);
this.AddText(paramterSuffix, false);
}
string commonParametersText = string.Format(
CultureInfo.CurrentCulture,
"[<{0}>]\r\n\r\n",
HelpWindowResources.CommonParameters);
this.AddText(commonParametersText, false);
}
this.AddText("\r\n", false);
}
/// <summary>
/// Adds the help description segment
/// </summary>
/// <param name="setting">true if it should add the segment</param>
/// <param name="sectionTitle">title of the section</param>
/// <param name="propertyName">propertyName that has description</param>
private void AddDescription(bool setting, string sectionTitle, string propertyName)
{
PSObject[] descriptionObjects;
if (!setting ||
(descriptionObjects = HelpParagraphBuilder.GetPropertyObject(this.psObj, propertyName) as PSObject[]) == null ||
descriptionObjects.Length == 0)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
foreach (PSObject description in descriptionObjects)
{
string descriptionText = GetPropertyString(description, "text");
this.AddText(HelpParagraphBuilder.AddIndent(descriptionText), false);
this.AddText("\r\n", false);
}
this.AddText("\r\n\r\n", false);
}
/// <summary>
/// Adds the help examples segment
/// </summary>
/// <param name="setting">true if it should add the segment</param>
/// <param name="sectionTitle">title of the section</param>
private void AddExamples(bool setting, string sectionTitle)
{
if (!setting)
{
return;
}
PSObject exampleRootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "Examples") as PSObject;
if (exampleRootObject == null)
{
return;
}
object[] exampleObjects = HelpParagraphBuilder.GetPropertyObjectArray(exampleRootObject, "example");
if (exampleObjects == null || exampleObjects.Length == 0)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
foreach (object exampleObj in exampleObjects)
{
PSObject example = exampleObj as PSObject;
if (example == null)
{
continue;
}
string introductionText = null;
introductionText = GetTextFromArray(example, "introduction");
string codeText = GetPropertyString(example, "code");
string title = GetPropertyString(example, "title");
if (codeText == null)
{
continue;
}
if (title != null)
{
this.AddText(HelpParagraphBuilder.AddIndent(title), false);
this.AddText("\r\n", false);
}
string codeLine = string.Format(
CultureInfo.CurrentCulture,
"{0}{1}\r\n\r\n",
introductionText,
codeText);
this.AddText(HelpParagraphBuilder.AddIndent(codeLine), false);
PSObject[] remarks = HelpParagraphBuilder.GetPropertyObject(example, "remarks") as PSObject[];
if (remarks == null)
{
continue;
}
foreach (PSObject remark in remarks)
{
string remarkText = GetPropertyString(remark, "text");
if (remarkText == null)
{
continue;
}
this.AddText(remarkText, false);
this.AddText("\r\n", false);
}
}
this.AddText("\r\n\r\n", false);
}
private void AddMembers(bool setting, string sectionTitle)
{
if (!setting || string.IsNullOrEmpty(sectionTitle))
{
return;
}
PSObject memberRootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "Members") as PSObject;
if (memberRootObject == null)
{
return;
}
object[] memberObjects = HelpParagraphBuilder.GetPropertyObjectArray(memberRootObject, "member");
if (memberObjects == null)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
foreach (object memberObj in memberObjects)
{
string description = null;
string memberText = null;
PSObject member = memberObj as PSObject;
if (member == null)
{
continue;
}
string name = GetPropertyString(member, "title");
string type = GetPropertyString(member, "type");
string propertyType = null;
if (string.Compare("field", type, StringComparison.OrdinalIgnoreCase) == 0)
{
PSObject fieldData = HelpParagraphBuilder.GetPropertyObject(member, "fieldData") as PSObject;
if (fieldData != null)
{
PSObject propertyTypeObject = HelpParagraphBuilder.GetPropertyObject(fieldData, "type") as PSObject;
if (propertyTypeObject != null)
{
propertyType = GetPropertyString(propertyTypeObject, "name");
description = GetPropertyString(propertyTypeObject, "description");
}
memberText = string.Format(CultureInfo.CurrentCulture, " [{0}] {1}\r\n", propertyType, name);
}
}
else if (string.Compare("method", type, StringComparison.OrdinalIgnoreCase) == 0)
{
FormatMethodData(member, name, out memberText, out description);
}
if (!string.IsNullOrEmpty(memberText))
{
this.AddText(HelpParagraphBuilder.AddIndent(string.Empty), false);
this.AddText(memberText, true);
if (description != null)
{
this.AddText(HelpParagraphBuilder.AddIndent(description, 2), false);
this.AddText("\r\n", false);
}
this.AddText("\r\n", false);
}
}
}
private static void FormatMethodData(PSObject member, string name, out string memberText, out string description)
{
memberText = null;
description = null;
if (member == null || string.IsNullOrEmpty(name))
{
return;
}
string returnType = null;
StringBuilder parameterText = new StringBuilder();
// Get method return type
PSObject returnTypeObject = HelpParagraphBuilder.GetPropertyObject(member, "returnValue") as PSObject;
if (returnTypeObject != null)
{
PSObject returnTypeData = HelpParagraphBuilder.GetPropertyObject(returnTypeObject, "type") as PSObject;
if (returnTypeData != null)
{
returnType = GetPropertyString(returnTypeData, "name");
}
}
// Get method description.
PSObject[] methodDescriptions = HelpParagraphBuilder.GetPropertyObject(member, "introduction") as PSObject[];
if (methodDescriptions != null)
{
foreach (var methodDescription in methodDescriptions)
{
description = GetPropertyString(methodDescription, "Text");
// If we get an text we do not need to iterate more.
if (!string.IsNullOrEmpty(description))
{
break;
}
}
}
// Get method parameters.
PSObject parametersObject = HelpParagraphBuilder.GetPropertyObject(member, "parameters") as PSObject;
if (parametersObject != null)
{
PSObject[] paramObject = HelpParagraphBuilder.GetPropertyObject(parametersObject, "parameter") as PSObject[];
if (paramObject != null)
{
foreach (var param in paramObject)
{
string parameterName = GetPropertyString(param, "name");
string parameterType = null;
PSObject parameterTypeData = HelpParagraphBuilder.GetPropertyObject(param, "type") as PSObject;
if (parameterTypeData != null)
{
parameterType = GetPropertyString(parameterTypeData, "name");
// If there is no type for the paramter, we expect it is System.Object
if (string.IsNullOrEmpty(parameterType))
{
parameterType = "object";
}
}
string paramString = string.Format(CultureInfo.CurrentCulture, "[{0}] ${1},", parameterType, parameterName);
parameterText.Append(paramString);
}
if (string.Compare(parameterText[parameterText.Length - 1].ToString(), ",", StringComparison.OrdinalIgnoreCase) == 0)
{
parameterText = parameterText.Remove(parameterText.Length - 1, 1);
}
}
}
memberText = string.Format(CultureInfo.CurrentCulture, " [{0}] {1}({2})\r\n", returnType, name, parameterText);
}
/// <summary>
/// Adds the help parameters segment
/// </summary>
/// <param name="setting">true if it should add the segment</param>
/// <param name="sectionTitle">title of the section</param>
/// <param name="paramPropertyName">name of the property which has properties</param>
/// <param name="helpCategory">category of help</param>
private void AddParameters(bool setting, string sectionTitle, string paramPropertyName, HelpCategory helpCategory)
{
if (!setting)
{
return;
}
PSObject parameterRootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, paramPropertyName) as PSObject;
if (parameterRootObject == null)
{
return;
}
object[] parameterObjects = null;
// Root object for Class has members not parameters.
if (helpCategory != HelpCategory.Class)
{
parameterObjects = HelpParagraphBuilder.GetPropertyObjectArray(parameterRootObject, "parameter");
}
if (parameterObjects == null || parameterObjects.Length == 0)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
foreach (object parameterObj in parameterObjects)
{
PSObject parameter = parameterObj as PSObject;
if (parameter == null)
{
continue;
}
string parameterValue = GetPropertyString(parameter, "parameterValue");
string name = GetPropertyString(parameter, "name");
string description = GetTextFromArray(parameter, "description");
string required = GetPropertyString(parameter, "required");
string position = GetPropertyString(parameter, "position");
string pipelineinput = GetPropertyString(parameter, "pipelineInput");
string defaultValue = GetPropertyString(parameter, "defaultValue");
string acceptWildcard = GetPropertyString(parameter, "globbing");
if (string.IsNullOrEmpty(name))
{
continue;
}
if (helpCategory == HelpCategory.DscResource)
{
this.AddText(HelpParagraphBuilder.AddIndent(string.Empty), false);
}
else
{
this.AddText(HelpParagraphBuilder.AddIndent("-"), false);
}
this.AddText(name, true);
string parameterText = string.Format(
CultureInfo.CurrentCulture,
" <{0}>\r\n",
parameterValue);
this.AddText(parameterText, false);
if (description != null)
{
this.AddText(HelpParagraphBuilder.AddIndent(description, 2), false);
this.AddText("\r\n", false);
}
this.AddText("\r\n", false);
int largestSize = HelpParagraphBuilder.LargestSize(
HelpWindowResources.ParameterRequired,
HelpWindowResources.ParameterPosition,
HelpWindowResources.ParameterDefaultValue,
HelpWindowResources.ParameterPipelineInput,
HelpWindowResources.ParameterAcceptWildcard);
// justification of parameter values is not localized
string formatString = string.Format(
CultureInfo.CurrentCulture,
"{{0,-{0}}}{{1}}",
largestSize + 2);
string tableLine;
tableLine = string.Format(
CultureInfo.CurrentCulture,
formatString,
HelpWindowResources.ParameterRequired,
required);
this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
this.AddText("\r\n", false);
// these are not applicable for Dsc Resource help
if (helpCategory != HelpCategory.DscResource)
{
tableLine = string.Format(
CultureInfo.CurrentCulture,
formatString,
HelpWindowResources.ParameterPosition,
position);
this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
this.AddText("\r\n", false);
tableLine = string.Format(
CultureInfo.CurrentCulture,
formatString,
HelpWindowResources.ParameterDefaultValue,
defaultValue);
this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
this.AddText("\r\n", false);
tableLine = string.Format(
CultureInfo.CurrentCulture,
formatString,
HelpWindowResources.ParameterPipelineInput,
pipelineinput);
this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
this.AddText("\r\n", false);
tableLine = string.Format(
CultureInfo.CurrentCulture,
formatString,
HelpWindowResources.ParameterAcceptWildcard,
acceptWildcard);
this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
}
this.AddText("\r\n\r\n", false);
}
this.AddText("\r\n\r\n", false);
}
/// <summary>
/// Adds the help navigation links segment
/// </summary>
/// <param name="setting">true if it should add the segment</param>
/// <param name="sectionTitle">title of the section</param>
private void AddNavigationLink(bool setting, string sectionTitle)
{
if (!setting)
{
return;
}
PSObject linkRootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "RelatedLinks") as PSObject;
if (linkRootObject == null)
{
return;
}
PSObject[] linkObjects;
if ((linkObjects = HelpParagraphBuilder.GetPropertyObject(linkRootObject, "navigationLink") as PSObject[]) == null ||
linkObjects.Length == 0)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
foreach (PSObject linkObject in linkObjects)
{
string text = GetPropertyString(linkObject, "linkText");
string uri = GetPropertyString(linkObject, "uri");
string linkLine = string.IsNullOrEmpty(uri) ? text : string.Format(
CultureInfo.CurrentCulture,
HelpWindowResources.LinkTextFormat,
text,
uri);
this.AddText(HelpParagraphBuilder.AddIndent(linkLine), false);
this.AddText("\r\n", false);
}
this.AddText("\r\n\r\n", false);
}
/// <summary>
/// Adds the help input or output segment
/// </summary>
/// <param name="setting">true if it should add the segment</param>
/// <param name="sectionTitle">title of the section</param>
/// <param name="inputOrOutputProperty">property with the outter object</param>
/// <param name="inputOrOutputInnerProperty">property with the inner object</param>
private void AddInputOrOutputEntries(bool setting, string sectionTitle, string inputOrOutputProperty, string inputOrOutputInnerProperty)
{
if (!setting)
{
return;
}
PSObject rootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, inputOrOutputProperty) as PSObject;
if (rootObject == null)
{
return;
}
object[] inputOrOutputObjs;
inputOrOutputObjs = HelpParagraphBuilder.GetPropertyObjectArray(rootObject, inputOrOutputInnerProperty);
if (inputOrOutputObjs == null || inputOrOutputObjs.Length == 0)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
foreach (object inputOrOutputObj in inputOrOutputObjs)
{
PSObject inputOrOutput = inputOrOutputObj as PSObject;
if (inputOrOutput == null)
{
continue;
}
string type = HelpParagraphBuilder.GetInnerPSObjectPropertyString(inputOrOutput, "type", "name");
string description = GetTextFromArray(inputOrOutput, "description");
this.AddText(HelpParagraphBuilder.AddIndent(type), false);
this.AddText("\r\n", false);
if (description != null)
{
this.AddText(HelpParagraphBuilder.AddIndent(description), false);
this.AddText("\r\n", false);
}
}
this.AddText("\r\n", false);
}
/// <summary>
/// Adds the help notes segment
/// </summary>
/// <param name="setting">true if it should add the segment</param>
/// <param name="sectionTitle">title of the section</param>
private void AddNotes(bool setting, string sectionTitle)
{
if (!setting)
{
return;
}
PSObject rootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "alertSet") as PSObject;
if (rootObject == null)
{
return;
}
string note = GetTextFromArray(rootObject, "alert");
if (note == null)
{
return;
}
this.AddText(sectionTitle, true);
this.AddText("\r\n", false);
this.AddText(HelpParagraphBuilder.AddIndent(note), false);
this.AddText("\r\n\r\n", false);
}
}
}

View File

@ -0,0 +1,283 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Management.Automation;
using System.Windows.Documents;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// ViewModel for the Help Dialog used to:
/// build the help document
/// search the help document
/// offer text for labels
/// </summary>
internal class HelpViewModel : INotifyPropertyChanged
{
/// <summary>
/// The builder for the help FlowDocument Paragraph used in a RichEditText control
/// </summary>
private readonly HelpParagraphBuilder helpBuilder;
/// <summary>
/// Searcher for selecting current matches in paragraph text
/// </summary>
private readonly ParagraphSearcher searcher;
/// <summary>
/// Title of the help window
/// </summary>
private readonly string helpTitle;
/// <summary>
/// the zoom bound to the zoom slider value
/// </summary>
private double zoom = 100;
/// <summary>
/// Text to be found. This is bound to the find TextBox
/// </summary>
private string findText;
/// <summary>
/// text for the number of matches found
/// </summary>
private string matchesLabel;
/// <summary>
/// Initializes a new instance of the HelpViewModel class
/// </summary>
/// <param name="psObj">object containing help</param>
/// <param name="documentParagraph">paragraph in which help text is built/searched</param>
internal HelpViewModel(PSObject psObj, Paragraph documentParagraph)
{
Debug.Assert(psObj != null, "ensured by caller");
Debug.Assert(documentParagraph != null, "ensured by caller");
this.helpBuilder = new HelpParagraphBuilder(documentParagraph, psObj);
this.helpBuilder.BuildParagraph();
this.searcher = new ParagraphSearcher();
this.helpBuilder.PropertyChanged += new PropertyChangedEventHandler(this.HelpBuilder_PropertyChanged);
this.helpTitle = string.Format(
CultureInfo.CurrentCulture,
HelpWindowResources.HelpTitleFormat,
HelpParagraphBuilder.GetPropertyString(psObj, "name"));
}
#region INotifyPropertyChanged Members
/// <summary>
/// Used to notify of property changes
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
/// <summary>
/// Gets or sets the Zoom bound to the zoom slider value
/// </summary>
public double Zoom
{
get
{
return this.zoom;
}
set
{
this.zoom = value;
this.OnNotifyPropertyChanged("Zoom");
this.OnNotifyPropertyChanged("ZoomLabel");
this.OnNotifyPropertyChanged("ZoomLevel");
}
}
/// <summary>
/// Gets the value bound to the RichTextEdit zoom, which is calculated based on the zoom
/// </summary>
public double ZoomLevel
{
get
{
return this.zoom / 100.0;
}
}
/// <summary>
/// Gets the label to be displayed for the zoom
/// </summary>
public string ZoomLabel
{
get
{
return string.Format(CultureInfo.CurrentCulture, HelpWindowResources.ZoomLabelTextFormat, this.zoom);
}
}
/// <summary>
/// Gets or sets the text to be found
/// </summary>
public string FindText
{
get
{
return this.findText;
}
set
{
this.findText = value;
this.Search();
this.SetMatchesLabel();
}
}
/// <summary>
/// Gets the title of the window
/// </summary>
public string HelpTitle
{
get
{
return this.helpTitle;
}
}
/// <summary>
/// Gets or sets the label for current matches
/// </summary>
public string MatchesLabel
{
get
{
return this.matchesLabel;
}
set
{
this.matchesLabel = value;
this.OnNotifyPropertyChanged("MatchesLabel");
}
}
/// <summary>
/// Gets a value indicating whether there are matches to go to
/// </summary>
public bool CanGoToNextOrPrevious
{
get
{
return this.HelpBuilder.HighlightCount != 0;
}
}
/// <summary>
/// Gets the searcher for selecting current matches in paragraph text
/// </summary>
internal ParagraphSearcher Searcher
{
get { return this.searcher; }
}
/// <summary>
/// Gets the paragraph builder used to write help content
/// </summary>
internal HelpParagraphBuilder HelpBuilder
{
get { return this.helpBuilder; }
}
/// <summary>
/// Highlights all matches to this.findText
/// Called when findText changes or whenever the search has to be refreshed
/// </summary>
internal void Search()
{
this.HelpBuilder.HighlightAllInstancesOf(this.findText, HelpWindowSettings.Default.HelpSearchMatchCase, HelpWindowSettings.Default.HelpSearchWholeWord);
this.searcher.ResetSearch();
}
/// <summary>
/// Increases Zoom if not above maximum
/// </summary>
internal void ZoomIn()
{
if (this.Zoom + HelpWindow.ZoomInterval <= HelpWindow.MaximumZoom)
{
this.Zoom += HelpWindow.ZoomInterval;
}
}
/// <summary>
/// Decreases Zoom if not below minimum
/// </summary>
internal void ZoomOut()
{
if (this.Zoom - HelpWindow.ZoomInterval >= HelpWindow.MinimumZoom)
{
this.Zoom -= HelpWindow.ZoomInterval;
}
}
/// <summary>
/// Called to update the matches label
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void HelpBuilder_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "HighlightCount")
{
this.SetMatchesLabel();
this.OnNotifyPropertyChanged("CanGoToNextOrPrevious");
}
}
/// <summary>
/// Sets the current matches label
/// </summary>
private void SetMatchesLabel()
{
if (this.findText == null || this.findText.Trim().Length == 0)
{
this.MatchesLabel = string.Empty;
}
else
{
if (this.HelpBuilder.HighlightCount == 0)
{
this.MatchesLabel = HelpWindowResources.NoMatches;
}
else
{
if (this.HelpBuilder.HighlightCount == 1)
{
this.MatchesLabel = HelpWindowResources.OneMatch;
}
else
{
this.MatchesLabel = string.Format(
CultureInfo.CurrentCulture,
HelpWindowResources.SomeMatchesFormat,
this.HelpBuilder.HighlightCount);
}
}
}
}
/// <summary>
/// Called internally to notify when a proiperty changed
/// </summary>
/// <param name="propertyName">property name</param>
private void OnNotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

View File

@ -0,0 +1,76 @@
<!--=================================================================
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
==================================================================-->
<Window x:Class="Microsoft.Management.UI.HelpWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:Microsoft.Management.UI.Internal"
xmlns:default="clr-namespace:"
xmlns:ui="clr-namespace:Microsoft.Management.UI"
Height="400"
Width="600"
Title="{Binding HelpTitle}"
AutomationProperties.AutomationId="HelpWindow"
FocusManager.FocusedElement="{Binding ElementName=HelpText}">
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid x:Name="HeaderGrid" Grid.Row="0" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto" SharedSizeGroup="HeaderButtons"></ColumnDefinition>
<ColumnDefinition Width="Auto" SharedSizeGroup="HeaderButtons"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto" SharedSizeGroup="HeaderButtons"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid x:Name="FindLabelAndTextGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label x:Name="FindLabel" Margin="0,5,0,5" Grid.Column="0" Content="{x:Static default:HelpWindowResources.FindText}"></Label>
<TextBox x:Name="Find" Margin="5" Grid.Column="1" Text="{Binding FindText, UpdateSourceTrigger=PropertyChanged}" AutomationProperties.Name="{x:Static default:HelpWindowResources.FindText}"></TextBox>
</Grid>
<Button x:Name="PreviousMatch" Margin="5" Padding="3" Grid.Column="1"
IsEnabled="{Binding CanGoToNextOrPrevious}"
Content="{x:Static default:HelpWindowResources.PreviousText}" Click="PreviousMatch_Click"></Button>
<Button x:Name="NextMatch" Margin="5" Padding="3" Grid.Column="2"
IsEnabled="{Binding CanGoToNextOrPrevious}"
Content="{x:Static default:HelpWindowResources.NextText}" Click="NextMatch_Click"></Button>
<Label x:Name="MatchCountLabel" Margin="5" MinWidth="100" Grid.Column="3" Content="{Binding MatchesLabel}"></Label>
<Button x:Name="Settings" Margin="5" Padding="3" Grid.Column="4" Click="Settings_Click" Content="{x:Static default:HelpWindowResources.SettingsText}"></Button>
</Grid>
<ScrollViewer x:Name="Scroll" HorizontalAlignment="Stretch" Grid.Row="1" AutomationProperties.Name="{Binding HelpTitle}">
<RichTextBox x:Name="HelpText" FontFamily="Consolas" VerticalScrollBarVisibility="Disabled" BorderThickness="0" IsReadOnly="True" IsReadOnlyCaretVisible="True" AutomationProperties.Name="{Binding HelpTitle}">
<RichTextBox.LayoutTransform>
<ScaleTransform ScaleX="{Binding Path=ZoomLevel}" ScaleY="{Binding Path=ZoomLevel}"/>
</RichTextBox.LayoutTransform>
<RichTextBox.Document>
<FlowDocument>
<Paragraph x:Name="DocumentParagraph"></Paragraph>
</FlowDocument>
</RichTextBox.Document>
</RichTextBox>
</ScrollViewer>
<Grid Grid.Row="2" HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ZoomLabel}" VerticalAlignment="Center"></TextBlock>
<Slider Grid.Column="1" x:Name="ZoomSlider" Margin="5" Value="{Binding Zoom}" Minimum="{x:Static ui:HelpWindow.MinimumZoom}" Maximum="{x:Static ui:HelpWindow.MaximumZoom}" TickFrequency="{x:Static ui:HelpWindow.ZoomInterval}" TickPlacement="None" IsSnapToTickEnabled="True" Width="110" ToolTip="{x:Static default:HelpWindowResources.ZoomSlider}" AutomationProperties.Name="{x:Static default:HelpWindowResources.ZoomSlider}"></Slider>
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,318 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Globalization;
using System.Management.Automation;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using Microsoft.Management.UI.Internal;
namespace Microsoft.Management.UI
{
/// <summary>
/// A window displaying help content and allowing search
/// </summary>
public partial class HelpWindow : Window
{
/// <summary>
/// Minimum zoom in the slider
/// </summary>
public static double MinimumZoom
{
get
{
return 20;
}
}
/// <summary>
/// Maximum zoom in the slider
/// </summary>
public static double MaximumZoom
{
get
{
return 300;
}
}
/// <summary>
/// Zoom interval
/// </summary>
public static double ZoomInterval
{
get
{
return 10;
}
}
/// <summary>
/// The ViewModel for the dialog
/// </summary>
private readonly HelpViewModel viewModel;
/// <summary>
/// Initializes a new instance of the HelpWindow class
/// </summary>
/// <param name="helpObject">the object with help information</param>
public HelpWindow(PSObject helpObject)
{
InitializeComponent();
this.viewModel = new HelpViewModel(helpObject, this.DocumentParagraph);
CommonHelper.SetStartingPositionAndSize(
this,
HelpWindowSettings.Default.HelpWindowTop,
HelpWindowSettings.Default.HelpWindowLeft,
HelpWindowSettings.Default.HelpWindowWidth,
HelpWindowSettings.Default.HelpWindowHeight,
double.Parse((string)HelpWindowSettings.Default.Properties["HelpWindowWidth"].DefaultValue, CultureInfo.InvariantCulture.NumberFormat),
double.Parse((string)HelpWindowSettings.Default.Properties["HelpWindowHeight"].DefaultValue, CultureInfo.InvariantCulture.NumberFormat),
HelpWindowSettings.Default.HelpWindowMaximized);
this.ReadZoomUserSetting();
this.viewModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(this.ViewModel_PropertyChanged);
this.DataContext = this.viewModel;
this.Loaded += new RoutedEventHandler(this.HelpDialog_Loaded);
this.Closed += new System.EventHandler(this.HelpDialog_Closed);
}
/// <summary>
/// Handles the mouse wheel to zoom in/out
/// </summary>
/// <param name="e">event arguments</param>
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
if (Keyboard.Modifiers != ModifierKeys.Control)
{
return;
}
if (e.Delta > 0)
{
this.viewModel.ZoomIn();
e.Handled = true;
}
else
{
this.viewModel.ZoomOut();
e.Handled = true;
}
}
/// <summary>
/// Handles key down to fix the Page/Douwn going to end of help issue
/// And to implement some additional shortcuts like Ctrl+F and ZoomIn/ZoomOut
/// </summary>
/// <param name="e">event arguments</param>
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.None)
{
if (e.Key == Key.PageUp)
{
this.Scroll.PageUp();
e.Handled = true;
return;
}
if (e.Key == Key.PageDown)
{
this.Scroll.PageDown();
e.Handled = true;
return;
}
}
if (Keyboard.Modifiers == ModifierKeys.Control)
{
this.HandleZoomInAndZoomOut(e);
if (e.Handled)
{
return;
}
if (e.Key == Key.F)
{
this.Find.Focus();
e.Handled = true;
return;
}
}
if (Keyboard.Modifiers == (ModifierKeys.Control | ModifierKeys.Shift))
{
this.HandleZoomInAndZoomOut(e);
}
}
/// <summary>
/// Reads the zoom part of the user settings
/// </summary>
private void ReadZoomUserSetting()
{
if (HelpWindowSettings.Default.HelpZoom < HelpWindow.MinimumZoom || HelpWindowSettings.Default.HelpZoom > HelpWindow.MaximumZoom)
{
HelpWindowSettings.Default.HelpZoom = 100;
}
this.viewModel.Zoom = HelpWindowSettings.Default.HelpZoom;
}
/// <summary>
/// Handles Zoom in and Zoom out keys
/// </summary>
/// <param name="e">event arguments</param>
private void HandleZoomInAndZoomOut(KeyEventArgs e)
{
if (e.Key == Key.OemPlus || e.Key == Key.Add)
{
this.viewModel.ZoomIn();
e.Handled = true;
}
if (e.Key == Key.OemMinus || e.Key == Key.Subtract)
{
this.viewModel.ZoomOut();
e.Handled = true;
}
}
/// <summary>
/// Listens to changes in the zoom in order to update the user settings
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "Zoom")
{
HelpWindowSettings.Default.HelpZoom = this.viewModel.Zoom;
}
}
/// <summary>
/// Saves the user settings
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void HelpDialog_Closed(object sender, System.EventArgs e)
{
HelpWindowSettings.Default.Save();
}
/// <summary>
/// Updates the user setting with window state
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void HelpDialog_StateChanged(object sender, System.EventArgs e)
{
HelpWindowSettings.Default.HelpWindowMaximized = this.WindowState == WindowState.Maximized;
}
/// <summary>
/// Sets the positions from user settings and start monitoring position changes
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void HelpDialog_Loaded(object sender, RoutedEventArgs e)
{
this.StateChanged += new System.EventHandler(this.HelpDialog_StateChanged);
this.LocationChanged += new System.EventHandler(this.HelpDialog_LocationChanged);
this.SizeChanged += new SizeChangedEventHandler(this.HelpDialog_SizeChanged);
}
/// <summary>
/// Saves size changes in user settings
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void HelpDialog_SizeChanged(object sender, SizeChangedEventArgs e)
{
HelpWindowSettings.Default.HelpWindowWidth = this.Width;
HelpWindowSettings.Default.HelpWindowHeight = this.Height;
}
/// <summary>
/// Saves position changes in user settings
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void HelpDialog_LocationChanged(object sender, System.EventArgs e)
{
HelpWindowSettings.Default.HelpWindowTop = this.Top;
HelpWindowSettings.Default.HelpWindowLeft = this.Left;
}
/// <summary>
/// Called when the settings button is clicked
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void Settings_Click(object sender, RoutedEventArgs e)
{
SettingsDialog settings = new SettingsDialog();
settings.Owner = this;
settings.ShowDialog();
if (settings.DialogResult == true)
{
this.viewModel.HelpBuilder.AddTextToParagraphBuilder();
this.viewModel.Search();
}
}
/// <summary>
/// Called when the Previous button is clicked
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void PreviousMatch_Click(object sender, RoutedEventArgs e)
{
this.MoveToNextMatch(false);
}
/// <summary>
/// Called when the Next button is clicked
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void NextMatch_Click(object sender, RoutedEventArgs e)
{
this.MoveToNextMatch(true);
}
/// <summary>
/// Moves to the previous or next match
/// </summary>
/// <param name="forward">true for forward false for backwards</param>
private void MoveToNextMatch(bool forward)
{
TextPointer caretPosition = this.HelpText.CaretPosition;
Run nextRun = this.viewModel.Searcher.MoveAndHighlightNextNextMatch(forward, caretPosition);
this.MoveToRun(nextRun);
}
/// <summary>
/// Moves to the caret and brings the view to the <paramref name="run"/>
/// </summary>
/// <param name="run">run to move to</param>
private void MoveToRun(Run run)
{
if (run == null)
{
return;
}
run.BringIntoView();
this.HelpText.CaretPosition = run.ElementEnd;
this.HelpText.Focus();
}
}
}

View File

@ -0,0 +1,247 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.16598
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
// namespace Microsoft.Management.UI.Internal {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class HelpWindowSettings : global::System.Configuration.ApplicationSettingsBase {
private static HelpWindowSettings defaultInstance = ((HelpWindowSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new HelpWindowSettings())));
public static HelpWindowSettings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpRemarksDisplayed
{
get
{
return ((bool)(this["HelpRemarksDisplayed"]));
}
set
{
this["HelpRemarksDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpSyntaxDisplayed {
get {
return ((bool)(this["HelpSyntaxDisplayed"]));
}
set {
this["HelpSyntaxDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpExamplesDisplayed {
get {
return ((bool)(this["HelpExamplesDisplayed"]));
}
set {
this["HelpExamplesDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpSynopsysDisplayed {
get {
return ((bool)(this["HelpSynopsysDisplayed"]));
}
set {
this["HelpSynopsysDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpDescriptionDisplayed {
get {
return ((bool)(this["HelpDescriptionDisplayed"]));
}
set {
this["HelpDescriptionDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpParametersDisplayed {
get {
return ((bool)(this["HelpParametersDisplayed"]));
}
set {
this["HelpParametersDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpInputsDisplayed {
get {
return ((bool)(this["HelpInputsDisplayed"]));
}
set {
this["HelpInputsDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpOutputsDisplayed {
get {
return ((bool)(this["HelpOutputsDisplayed"]));
}
set {
this["HelpOutputsDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpNotesDisplayed {
get {
return ((bool)(this["HelpNotesDisplayed"]));
}
set {
this["HelpNotesDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool HelpRelatedLinksDisplayed {
get {
return ((bool)(this["HelpRelatedLinksDisplayed"]));
}
set {
this["HelpRelatedLinksDisplayed"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool HelpSearchMatchCase {
get {
return ((bool)(this["HelpSearchMatchCase"]));
}
set {
this["HelpSearchMatchCase"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool HelpSearchWholeWord {
get {
return ((bool)(this["HelpSearchWholeWord"]));
}
set {
this["HelpSearchWholeWord"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("400")]
public double HelpWindowHeight {
get {
return ((double)(this["HelpWindowHeight"]));
}
set {
this["HelpWindowHeight"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("600")]
public double HelpWindowWidth {
get {
return ((double)(this["HelpWindowWidth"]));
}
set {
this["HelpWindowWidth"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("-1")]
public double HelpWindowTop {
get {
return ((double)(this["HelpWindowTop"]));
}
set {
this["HelpWindowTop"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("-1")]
public double HelpWindowLeft {
get {
return ((double)(this["HelpWindowLeft"]));
}
set {
this["HelpWindowLeft"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool HelpWindowMaximized {
get {
return ((bool)(this["HelpWindowMaximized"]));
}
set {
this["HelpWindowMaximized"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("100")]
public double HelpZoom {
get {
return ((double)(this["HelpZoom"]));
}
set {
this["HelpZoom"] = value;
}
}
}
//}

View File

@ -0,0 +1,60 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Microsoft.Management.UI.Internal.HelpWindow" GeneratedClassName="HelpWindowSettings">
<Profiles />
<Settings>
<Setting Name="HelpSyntaxDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpExamplesDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpSynopsysDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpDescriptionDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpParametersDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpInputsDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpOutputsDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpNotesDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpRelatedLinksDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HelpSearchMatchCase" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="HelpSearchWholeWord" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="HelpWindowTop" Type="System.Double" Scope="User">
<Value Profile="(Default)">-1</Value>
</Setting>
<Setting Name="HelpWindowLeft" Type="System.Double" Scope="User">
<Value Profile="(Default)">-1</Value>
</Setting>
<Setting Name="HelpWindowMaximized" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="HelpZoom" Type="System.Double" Scope="User">
<Value Profile="(Default)">100</Value>
</Setting>
<Setting Name="HelpWindowHeight" Type="System.Double" Scope="User">
<Value Profile="(Default)">500</Value>
</Setting>
<Setting Name="HelpWindowWidth" Type="System.Double" Scope="User">
<Value Profile="(Default)">700</Value>
</Setting>
<Setting Name="HelpRemarksDisplayed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@ -0,0 +1,377 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Documents;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Builds a paragraph based on Text + Bold + Highlight information.
/// Bold are the segments of thexct that should be bold, and Highlight are
/// the segments of thext that should be highlighted (like search results).
/// </summary>
internal class ParagraphBuilder : INotifyPropertyChanged
{
/// <summary>
/// The text spans that should be bold
/// </summary>
private readonly List<TextSpan> boldSpans;
/// <summary>
/// The text spans that should be highlighted
/// </summary>
private readonly List<TextSpan> highlightedSpans;
/// <summary>
/// The text displayed
/// </summary>
private readonly StringBuilder textBuilder;
/// <summary>
/// Paragraph built in BuildParagraph
/// </summary>
private readonly Paragraph paragraph;
/// <summary>
/// Initializes a new instance of the ParagraphBuilder class
/// </summary>
/// <param name="paragraph">paragraph we will be adding lines to in BuildParagraph</param>
internal ParagraphBuilder(Paragraph paragraph)
{
if (paragraph == null)
{
throw new ArgumentNullException("paragraph");
}
this.paragraph = paragraph;
this.boldSpans = new List<TextSpan>();
this.highlightedSpans = new List<TextSpan>();
this.textBuilder = new StringBuilder();
}
#region INotifyPropertyChanged Members
/// <summary>
/// Used to notify of property changes
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
/// <summary>
/// Gets the number of highlights.
/// </summary>
internal int HighlightCount
{
get { return this.highlightedSpans.Count; }
}
/// <summary>
/// Gets the paragraph built in BuildParagraph
/// </summary>
internal Paragraph Paragraph
{
get { return this.paragraph; }
}
/// <summary>
/// Called after all the AddText calls have been made to build the paragraph
/// based on the current text.
/// This method goes over 3 collections simultaneouslly:
/// 1) characters in this.textBuilder
/// 2) spans in this.boldSpans
/// 3) spans in this.highlightedSpans
/// And adds the minimal number of Inlines to the paragraph so that all
/// characters that should be bold and/or highlighed are.
/// </summary>
internal void BuildParagraph()
{
this.paragraph.Inlines.Clear();
int currentBoldIndex = 0;
TextSpan? currentBoldSpan = this.boldSpans.Count == 0 ? (TextSpan?)null : this.boldSpans[0];
int currentHighlightedIndex = 0;
TextSpan? currentHighlightedSpan = this.highlightedSpans.Count == 0 ? (TextSpan?)null : this.highlightedSpans[0];
bool currentBold = false;
bool currentHighlighted = false;
StringBuilder sequence = new StringBuilder();
int i = 0;
foreach (char c in this.textBuilder.ToString())
{
bool newBold = false;
bool newHighlighted = false;
ParagraphBuilder.MoveSpanToPosition(ref currentBoldIndex, ref currentBoldSpan, i, this.boldSpans);
newBold = currentBoldSpan == null ? false : currentBoldSpan.Value.Contains(i);
ParagraphBuilder.MoveSpanToPosition(ref currentHighlightedIndex, ref currentHighlightedSpan, i, this.highlightedSpans);
newHighlighted = currentHighlightedSpan == null ? false : currentHighlightedSpan.Value.Contains(i);
if (newBold != currentBold || newHighlighted != currentHighlighted)
{
ParagraphBuilder.AddInline(this.paragraph, currentBold, currentHighlighted, sequence);
}
sequence.Append(c);
currentHighlighted = newHighlighted;
currentBold = newBold;
i++;
}
ParagraphBuilder.AddInline(this.paragraph, currentBold, currentHighlighted, sequence);
}
/// <summary>
/// Highlights all ocurrences of <paramref name="search"/>.
/// This is called after all calls to AddText have been made
/// </summary>
/// <param name="search">search string</param>
/// <param name="caseSensitive">true if search should be case sensitive</param>
/// <param name="wholeWord">true if we should search whole word only</param>
internal void HighlightAllInstancesOf(string search, bool caseSensitive, bool wholeWord)
{
this.highlightedSpans.Clear();
if (search == null || search.Trim().Length == 0)
{
this.BuildParagraph();
this.OnNotifyPropertyChanged("HighlightCount");
return;
}
string text = this.textBuilder.ToString();
StringComparison comparison = caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
int start = 0;
int match;
while ((match = text.IndexOf(search, start, comparison)) != -1)
{
// false loop
do
{
if (wholeWord)
{
if (match > 0 && char.IsLetterOrDigit(text[match - 1]))
{
break;
}
if ((match + search.Length <= text.Length - 1) && char.IsLetterOrDigit(text[match + search.Length]))
{
break;
}
}
this.AddHighlight(match, search.Length);
}
while (false);
start = match + search.Length;
}
this.BuildParagraph();
this.OnNotifyPropertyChanged("HighlightCount");
}
/// <summary>
/// Adds text to the paragraph later build with BuildParagraph
/// </summary>
/// <param name="str">text to be added</param>
/// <param name="bold">true if the text should be bold</param>
internal void AddText(string str, bool bold)
{
if (str == null)
{
throw new ArgumentNullException("str");
}
if (str.Length == 0)
{
return;
}
if (bold)
{
this.boldSpans.Add(new TextSpan(this.textBuilder.Length, str.Length));
}
this.textBuilder.Append(str);
}
/// <summary>
/// Called before a derived class starts adding text
/// to reset the current content
/// </summary>
internal void ResetAllText()
{
this.boldSpans.Clear();
this.highlightedSpans.Clear();
this.textBuilder.Clear();
}
/// <summary>
/// Adds an inline to <paramref name="currentParagraph"/> based on the remaining parameters.
/// </summary>
/// <param name="currentParagraph">paragraph to add Inline to</param>
/// <param name="currentBold">true if text should be added in bold</param>
/// <param name="currentHighlighted">true if the text should be added with highlight</param>
/// <param name="sequence">the text to add and clear</param>
private static void AddInline(Paragraph currentParagraph, bool currentBold, bool currentHighlighted, StringBuilder sequence)
{
if (sequence.Length == 0)
{
return;
}
Run run = new Run(sequence.ToString());
if (currentHighlighted)
{
run.Background = ParagraphSearcher.HighlightBrush;
}
Inline inline = currentBold ? (Inline)new Bold(run) : run;
currentParagraph.Inlines.Add(inline);
sequence.Clear();
}
/// <summary>
/// This is an auxiliar method in BuildParagraph to move the current bold or highlighed spans
/// according to the <paramref name="caracterPosition"/>
/// The current bold and higlighed span should be ending ahead of the current position.
/// Moves <paramref name="currentSpanIndex"/> and <paramref name="currentSpan"/> to the
/// propper span in <paramref name="allSpans"/> according to the <paramref name="caracterPosition"/>
/// This is an auxiliar method in BuildParagraph.
/// </summary>
/// <param name="currentSpanIndex">current index within <paramref name="allSpans"/></param>
/// <param name="currentSpan">current span within <paramref name="allSpans"/></param>
/// <param name="caracterPosition">caracter position. This comes from a position within this.textBuilder</param>
/// <param name="allSpans">the collection of spans. This is either this.boldSpans or this.highlightedSpans</param>
private static void MoveSpanToPosition(ref int currentSpanIndex, ref TextSpan? currentSpan, int caracterPosition, List<TextSpan> allSpans)
{
if (currentSpan == null || caracterPosition <= currentSpan.Value.End)
{
return;
}
for (int newBoldIndex = currentSpanIndex + 1; newBoldIndex < allSpans.Count; newBoldIndex++)
{
TextSpan newBoldSpan = allSpans[newBoldIndex];
if (caracterPosition <= newBoldSpan.End)
{
currentSpanIndex = newBoldIndex;
currentSpan = newBoldSpan;
return;
}
}
// there is no span ending ahead of current position, so
// we set the current span to null to prevent unecessary comparisons against the currentSpan
currentSpan = null;
}
/// <summary>
/// Adds one individual text highlight
/// This is called after all calls to AddText have been made
/// </summary>
/// <param name="start">highlight start</param>
/// <param name="length">highlight length</param>
private void AddHighlight(int start, int length)
{
if (start < 0)
{
throw new ArgumentOutOfRangeException("start");
}
if (start + length > this.textBuilder.Length)
{
throw new ArgumentOutOfRangeException("length");
}
this.highlightedSpans.Add(new TextSpan(start, length));
}
/// <summary>
/// Called internally to notify when a proiperty changed
/// </summary>
/// <param name="propertyName">property name</param>
private void OnNotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
/// <summary>
/// A text span used to mark bold and highlighed segments
/// </summary>
internal struct TextSpan
{
/// <summary>
/// Index of the first character in the span
/// </summary>
private readonly int start;
/// <summary>
/// Index of the last character in the span
/// </summary>
private readonly int end;
/// <summary>
/// Initializes a new instance of the TextSpan struct
/// </summary>
/// <param name="start">Index of the first character in the span</param>
/// <param name="length">Index of the last character in the span</param>
internal TextSpan(int start, int length)
{
if (start < 0)
{
throw new ArgumentOutOfRangeException("start");
}
if (length < 1)
{
throw new ArgumentOutOfRangeException("length");
}
this.start = start;
this.end = start + length - 1;
}
/// <summary>
/// Gets the index of the first character in the span
/// </summary>
internal int Start
{
get { return this.start; }
}
/// <summary>
/// Gets the index of the first character in the span
/// </summary>
internal int End
{
get
{
return this.end;
}
}
/// <summary>
/// Returns true if the <paramref name="position"/> is between start and end (inclusive)
/// </summary>
/// <param name="position">position to verify if is in the span</param>
/// <returns>true if the <paramref name="position"/> is between start and end (inclusive)</returns>
internal bool Contains(int position)
{
return (position >= this.start) && (position <= this.end);
}
}
}
}

View File

@ -0,0 +1,241 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Diagnostics;
using System.Windows.Documents;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Moves through search highlights built in a ParagraphBuilder
/// changing the color of the current highlight
/// </summary>
internal class ParagraphSearcher
{
/// <summary>
/// Highlight for all matches except the current
/// </summary>
internal static readonly Brush HighlightBrush = Brushes.Yellow;
/// <summary>
/// Highlight for the current match
/// </summary>
private static readonly Brush CurrentHighlightBrush = Brushes.Cyan;
/// <summary>
/// Current match being highlighted in search
/// </summary>
private Run currentHighlightedMatch;
/// <summary>
/// Initializes a new instance of the ParagraphSearcher class
/// </summary>
internal ParagraphSearcher()
{
}
/// <summary>
/// Move to the next highlight starting at the <paramref name="caretPosition"/>
/// </summary>
/// <param name="forward">true for next false for previous</param>
/// <param name="caretPosition">caret position</param>
/// <returns>the next highlight starting at the <paramref name="caretPosition"/></returns>
internal Run MoveAndHighlightNextNextMatch(bool forward, TextPointer caretPosition)
{
Debug.Assert(caretPosition != null, "a caret position is allways valid");
Debug.Assert(caretPosition.Parent != null && caretPosition.Parent is Run, "a caret PArent is allways a valid Run");
Run caretRun = (Run)caretPosition.Parent;
Run currentRun;
if (this.currentHighlightedMatch != null)
{
// restore the curent highlighted background to plain highlighted
this.currentHighlightedMatch.Background = ParagraphSearcher.HighlightBrush;
}
// If the caret is in the end of a highlight we move to the adjacent run
// It has to be in the end because if there is a match at the begining of the file
// and the caret has not been touched (so it is in the beginning of the file too)
// we want to highlight this first match.
// Considering the caller allways set the caret to the end of the highlight
// The condition below works well for successive searchs
// We also need to move to the adjacent run if the caret is at the first run and we
// are moving backwards so that a search backwards when the first run is highlighted
// and the caret is at the beginning will wrap to the end
if ((!forward && IsFirstRun(caretRun)) ||
((caretPosition.GetOffsetToPosition(caretRun.ContentEnd) == 0) && ParagraphSearcher.Ishighlighted(caretRun)))
{
currentRun = ParagraphSearcher.GetNextRun(caretRun, forward);
}
else
{
currentRun = caretRun;
}
currentRun = ParagraphSearcher.GetNextMatch(currentRun, forward);
if (currentRun == null)
{
// if we could not find a next highlight wrap arround
currentRun = ParagraphSearcher.GetFirstOrLastRun(caretRun, forward);
currentRun = ParagraphSearcher.GetNextMatch(currentRun, forward);
}
this.currentHighlightedMatch = currentRun;
if (this.currentHighlightedMatch != null)
{
// restore the curent highligthed background to current highlighted
this.currentHighlightedMatch.Background = ParagraphSearcher.CurrentHighlightBrush;
}
return currentRun;
}
/// <summary>
/// Resets the search for fresh calls to MoveAndHighlightNextNextMatch
/// </summary>
internal void ResetSearch()
{
this.currentHighlightedMatch = null;
}
/// <summary>
/// Returns true if <paramref name="run"/> is highlighted
/// </summary>
/// <param name="run">run to check if is highlighted</param>
/// <returns>true if <paramref name="run"/> is highlighted</returns>
private static bool Ishighlighted(Run run)
{
if (run == null)
{
return false;
}
SolidColorBrush background = run.Background as SolidColorBrush;
if (background != null && background == ParagraphSearcher.HighlightBrush)
{
return true;
}
return false;
}
/// <summary>
/// Get the next or previous run according to <paramref name="forward"/>
/// </summary>
/// <param name="currentRun">the current run</param>
/// <param name="forward">true for next false for previous</param>
/// <returns>the next or previous run according to <paramref name="forward"/></returns>
private static Run GetNextRun(Run currentRun, bool forward)
{
Bold parentBold = currentRun.Parent as Bold;
Inline nextInline;
if (forward)
{
nextInline = parentBold != null ? ((Inline)parentBold).NextInline : currentRun.NextInline;
}
else
{
nextInline = parentBold != null ? ((Inline)parentBold).PreviousInline : currentRun.PreviousInline;
}
return GetRun(nextInline);
}
/// <summary>
/// Gets the run of an inline. Inlines in a ParagrahBuilder are either a Run or a Bold
/// which contains a Run
/// </summary>
/// <param name="inline">inline to get the run from</param>
/// <returns>the run of the inline</returns>
private static Run GetRun(Inline inline)
{
Bold inlineBold = inline as Bold;
if (inlineBold != null)
{
return (Run)inlineBold.Inlines.FirstInline;
}
return (Run)inline;
}
/// <summary>
/// Gets the next highlighted run starting and including <paramref name="currentRun"/>
/// according to the direction specified in <paramref name="forward"/>
/// </summary>
/// <param name="currentRun">the current run</param>
/// <param name="forward">true for next false for previous</param>
/// <returns>
/// the next highlighted run starting and including <paramref name="currentRun"/>
/// according to the direction specified in <paramref name="forward"/>
/// </returns>
private static Run GetNextMatch(Run currentRun, bool forward)
{
while (currentRun != null)
{
if (ParagraphSearcher.Ishighlighted(currentRun))
{
return currentRun;
}
currentRun = ParagraphSearcher.GetNextRun(currentRun, forward);
}
return currentRun;
}
/// <summary>
/// Gets the run's paragraph
/// </summary>
/// <param name="run">run to get the paragraph from</param>
/// <returns>the run's paragraph</returns>
private static Paragraph GetParagraph(Run run)
{
Bold parentBold = run.Parent as Bold;
Paragraph parentParagraph = (parentBold != null ? parentBold.Parent : run.Parent) as Paragraph;
Debug.Assert(parentParagraph != null, "the documents we are saerching are built with ParagraphBuilder, which builds the document like this");
return parentParagraph;
}
/// <summary>
/// Returns true if the run is the fiorst run of the paragraph
/// </summary>
/// <param name="run">run to check</param>
/// <returns>true if the run is the fiorst run of the paragraph</returns>
private static bool IsFirstRun(Run run)
{
Paragraph paragraph = GetParagraph(run);
Run firstRun = ParagraphSearcher.GetRun(paragraph.Inlines.FirstInline);
return run == firstRun;
}
/// <summary>
/// Gets the first or lasr run in the paragraph containing <paramref name="caretRun"/>
/// </summary>
/// <param name="caretRun">run containing the caret</param>
/// <param name="forward">true for first false for last</param>
/// <returns>the first or last run in the paragraph containing <paramref name="caretRun"/></returns>
private static Run GetFirstOrLastRun(Run caretRun, bool forward)
{
Debug.Assert(caretRun != null, "a caret run is allways valid");
Paragraph paragraph = GetParagraph(caretRun);
Inline firstOrLastInline;
if (forward)
{
firstOrLastInline = paragraph.Inlines.FirstInline;
}
else
{
firstOrLastInline = paragraph.Inlines.LastInline;
}
return GetRun(firstOrLastInline);
}
}
}

View File

@ -0,0 +1,63 @@
<!--=================================================================
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
==================================================================-->
<Window x:Class="Microsoft.Management.UI.SettingsDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:Microsoft.Management.UI.Internal"
xmlns:default="clr-namespace:"
Title="{x:Static default:HelpWindowResources.SettingsText}" SizeToContent="WidthAndHeight">
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<GroupBox x:Name="HelpSectionsGroup" Margin="5" Header="{x:Static default:HelpWindowResources.HelpSectionsTitle}" Grid.Row="0" Padding="5">
<Grid x:Name="HelpSectionsGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<CheckBox x:Name="Synopsys" Margin="5" Grid.Row="0" Grid.Column="0" Content="{x:Static default:HelpWindowResources.SynopsisTitle}"></CheckBox>
<CheckBox x:Name="Syntax" Margin="5" Grid.Row="1" Grid.Column="0" Content="{x:Static default:HelpWindowResources.SyntaxTitle}"></CheckBox>
<CheckBox x:Name="Description" Margin="5" Grid.Row="2" Grid.Column="0" Content="{x:Static default:HelpWindowResources.DescriptionTitle}"></CheckBox>
<CheckBox x:Name="Parameters" Margin="5" Grid.Row="3" Grid.Column="0" Content="{x:Static default:HelpWindowResources.ParametersTitle}"></CheckBox>
<CheckBox x:Name="Inputs" Margin="5" Grid.Row="4" Grid.Column="0" Content="{x:Static default:HelpWindowResources.InputsTitle}"></CheckBox>
<CheckBox x:Name="Outputs" Margin="5" Grid.Row="0" Grid.Column="1" Content="{x:Static default:HelpWindowResources.OutputsTitle}"></CheckBox>
<CheckBox x:Name="Notes" Margin="5" Grid.Row="1" Grid.Column="1" Content="{x:Static default:HelpWindowResources.NotesTitle}"></CheckBox>
<CheckBox x:Name="Examples" Margin="5" Grid.Row="2" Grid.Column="1" Content="{x:Static default:HelpWindowResources.ExamplesTitle}"></CheckBox>
<CheckBox x:Name="RelatedLinks" Margin="5" Grid.Row="3" Grid.Column="1" Content="{x:Static default:HelpWindowResources.RelatedLinksTitle}"></CheckBox>
<CheckBox x:Name="Remarks" Margin="5" Grid.Row="4" Grid.Column="1" Content="{x:Static default:HelpWindowResources.RemarksTitle}"></CheckBox>
</Grid>
</GroupBox>
<GroupBox x:Name="SearchOptions" Margin="5" Header="{x:Static default:HelpWindowResources.SearchOptionsTitle}" Grid.Row="1" Padding="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<CheckBox x:Name="CaseSensitive" Margin="5" Grid.Row="0" Grid.Column="0" Content="{x:Static default:HelpWindowResources.CaseSensitiveTitle}"></CheckBox>
<CheckBox x:Name="WholeWord" Margin="5" Grid.Row="1" Grid.Column="0" Content="{x:Static default:HelpWindowResources.WholeWordTitle}"></CheckBox>
</Grid>
</GroupBox>
<Grid x:Name="ButtonGrid" Grid.Row="2" Grid.IsSharedSizeScope="True" HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="ButtonSize"></ColumnDefinition>
<ColumnDefinition Width="Auto" SharedSizeGroup="ButtonSize"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button x:Name="OK" Margin="5" Padding="3" Grid.Row="0" Grid.Column="0" IsDefault="True" Click="OK_Click" Content="{x:Static default:HelpWindowResources.OKText}"></Button>
<Button x:Name="Cancel" Margin="5" Padding="3" Grid.Row="0" Grid.Column="1" IsCancel="True" Content="{x:Static default:HelpWindowResources.CancelText}"></Button>
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,58 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Management.UI
{
using System.Windows;
using Microsoft.Management.UI.Internal;
/// <summary>
/// Dialog with settings for the help dialog
/// </summary>
public partial class SettingsDialog : Window
{
/// <summary>
/// Initializes a new instance of the SettingsDialog class
/// </summary>
public SettingsDialog()
{
InitializeComponent();
this.Description.IsChecked = HelpWindowSettings.Default.HelpDescriptionDisplayed;
this.Examples.IsChecked = HelpWindowSettings.Default.HelpExamplesDisplayed;
this.Inputs.IsChecked = HelpWindowSettings.Default.HelpInputsDisplayed;
this.Notes.IsChecked = HelpWindowSettings.Default.HelpNotesDisplayed;
this.Outputs.IsChecked = HelpWindowSettings.Default.HelpOutputsDisplayed;
this.Parameters.IsChecked = HelpWindowSettings.Default.HelpParametersDisplayed;
this.RelatedLinks.IsChecked = HelpWindowSettings.Default.HelpRelatedLinksDisplayed;
this.Remarks.IsChecked = HelpWindowSettings.Default.HelpRemarksDisplayed;
this.Synopsys.IsChecked = HelpWindowSettings.Default.HelpSynopsysDisplayed;
this.Syntax.IsChecked = HelpWindowSettings.Default.HelpSyntaxDisplayed;
this.CaseSensitive.IsChecked = HelpWindowSettings.Default.HelpSearchMatchCase;
this.WholeWord.IsChecked = HelpWindowSettings.Default.HelpSearchWholeWord;
}
/// <summary>
/// Called when the OK button has been clicked
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private void OK_Click(object sender, RoutedEventArgs e)
{
HelpWindowSettings.Default.HelpDescriptionDisplayed = this.Description.IsChecked == true;
HelpWindowSettings.Default.HelpExamplesDisplayed = this.Examples.IsChecked == true;
HelpWindowSettings.Default.HelpInputsDisplayed = this.Inputs.IsChecked == true;
HelpWindowSettings.Default.HelpOutputsDisplayed = this.Outputs.IsChecked == true;
HelpWindowSettings.Default.HelpNotesDisplayed = this.Notes.IsChecked == true;
HelpWindowSettings.Default.HelpParametersDisplayed = this.Parameters.IsChecked == true;
HelpWindowSettings.Default.HelpRelatedLinksDisplayed = this.RelatedLinks.IsChecked == true;
HelpWindowSettings.Default.HelpRemarksDisplayed = this.Remarks.IsChecked == true;
HelpWindowSettings.Default.HelpSynopsysDisplayed = this.Synopsys.IsChecked == true;
HelpWindowSettings.Default.HelpSyntaxDisplayed = this.Syntax.IsChecked == true;
HelpWindowSettings.Default.HelpSearchMatchCase = this.CaseSensitive.IsChecked == true;
HelpWindowSettings.Default.HelpSearchWholeWord = this.WholeWord.IsChecked == true;
HelpWindowSettings.Default.Save();
this.DialogResult = true;
this.Close();
}
}
}

View File

@ -0,0 +1,78 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides a <see cref="Button"/> control that is always visible in the automation tree.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
[Description("Provides a System.Windows.Controls.Button control that is always visible in the automation tree.")]
public class AutomationButton : Button
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="AutomationButton" /> class.
/// </summary>
public AutomationButton()
{
// This constructor intentionally left blank
}
#endregion
#region Overides
/// <summary>
/// Returns the <see cref="System.Windows.Automation.Peers.AutomationPeer"/> implementations for this control.
/// </summary>
/// <returns>The <see cref="System.Windows.Automation.Peers.AutomationPeer"/> implementations for this control.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
return new AutomationButtonAutomationPeer(this);
}
#endregion
}
/// <summary>
/// Provides an automation peer for AutomationButton.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
internal class AutomationButtonAutomationPeer : ButtonAutomationPeer
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Microsoft.Management.UI.Internal.AutomationButtonAutomationPeer" /> class.
/// </summary>
/// <param name="owner">The owner of the automation peer.</param>
public AutomationButtonAutomationPeer(Button owner)
: base(owner)
{
// This constructor intentionally left blank
}
#endregion
#region Overrides
/// <summary>
/// Gets a value that indicates whether the element is understood by the user as interactive or as contributing to the logical structure of the control in the GUI. Called by IsControlElement().
/// </summary>
/// <returns>This method always returns false.</returns>
protected override bool IsControlElementCore()
{
return this.Owner.Visibility != Visibility.Hidden;
}
#endregion
}
}

View File

@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides a <see cref="Image"/> control that is always visible in the automation tree.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
[Description("Provides a System.Windows.Controls.Image control that is always visible in the automation tree.")]
public class AutomationImage : Image
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="AutomationImage" /> class.
/// </summary>
public AutomationImage()
{
// This constructor intentionally left blank
}
#endregion
#region Overides
/// <summary>
/// Returns the <see cref="System.Windows.Automation.Peers.AutomationPeer"/> implementations for this control.
/// </summary>
/// <returns>The <see cref="System.Windows.Automation.Peers.AutomationPeer"/> implementations for this control.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
return new AutomationImageAutomationPeer(this);
}
#endregion
}
/// <summary>
/// Provides an automation peer for AutomationImage.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
internal class AutomationImageAutomationPeer : ImageAutomationPeer
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Microsoft.Management.UI.Internal.AutomationImageAutomationPeer" /> class.
/// </summary>
/// <param name="owner">The owner of the automation peer.</param>
public AutomationImageAutomationPeer(Image owner)
: base(owner)
{
// This constructor intentionally left blank
}
#endregion
#region Overrides
/// <summary>
/// Gets a value that indicates whether the element is understood by the user as interactive or as contributing to the logical structure of the control in the GUI. Called by IsControlElement().
/// </summary>
/// <returns>This method always returns false.</returns>
protected override bool IsControlElementCore()
{
return false;
}
#endregion
}
}

View File

@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides a <see cref="TextBlock"/> control that is always visible in the automation tree.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
[Description("Provides a System.Windows.Controls.TextBlock control that is always visible in the automation tree.")]
public class AutomationTextBlock : TextBlock
{
#region Structors
/// <summary>
/// Initializes a new instance of the <see cref="AutomationTextBlock" /> class.
/// </summary>
public AutomationTextBlock()
{
// This constructor intentionally left blank
}
#endregion
#region Overides
/// <summary>
/// Returns the <see cref="System.Windows.Automation.Peers.AutomationPeer"/> implementations for this control.
/// </summary>
/// <returns>The <see cref="System.Windows.Automation.Peers.AutomationPeer"/> implementations for this control.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
return new AutomationTextBlockAutomationPeer(this);
}
#endregion
}
}

View File

@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Diagnostics.CodeAnalysis;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides an automation peer for AutomationTextBlock.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
internal class AutomationTextBlockAutomationPeer : TextBlockAutomationPeer
{
#region Structors
/// <summary>
/// Initializes a new instance of the <see cref="Microsoft.Management.UI.Internal.AutomationTextBlockAutomationPeer" /> class.
/// </summary>
/// <param name="owner">The owner of the automation peer.</param>
public AutomationTextBlockAutomationPeer(TextBlock owner)
: base(owner)
{
// This constructor intentionally left blank
}
#endregion
#region Overrides
/// <summary>
/// Gets a value that indicates whether the element is understood by the user as interactive or as contributing to the logical structure of the control in the GUI. Called by IsControlElement().
/// </summary>
/// <returns>This method always returns true.</returns>
protected override bool IsControlElementCore()
{
return true;
}
/// <summary>
/// Gets the class name.
/// </summary>
/// <returns>The class name.</returns>
protected override string GetClassNameCore()
{
return this.Owner.GetType().Name;
}
#endregion
}
}

View File

@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// A class which returns the same boxed bool values.
/// </summary>
internal static class BooleanBoxes
{
private static object trueBox = true;
private static object falseBox = false;
internal static object TrueBox
{
get
{
return trueBox;
}
}
internal static object FalseBox
{
get
{
return falseBox;
}
}
internal static object Box(bool value)
{
if (value)
{
return TrueBox;
}
else
{
return FalseBox;
}
}
}
}

View File

@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Security;
using System.Text;
using System.Windows;
using System.Windows.Input;
namespace Microsoft.Management.UI.Internal
{
internal static class CommandHelper
{
internal static void ExecuteCommand(ICommand command, object parameter, IInputElement target)
{
RoutedCommand command2 = command as RoutedCommand;
if (command2 != null)
{
if (command2.CanExecute(parameter, target))
{
command2.Execute(parameter, target);
}
}
else if (command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
internal static bool CanExecuteCommand(ICommand command, object parameter, IInputElement target)
{
if (command == null)
{
return false;
}
RoutedCommand command2 = command as RoutedCommand;
if (command2 != null)
{
return command2.CanExecute(parameter, target);
}
else
{
return command.CanExecute(parameter);
}
}
}
}

View File

@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The CustomTypeComparer is responsible for holding custom comparers
/// for different types, which are in turn used to perform comparison
/// operations instead of the default IComparable comparison.
/// with a custom comparer
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public static class CustomTypeComparer
{
private static Dictionary<Type, object> comparers = new Dictionary<Type, object>();
/// <summary>
/// The static constructor.
/// </summary>
static CustomTypeComparer()
{
comparers.Add(typeof(DateTime), new DateTimeApproximationComparer());
}
/// <summary>
/// Compares two objects and returns a value indicating
/// whether one is less than, equal to, or greater than the other.
/// </summary>
/// <param name="value1">
/// The first object to compare.
/// </param>
/// <param name="value2">
/// The second object to compare.
/// </param>
/// <typeparam name="T">
/// A type implementing IComparable.
/// </typeparam>
/// <returns>
/// If value1 is less than value2, then a value less than zero is returned.
/// If value1 equals value2, than zero is returned.
/// If value1 is greater than value2, then a value greater than zero is returned.
/// </returns>
public static int Compare<T>(T value1, T value2) where T : IComparable
{
IComparer<T> comparer;
if (TryGetCustomComparer<T>(out comparer) == false)
{
return value1.CompareTo(value2);
}
return comparer.Compare(value1, value2);
}
private static bool TryGetCustomComparer<T>(out IComparer<T> comparer) where T : IComparable
{
comparer = null;
object uncastComparer = null;
if (comparers.TryGetValue(typeof(T), out uncastComparer) == false)
{
return false;
}
Debug.Assert(uncastComparer is IComparer<T>, "must be IComparer");
comparer = (IComparer<T>)uncastComparer;
return true;
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Windows;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Routed event args which provide the ability to attach an
/// arbitrary peice of data.
/// </summary>
/// <typeparam name="T">There are no restrictions on type T.</typeparam>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class DataRoutedEventArgs<T> : RoutedEventArgs
{
private T data;
/// <summary>
/// Constructs a new instance of the DataRoutedEventArgs class.
/// </summary>
/// <param name="data">The data payload to be stored.</param>
/// <param name="routedEvent">The routed event.</param>
public DataRoutedEventArgs(T data, RoutedEvent routedEvent)
{
this.data = data;
this.RoutedEvent = routedEvent;
}
/// <summary>
/// Gets a value containing the data being stored.
/// </summary>
public T Data
{
get { return this.data; }
}
}
}

View File

@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The DateTimeApproximationComparer is responsible for comparing two
/// DateTime objects at a level of precision determined by
/// the first object. The comparison either compares at the
/// date level or the date and time (down to Seconds precision).
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class DateTimeApproximationComparer : IComparer<DateTime>
{
/// <summary>
/// Compares two objects and returns a value indicating
/// whether one is less than, equal to, or greater than the other.
/// </summary>
/// <param name="value1">
/// The first object to compare.
/// </param>
/// <param name="value2">
/// The second object to compare.
/// </param>
/// <returns>
/// If value1 is less than value2, then a value less than zero is returned.
/// If value1 equals value2, than zero is returned.
/// If value1 is greater than value2, then a value greater than zero is returned.
/// </returns>
public int Compare(DateTime value1, DateTime value2)
{
DateTime roundedX;
DateTime roundedY;
GetRoundedValues(value1, value2, out roundedX, out roundedY);
return roundedX.CompareTo(roundedY);
}
private static void GetRoundedValues(DateTime value1, DateTime value2, out DateTime roundedValue1, out DateTime roundedValue2)
{
roundedValue1 = value1;
roundedValue2 = value2;
bool hasTimeComponent = HasTimeComponent(value1);
int hour = hasTimeComponent ? value1.Hour : value2.Hour;
int minute = hasTimeComponent ? value1.Minute : value2.Minute;
int second = hasTimeComponent ? value1.Second : value2.Second;
roundedValue1 = new DateTime(value1.Year, value1.Month, value1.Day, hour, minute, second);
roundedValue2 = new DateTime(value2.Year, value2.Month, value2.Day, value2.Hour, value2.Minute, value2.Second);
}
private static bool HasTimeComponent(DateTime value)
{
bool hasNoTimeComponent = true
&& value.Hour == 0
&& value.Minute == 0
&& value.Second == 0
&& value.Millisecond == 0;
return !hasNoTimeComponent;
}
}
}

View File

@ -0,0 +1,273 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// A popup which child controls can signal to be dimissed.
/// </summary>
/// <remarks>
/// If a control wants to dismiss the popup then they should execute the DismissPopupCommand on a target in the popup window.
/// </remarks>
[Localizability(LocalizationCategory.None)]
partial class DismissiblePopup
{
//
// DismissPopup routed command
//
/// <summary>
/// A command which child controls can use to tell the popup to close.
/// </summary>
public static readonly RoutedCommand DismissPopupCommand = new RoutedCommand("DismissPopup",typeof(DismissiblePopup));
static private void DismissPopupCommand_CommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
DismissiblePopup obj = (DismissiblePopup) sender;
obj.OnDismissPopupExecuted( e );
}
/// <summary>
/// Called when DismissPopup executes.
/// </summary>
/// <remarks>
/// A command which child controls can use to tell the popup to close.
/// </remarks>
protected virtual void OnDismissPopupExecuted(ExecutedRoutedEventArgs e)
{
OnDismissPopupExecutedImplementation(e);
}
partial void OnDismissPopupExecutedImplementation(ExecutedRoutedEventArgs e);
//
// CloseOnEscape dependency property
//
/// <summary>
/// Identifies the CloseOnEscape dependency property.
/// </summary>
public static readonly DependencyProperty CloseOnEscapeProperty = DependencyProperty.Register( "CloseOnEscape", typeof(bool), typeof(DismissiblePopup), new PropertyMetadata( BooleanBoxes.TrueBox, CloseOnEscapeProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value indicating whether the popup closes when ESC is pressed.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value indicating whether the popup closes when ESC is pressed.")]
[Localizability(LocalizationCategory.None)]
public bool CloseOnEscape
{
get
{
return (bool) GetValue(CloseOnEscapeProperty);
}
set
{
SetValue(CloseOnEscapeProperty,BooleanBoxes.Box(value));
}
}
static private void CloseOnEscapeProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
DismissiblePopup obj = (DismissiblePopup) o;
obj.OnCloseOnEscapeChanged( new PropertyChangedEventArgs<bool>((bool)e.OldValue, (bool)e.NewValue) );
}
/// <summary>
/// Occurs when CloseOnEscape property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<bool>> CloseOnEscapeChanged;
/// <summary>
/// Called when CloseOnEscape property changes.
/// </summary>
protected virtual void OnCloseOnEscapeChanged(PropertyChangedEventArgs<bool> e)
{
OnCloseOnEscapeChangedImplementation(e);
RaisePropertyChangedEvent(CloseOnEscapeChanged, e);
}
partial void OnCloseOnEscapeChangedImplementation(PropertyChangedEventArgs<bool> e);
//
// FocusChildOnOpen dependency property
//
/// <summary>
/// Identifies the FocusChildOnOpen dependency property.
/// </summary>
public static readonly DependencyProperty FocusChildOnOpenProperty = DependencyProperty.Register( "FocusChildOnOpen", typeof(bool), typeof(DismissiblePopup), new PropertyMetadata( BooleanBoxes.TrueBox, FocusChildOnOpenProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value indicating whether focus should be set on the child when the popup opens.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value indicating whether focus should be set on the child when the popup opens.")]
[Localizability(LocalizationCategory.None)]
public bool FocusChildOnOpen
{
get
{
return (bool) GetValue(FocusChildOnOpenProperty);
}
set
{
SetValue(FocusChildOnOpenProperty,BooleanBoxes.Box(value));
}
}
static private void FocusChildOnOpenProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
DismissiblePopup obj = (DismissiblePopup) o;
obj.OnFocusChildOnOpenChanged( new PropertyChangedEventArgs<bool>((bool)e.OldValue, (bool)e.NewValue) );
}
/// <summary>
/// Occurs when FocusChildOnOpen property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<bool>> FocusChildOnOpenChanged;
/// <summary>
/// Called when FocusChildOnOpen property changes.
/// </summary>
protected virtual void OnFocusChildOnOpenChanged(PropertyChangedEventArgs<bool> e)
{
OnFocusChildOnOpenChangedImplementation(e);
RaisePropertyChangedEvent(FocusChildOnOpenChanged, e);
}
partial void OnFocusChildOnOpenChangedImplementation(PropertyChangedEventArgs<bool> e);
//
// SetFocusOnClose dependency property
//
/// <summary>
/// Identifies the SetFocusOnClose dependency property.
/// </summary>
public static readonly DependencyProperty SetFocusOnCloseProperty = DependencyProperty.Register( "SetFocusOnClose", typeof(bool), typeof(DismissiblePopup), new PropertyMetadata( BooleanBoxes.FalseBox, SetFocusOnCloseProperty_PropertyChanged) );
/// <summary>
/// Indicates whether the focus returns to either a defined by the FocusOnCloseTarget dependency property UIElement or PlacementTarget or not.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Indicates whether the focus returns to either a defined by the FocusOnCloseTarget dependency property UIElement or PlacementTarget or not.")]
[Localizability(LocalizationCategory.None)]
public bool SetFocusOnClose
{
get
{
return (bool) GetValue(SetFocusOnCloseProperty);
}
set
{
SetValue(SetFocusOnCloseProperty,BooleanBoxes.Box(value));
}
}
static private void SetFocusOnCloseProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
DismissiblePopup obj = (DismissiblePopup) o;
obj.OnSetFocusOnCloseChanged( new PropertyChangedEventArgs<bool>((bool)e.OldValue, (bool)e.NewValue) );
}
/// <summary>
/// Occurs when SetFocusOnClose property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<bool>> SetFocusOnCloseChanged;
/// <summary>
/// Called when SetFocusOnClose property changes.
/// </summary>
protected virtual void OnSetFocusOnCloseChanged(PropertyChangedEventArgs<bool> e)
{
OnSetFocusOnCloseChangedImplementation(e);
RaisePropertyChangedEvent(SetFocusOnCloseChanged, e);
}
partial void OnSetFocusOnCloseChangedImplementation(PropertyChangedEventArgs<bool> e);
//
// SetFocusOnCloseElement dependency property
//
/// <summary>
/// Identifies the SetFocusOnCloseElement dependency property.
/// </summary>
public static readonly DependencyProperty SetFocusOnCloseElementProperty = DependencyProperty.Register( "SetFocusOnCloseElement", typeof(UIElement), typeof(DismissiblePopup), new PropertyMetadata( null, SetFocusOnCloseElementProperty_PropertyChanged) );
/// <summary>
/// If the SetFocusOnClose property is set True and this property is set to a valid UIElement, focus returns to this UIElement after the DismissiblePopup is closed.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("If the SetFocusOnClose property is set True and this property is set to a valid UIElement, focus returns to this UIElement after the DismissiblePopup is closed.")]
[Localizability(LocalizationCategory.None)]
public UIElement SetFocusOnCloseElement
{
get
{
return (UIElement) GetValue(SetFocusOnCloseElementProperty);
}
set
{
SetValue(SetFocusOnCloseElementProperty,value);
}
}
static private void SetFocusOnCloseElementProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
DismissiblePopup obj = (DismissiblePopup) o;
obj.OnSetFocusOnCloseElementChanged( new PropertyChangedEventArgs<UIElement>((UIElement)e.OldValue, (UIElement)e.NewValue) );
}
/// <summary>
/// Occurs when SetFocusOnCloseElement property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<UIElement>> SetFocusOnCloseElementChanged;
/// <summary>
/// Called when SetFocusOnCloseElement property changes.
/// </summary>
protected virtual void OnSetFocusOnCloseElementChanged(PropertyChangedEventArgs<UIElement> e)
{
OnSetFocusOnCloseElementChangedImplementation(e);
RaisePropertyChangedEvent(SetFocusOnCloseElementChanged, e);
}
partial void OnSetFocusOnCloseElementChangedImplementation(PropertyChangedEventArgs<UIElement> e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
//
// Static constructor
//
/// <summary>
/// Called when the type is initialized.
/// </summary>
static DismissiblePopup()
{
CommandManager.RegisterClassCommandBinding( typeof(DismissiblePopup), new CommandBinding( DismissiblePopup.DismissPopupCommand, DismissPopupCommand_CommandExecuted ));
StaticConstructorImplementation();
}
static partial void StaticConstructorImplementation();
}
}
#endregion

View File

@ -0,0 +1,150 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
/// <content>
/// Partial class implementation for DismissiblePopup control.
/// </content>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class DismissiblePopup : Popup
{
/// <summary>
/// Constructs an instance of DismissablePopup.
/// </summary>
public DismissiblePopup() : base()
{
// nothing
}
private delegate void FocusChildDelegate();
/// <summary>
/// Responds to the condition in which the value of the IsOpen property changes from false to true.
/// </summary>
/// <param name="e">The event arguments.</param>
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
if (this.FocusChildOnOpen)
{
this.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Loaded,
new FocusChildDelegate(this.FocusChild));
}
this.SetupAutomationIdBinding();
}
/// <summary>
/// Responds when the value of the IsOpen property changes from to true to false.
/// </summary>
/// <param name="e">The event arguments.</param>
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (this.SetFocusOnClose)
{
// Find a control to set focus on.
if (this.SetFocusOnCloseElement != null)
{
// The focus target is set explicitly.
this.SetFocus(this.SetFocusOnCloseElement);
}
else if (this.PlacementTarget != null)
{
// Use PlacementTarget as a first chance option.
this.SetFocus(this.PlacementTarget);
}
else
{
// Use parent UIObject when neither FocusOnCloseTarget nor PlacementTarget is set.
UIElement parent = this.Parent as UIElement;
if (parent != null)
{
this.SetFocus(parent);
}
}
}
}
private void SetFocus(UIElement element)
{
if (element.Focusable)
{
element.Focus();
}
else
{
element.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
}
private void SetupAutomationIdBinding()
{
var popupRoot = this.FindPopupRoot();
var binding = new Binding();
binding.Source = this;
binding.Path = new PropertyPath(AutomationProperties.AutomationIdProperty);
popupRoot.SetBinding(AutomationProperties.AutomationIdProperty, binding);
}
private FrameworkElement FindPopupRoot()
{
DependencyObject element = this.Child;
while (element.GetType().Name.Equals("PopupRoot", StringComparison.Ordinal) == false)
{
element = VisualTreeHelper.GetParent(element);
}
Debug.Assert(element != null, "element not null");
return (FrameworkElement)element;
}
/// <summary>
/// Provides class handling for the KeyDown routed event that occurs when the user presses a key while this control has focus.
/// </summary>
/// <param name="e">The event data.</param>
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
{
////
// Close the popup if ESC is pressed
////
if (e.Key == System.Windows.Input.Key.Escape && this.CloseOnEscape)
{
this.IsOpen = false;
}
else
{
base.OnKeyDown(e);
}
}
partial void OnDismissPopupExecutedImplementation(ExecutedRoutedEventArgs e)
{
this.IsOpen = false;
}
private void FocusChild()
{
if (this.Child != null)
{
this.Child.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
}
}
}

View File

@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides a base automation peer for FrameworkElement controls.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class ExtendedFrameworkElementAutomationPeer : FrameworkElementAutomationPeer
{
#region Fields
/// <summary>
/// Gets or sets the control type of the element that is associated with this automation peer.
/// </summary>
private AutomationControlType controlType = AutomationControlType.Custom;
/// <summary>
/// Gets or sets a value that indicates whether the control should show in the logical tree.
/// </summary>
private bool isControlElement = true;
#endregion
#region Structors
/// <summary>
/// Initializes a new instance of the <see cref="ExtendedFrameworkElementAutomationPeer" /> class.
/// </summary>
/// <param name="owner">The owner of the automation peer.</param>
public ExtendedFrameworkElementAutomationPeer(FrameworkElement owner)
: base(owner)
{
// This constructor intentionally left blank
}
/// <summary>
/// Initializes a new instance of the <see cref="ExtendedFrameworkElementAutomationPeer" /> class.
/// </summary>
/// <param name="owner">The owner of the automation peer.</param>
/// <param name="controlType">The control type of the element that is associated with the automation peer.</param>
public ExtendedFrameworkElementAutomationPeer(FrameworkElement owner, AutomationControlType controlType)
: this(owner)
{
this.controlType = controlType;
}
/// <summary>
/// Initializes a new instance of the <see cref="ExtendedFrameworkElementAutomationPeer" /> class.
/// </summary>
/// <param name="owner">The owner of the automation peer.</param>
/// <param name="controlType">The control type of the element that is associated with the automation peer.</param>
/// <param name="isControlElement">Whether the element should show in the logical tree.</param>
public ExtendedFrameworkElementAutomationPeer(FrameworkElement owner, AutomationControlType controlType, bool isControlElement)
: this(owner, controlType)
{
this.isControlElement = isControlElement;
}
#endregion
#region Overrides
/// <summary>
/// Gets the class name.
/// </summary>
/// <returns>The class name.</returns>
protected override string GetClassNameCore()
{
return this.Owner.GetType().Name;
}
/// <summary>
/// Gets the control type of the element that is associated with the automation peer.
/// </summary>
/// <returns>Returns the control type of the element that is associated with the automation peer.</returns>
protected override AutomationControlType GetAutomationControlTypeCore()
{
return this.controlType;
}
/// <summary>
/// Gets a value that indicates whether the element is understood by the user as interactive or as contributing to the logical structure of the control in the GUI. Called by IsControlElement().
/// </summary>
/// <returns>This method always returns true.</returns>
protected override bool IsControlElementCore()
{
return this.isControlElement;
}
#endregion
}
}

View File

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Windows;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// An interface designed to provide updates about an asynchronous operation.
/// If the UI is data bound to the properties in this interface then INotifyPropertyChanged should
/// be implemented by the type implementing IAsyncProgress so the UI can get notification of the properties
/// being changed.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public interface IAsyncProgress
{
/// <summary>
/// Gets a value indicating whether the async operation is currently running.
/// </summary>
bool OperationInProgress
{
get;
}
/// <summary>
/// Gets a the error for the async operation. This field is only valid if
/// OperationInProgress is false. null indicates there was no error.
/// </summary>
Exception OperationError
{
get;
}
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Defines an interface for a factory that creates
/// StateDescriptors.
/// </summary>
/// <typeparam name="T">The type T used by the StateDescriptor.</typeparam>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public interface IStateDescriptorFactory<T>
{
/// <summary>
/// Creates a new StateDescriptor based upon custom
/// logic.
/// </summary>
/// <returns>A new StateDescriptor.</returns>
StateDescriptor<T> Create();
}
}

View File

@ -0,0 +1,86 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Takes a value and returns the largest value which is a integral amount of the second value.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IntegralConverter : IMultiValueConverter
{
/// <summary>
/// Takes a value and returns the largest value which is a integral amount of the second value.
/// </summary>
/// <param name="values">
/// The first value is the source. The second is the factor.
/// </param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The padding to subtract from the first value.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>
/// The integral value.
/// </returns>
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != 2)
{
throw new ArgumentException("Two values expected", "values");
}
if (values[0] == DependencyProperty.UnsetValue ||
values[1] == DependencyProperty.UnsetValue)
{
return DependencyProperty.UnsetValue;
}
var source = (double)values[0];
var factor = (double)values[1];
double padding = 0;
if (parameter != null)
{
padding = double.Parse((string)parameter, CultureInfo.InvariantCulture);
}
var newSource = source - padding;
if (newSource < factor)
{
return source;
}
var remainder = newSource % factor;
var result = newSource - remainder;
return result;
}
/// <summary>
/// This method is not used.
/// </summary>
/// <param name="value">The parameter is not used.</param>
/// <param name="targetTypes">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The parameter is not used.</returns>
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Takes a bool value and returns the inverse.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class InverseBooleanConverter : IValueConverter
{
/// <summary>
/// Converts a boolean value to be it's inverse.
/// </summary>
/// <param name="value">The source value.</param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The inverted boolean value.</returns>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
var boolValue = (bool)value;
return !boolValue;
}
/// <summary>
/// This method is not used.
/// </summary>
/// <param name="value">The parameter is not used.</param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The parameter is not used.</returns>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Windows;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Takes two objects and determines whether they are equal.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IsEqualConverter : IMultiValueConverter
{
/// <summary>
/// Takes two items and determines whether they are equal.
/// </summary>
/// <param name="values">
/// Two objects of any type.
/// </param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>
/// True if-and-only-if the two objects are equal per Object.Equals().
/// Null is equal only to null.
/// </returns>
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != 2)
{
throw new ArgumentException("Two values expected", "values");
}
object item1 = values[0];
object item2 = values[1];
if (item1 == null)
{
return item2 == null;
}
if (item2 == null)
{
return false;
}
bool equal = item1.Equals(item2);
return equal;
}
/// <summary>
/// This method is not used.
/// </summary>
/// <param name="value">The parameter is not used.</param>
/// <param name="targetTypes">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The parameter is not used.</returns>
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IsNotNullConverter is responsible for converting a value into
/// a boolean indicting whether the value is not null.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IsNotNullConverter : IValueConverter
{
#region IValueConverter Members
/// <summary>
/// Determines if value is not null.
/// </summary>
/// <param name="value">The object to check.</param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>Returns true if value is not null, false otherwise.</returns>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value != null;
}
/// <summary>
/// This method is not used.
/// </summary>
/// <param name="value">The parameter is not used.</param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The parameter is not used.</returns>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
#endregion
}
}

View File

@ -0,0 +1,149 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Input;
namespace Microsoft.Management.UI.Internal
{
internal enum LogicalDirection
{
None,
Left,
Right
}
internal static class KeyboardHelp
{
/// <summary>
/// Gets the logical direction for a key, taking into account RTL settings.
/// </summary>
/// <param name="element">The element to get FlowDirection from.</param>
/// <param name="key">The key pressed.</param>
/// <returns>The logical direction.</returns>
public static LogicalDirection GetLogicalDirection(DependencyObject element, Key key)
{
Debug.Assert(element != null, "element not null");
bool rightToLeft = IsElementRightToLeft(element);
switch (key)
{
case Key.Right:
if (rightToLeft)
{
return LogicalDirection.Left;
}
else
{
return LogicalDirection.Right;
}
case Key.Left:
if (rightToLeft)
{
return LogicalDirection.Right;
}
else
{
return LogicalDirection.Left;
}
default:
return LogicalDirection.None;
}
}
/// <summary>
/// Gets the focus direction for a key, taking into account RTL settings.
/// </summary>
/// <param name="element">The element to get FlowDirection from.</param>
/// <param name="key">The key pressed.</param>
/// <returns>The focus direction.</returns>
public static FocusNavigationDirection GetNavigationDirection(DependencyObject element, Key key)
{
Debug.Assert(element != null, "element not null");
Debug.Assert(IsFlowDirectionKey(key));
bool rightToLeft = IsElementRightToLeft(element);
switch (key)
{
case Key.Right:
if (rightToLeft)
{
return FocusNavigationDirection.Left;
}
else
{
return FocusNavigationDirection.Right;
}
case Key.Left:
if (rightToLeft)
{
return FocusNavigationDirection.Right;
}
else
{
return FocusNavigationDirection.Left;
}
case Key.Down:
return FocusNavigationDirection.Down;
case Key.Up:
return FocusNavigationDirection.Up;
default:
Debug.Fail("Non-direction key specified");
return FocusNavigationDirection.First;
}
}
/// <summary>
/// Determines if the control key is pressed.
/// </summary>
/// <returns>True if a control is is pressed.</returns>
public static bool IsControlPressed()
{
if (ModifierKeys.Control == (Keyboard.Modifiers & ModifierKeys.Control))
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// Determines if the key is a navigation key.
/// </summary>
/// <param name="key">The key pressed.</param>
/// <returns>True if the key is a navigation key.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
private static bool IsFlowDirectionKey(Key key)
{
switch (key)
{
case Key.Right:
case Key.Left:
case Key.Down:
case Key.Up:
return true;
default:
return false;
}
}
private static bool IsElementRightToLeft(DependencyObject element)
{
FlowDirection flowDirection = FrameworkElement.GetFlowDirection(element);
bool rightToLeft = flowDirection == FlowDirection.RightToLeft;
return rightToLeft;
}
}
}

View File

@ -0,0 +1,487 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// <auto-generated>
// This code was generated by a tool. DO NOT EDIT
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
#region StyleCop Suppression - generated code
using System;
using System.Collections;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// This control presents a dropdown listbox with associated organizing actions that can be performed on it.
/// </summary>
/// <remarks>
///
///
/// If a custom template is provided for this control, then the template MUST provide the following template parts:
///
/// PART_Picker - A required template part which must be of type PickerBase. This control provides basic functionality for Picker-like controls.
///
/// </remarks>
[TemplatePart(Name="PART_Picker", Type=typeof(PickerBase))]
[Localizability(LocalizationCategory.None)]
partial class ListOrganizer
{
//
// Fields
//
private PickerBase picker;
//
// ItemDeleted RoutedEvent
//
/// <summary>
/// Identifies the ItemDeleted RoutedEvent.
/// </summary>
public static readonly RoutedEvent ItemDeletedEvent = EventManager.RegisterRoutedEvent("ItemDeleted",RoutingStrategy.Bubble,typeof(EventHandler<DataRoutedEventArgs<object>>),typeof(ListOrganizer));
/// <summary>
/// Occurs when an item is deleted from the list.
/// </summary>
public event EventHandler<DataRoutedEventArgs<object>> ItemDeleted
{
add
{
AddHandler(ItemDeletedEvent,value);
}
remove
{
RemoveHandler(ItemDeletedEvent,value);
}
}
//
// ItemSelected RoutedEvent
//
/// <summary>
/// Identifies the ItemSelected RoutedEvent.
/// </summary>
public static readonly RoutedEvent ItemSelectedEvent = EventManager.RegisterRoutedEvent("ItemSelected",RoutingStrategy.Bubble,typeof(EventHandler<DataRoutedEventArgs<object>>),typeof(ListOrganizer));
/// <summary>
/// Occurs when an item is selected in the list.
/// </summary>
public event EventHandler<DataRoutedEventArgs<object>> ItemSelected
{
add
{
AddHandler(ItemSelectedEvent,value);
}
remove
{
RemoveHandler(ItemSelectedEvent,value);
}
}
//
// DeleteItem routed command
//
/// <summary>
/// Informs the ListOrganizer that it should delete the item passed.
/// </summary>
public static readonly RoutedCommand DeleteItemCommand = new RoutedCommand("DeleteItem",typeof(ListOrganizer));
static private void DeleteItemCommand_CommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
ListOrganizer obj = (ListOrganizer) sender;
obj.OnDeleteItemExecuted( e );
}
/// <summary>
/// Called when DeleteItem executes.
/// </summary>
/// <remarks>
/// Informs the ListOrganizer that it should delete the item passed.
/// </remarks>
protected virtual void OnDeleteItemExecuted(ExecutedRoutedEventArgs e)
{
OnDeleteItemExecutedImplementation(e);
}
partial void OnDeleteItemExecutedImplementation(ExecutedRoutedEventArgs e);
//
// SelectItem routed command
//
/// <summary>
/// Informs the ListOrganizer that it should select the item passed.
/// </summary>
public static readonly RoutedCommand SelectItemCommand = new RoutedCommand("SelectItem",typeof(ListOrganizer));
static private void SelectItemCommand_CommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
ListOrganizer obj = (ListOrganizer) sender;
obj.OnSelectItemExecuted( e );
}
/// <summary>
/// Called when SelectItem executes.
/// </summary>
/// <remarks>
/// Informs the ListOrganizer that it should select the item passed.
/// </remarks>
protected virtual void OnSelectItemExecuted(ExecutedRoutedEventArgs e)
{
OnSelectItemExecutedImplementation(e);
}
partial void OnSelectItemExecutedImplementation(ExecutedRoutedEventArgs e);
//
// DropDownButtonTemplate dependency property
//
/// <summary>
/// Identifies the DropDownButtonTemplate dependency property.
/// </summary>
public static readonly DependencyProperty DropDownButtonTemplateProperty = DependencyProperty.Register( "DropDownButtonTemplate", typeof(ControlTemplate), typeof(ListOrganizer), new PropertyMetadata( null, DropDownButtonTemplateProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value that controls the visual tree of the DropDown button.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value that controls the visual tree of the DropDown button.")]
[Localizability(LocalizationCategory.None)]
public ControlTemplate DropDownButtonTemplate
{
get
{
return (ControlTemplate) GetValue(DropDownButtonTemplateProperty);
}
set
{
SetValue(DropDownButtonTemplateProperty,value);
}
}
static private void DropDownButtonTemplateProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ListOrganizer obj = (ListOrganizer) o;
obj.OnDropDownButtonTemplateChanged( new PropertyChangedEventArgs<ControlTemplate>((ControlTemplate)e.OldValue, (ControlTemplate)e.NewValue) );
}
/// <summary>
/// Occurs when DropDownButtonTemplate property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<ControlTemplate>> DropDownButtonTemplateChanged;
/// <summary>
/// Called when DropDownButtonTemplate property changes.
/// </summary>
protected virtual void OnDropDownButtonTemplateChanged(PropertyChangedEventArgs<ControlTemplate> e)
{
OnDropDownButtonTemplateChangedImplementation(e);
RaisePropertyChangedEvent(DropDownButtonTemplateChanged, e);
}
partial void OnDropDownButtonTemplateChangedImplementation(PropertyChangedEventArgs<ControlTemplate> e);
//
// DropDownStyle dependency property
//
/// <summary>
/// Identifies the DropDownStyle dependency property.
/// </summary>
public static readonly DependencyProperty DropDownStyleProperty = DependencyProperty.Register( "DropDownStyle", typeof(Style), typeof(ListOrganizer), new PropertyMetadata( null, DropDownStyleProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the style of the drop-down.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the style of the drop-down.")]
[Localizability(LocalizationCategory.None)]
public Style DropDownStyle
{
get
{
return (Style) GetValue(DropDownStyleProperty);
}
set
{
SetValue(DropDownStyleProperty,value);
}
}
static private void DropDownStyleProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ListOrganizer obj = (ListOrganizer) o;
obj.OnDropDownStyleChanged( new PropertyChangedEventArgs<Style>((Style)e.OldValue, (Style)e.NewValue) );
}
/// <summary>
/// Occurs when DropDownStyle property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<Style>> DropDownStyleChanged;
/// <summary>
/// Called when DropDownStyle property changes.
/// </summary>
protected virtual void OnDropDownStyleChanged(PropertyChangedEventArgs<Style> e)
{
OnDropDownStyleChangedImplementation(e);
RaisePropertyChangedEvent(DropDownStyleChanged, e);
}
partial void OnDropDownStyleChangedImplementation(PropertyChangedEventArgs<Style> e);
//
// HighlightedItem dependency property
//
/// <summary>
/// Identifies the HighlightedItem dependency property.
/// </summary>
public static readonly DependencyProperty HighlightedItemProperty = DependencyProperty.Register( "HighlightedItem", typeof(object), typeof(ListOrganizer), new PropertyMetadata( null, HighlightedItemProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value that controls the highlighted item in the list.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value that controls the highlighted item in the list.")]
[Localizability(LocalizationCategory.None)]
public object HighlightedItem
{
get
{
return (object) GetValue(HighlightedItemProperty);
}
set
{
SetValue(HighlightedItemProperty,value);
}
}
static private void HighlightedItemProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ListOrganizer obj = (ListOrganizer) o;
obj.OnHighlightedItemChanged( new PropertyChangedEventArgs<object>((object)e.OldValue, (object)e.NewValue) );
}
/// <summary>
/// Occurs when HighlightedItem property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<object>> HighlightedItemChanged;
/// <summary>
/// Called when HighlightedItem property changes.
/// </summary>
protected virtual void OnHighlightedItemChanged(PropertyChangedEventArgs<object> e)
{
OnHighlightedItemChangedImplementation(e);
RaisePropertyChangedEvent(HighlightedItemChanged, e);
}
partial void OnHighlightedItemChangedImplementation(PropertyChangedEventArgs<object> e);
//
// ItemsSource dependency property
//
/// <summary>
/// Identifies the ItemsSource dependency property.
/// </summary>
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register( "ItemsSource", typeof(IEnumerable), typeof(ListOrganizer), new PropertyMetadata( null, ItemsSourceProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value that controls the items in the list.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value that controls the items in the list.")]
[Localizability(LocalizationCategory.None)]
public IEnumerable ItemsSource
{
get
{
return (IEnumerable) GetValue(ItemsSourceProperty);
}
set
{
SetValue(ItemsSourceProperty,value);
}
}
static private void ItemsSourceProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ListOrganizer obj = (ListOrganizer) o;
obj.OnItemsSourceChanged( new PropertyChangedEventArgs<IEnumerable>((IEnumerable)e.OldValue, (IEnumerable)e.NewValue) );
}
/// <summary>
/// Occurs when ItemsSource property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<IEnumerable>> ItemsSourceChanged;
/// <summary>
/// Called when ItemsSource property changes.
/// </summary>
protected virtual void OnItemsSourceChanged(PropertyChangedEventArgs<IEnumerable> e)
{
OnItemsSourceChangedImplementation(e);
RaisePropertyChangedEvent(ItemsSourceChanged, e);
}
partial void OnItemsSourceChangedImplementation(PropertyChangedEventArgs<IEnumerable> e);
//
// NoItemsText dependency property
//
/// <summary>
/// Identifies the NoItemsText dependency property.
/// </summary>
public static readonly DependencyProperty NoItemsTextProperty = DependencyProperty.Register( "NoItemsText", typeof(string), typeof(ListOrganizer), new PropertyMetadata( string.Empty, NoItemsTextProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value that appears to inform the user that there are no items in the list.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value that appears to inform the user that there are no items in the list.")]
[Localizability(LocalizationCategory.Text, Modifiability=Modifiability.Modifiable, Readability=Readability.Readable)]
public string NoItemsText
{
get
{
return (string) GetValue(NoItemsTextProperty);
}
set
{
SetValue(NoItemsTextProperty,value);
}
}
static private void NoItemsTextProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ListOrganizer obj = (ListOrganizer) o;
obj.OnNoItemsTextChanged( new PropertyChangedEventArgs<string>((string)e.OldValue, (string)e.NewValue) );
}
/// <summary>
/// Occurs when NoItemsText property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<string>> NoItemsTextChanged;
/// <summary>
/// Called when NoItemsText property changes.
/// </summary>
protected virtual void OnNoItemsTextChanged(PropertyChangedEventArgs<string> e)
{
OnNoItemsTextChangedImplementation(e);
RaisePropertyChangedEvent(NoItemsTextChanged, e);
}
partial void OnNoItemsTextChangedImplementation(PropertyChangedEventArgs<string> e);
//
// TextContentPropertyName dependency property
//
/// <summary>
/// Identifies the TextContentPropertyName dependency property.
/// </summary>
public static readonly DependencyProperty TextContentPropertyNameProperty = DependencyProperty.Register( "TextContentPropertyName", typeof(string), typeof(ListOrganizer), new PropertyMetadata( string.Empty, TextContentPropertyNameProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value which dictates what binding is used to provide content for the items in the list.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value which dictates what binding is used to provide content for the items in the list.")]
[Localizability(LocalizationCategory.None)]
public string TextContentPropertyName
{
get
{
return (string) GetValue(TextContentPropertyNameProperty);
}
set
{
SetValue(TextContentPropertyNameProperty,value);
}
}
static private void TextContentPropertyNameProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ListOrganizer obj = (ListOrganizer) o;
obj.OnTextContentPropertyNameChanged( new PropertyChangedEventArgs<string>((string)e.OldValue, (string)e.NewValue) );
}
/// <summary>
/// Occurs when TextContentPropertyName property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<string>> TextContentPropertyNameChanged;
/// <summary>
/// Called when TextContentPropertyName property changes.
/// </summary>
protected virtual void OnTextContentPropertyNameChanged(PropertyChangedEventArgs<string> e)
{
OnTextContentPropertyNameChangedImplementation(e);
RaisePropertyChangedEvent(TextContentPropertyNameChanged, e);
}
partial void OnTextContentPropertyNameChangedImplementation(PropertyChangedEventArgs<string> e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
//
// OnApplyTemplate
//
/// <summary>
/// Called when ApplyTemplate is called.
/// </summary>
public override void OnApplyTemplate()
{
PreOnApplyTemplate();
base.OnApplyTemplate();
this.picker = WpfHelp.GetTemplateChild<PickerBase>(this,"PART_Picker");
PostOnApplyTemplate();
}
partial void PreOnApplyTemplate();
partial void PostOnApplyTemplate();
//
// Static constructor
//
/// <summary>
/// Called when the type is initialized.
/// </summary>
static ListOrganizer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ListOrganizer), new FrameworkPropertyMetadata(typeof(ListOrganizer)));
CommandManager.RegisterClassCommandBinding( typeof(ListOrganizer), new CommandBinding( ListOrganizer.DeleteItemCommand, DeleteItemCommand_CommandExecuted ));
CommandManager.RegisterClassCommandBinding( typeof(ListOrganizer), new CommandBinding( ListOrganizer.SelectItemCommand, SelectItemCommand_CommandExecuted ));
StaticConstructorImplementation();
}
static partial void StaticConstructorImplementation();
}
}
#endregion

View File

@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Picker control that displays a list with basic editing functionality.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class ListOrganizer : ContentControl
{
/// <summary>
/// Creates a new instance of the ListOrganizer class.
/// </summary>
public ListOrganizer()
{
// empty
}
/// <summary>
/// Prevents keyboard focus from leaving the dropdown.
/// </summary>
/// <param name="e">The event args.</param>
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Key == Key.Up ||
e.Key == Key.Down ||
e.Key == Key.Left ||
e.Key == Key.Right)
{
e.Handled = true;
}
}
partial void OnSelectItemExecutedImplementation(ExecutedRoutedEventArgs e)
{
if (e.Parameter == null)
{
throw new ArgumentException("e.Parameter is null", "e");
}
this.RaiseEvent(new DataRoutedEventArgs<object>(e.Parameter, ItemSelectedEvent));
this.picker.IsOpen = false;
}
partial void OnDeleteItemExecutedImplementation(ExecutedRoutedEventArgs e)
{
if (e.Parameter == null)
{
throw new ArgumentException("e.Parameter is null", "e");
}
this.RaiseEvent(new DataRoutedEventArgs<object>(e.Parameter, ItemDeletedEvent));
}
}
}

View File

@ -0,0 +1,151 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// <auto-generated>
// This code was generated by a tool. DO NOT EDIT
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
#region StyleCop Suppression - generated code
using System;
using System.Collections;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// This control is the row in the ListOrganizer and offers editing functionality.
/// </summary>
/// <remarks>
///
///
/// If a custom template is provided for this control, then the template MUST provide the following template parts:
///
/// PART_DeleteButton - A required template part which must be of type Button. Button which keeps track of whether the row should be deleted.
/// PART_EditBox - A required template part which must be of type TextBox. Displays the text content in an editable manner.
/// PART_LinkButton - A required template part which must be of type Button. Displays the text content in a read-only manner and allows single click selection.
/// PART_RenameButton - A required template part which must be of type ToggleButton. Button which allows for editing the name of the item.
///
/// </remarks>
[TemplatePart(Name="PART_DeleteButton", Type=typeof(Button))]
[TemplatePart(Name="PART_EditBox", Type=typeof(TextBox))]
[TemplatePart(Name="PART_LinkButton", Type=typeof(Button))]
[TemplatePart(Name="PART_RenameButton", Type=typeof(ToggleButton))]
[Localizability(LocalizationCategory.None)]
partial class ListOrganizerItem
{
//
// Fields
//
private Button deleteButton;
private TextBox editBox;
private Button linkButton;
private ToggleButton renameButton;
//
// TextContentPropertyName dependency property
//
/// <summary>
/// Identifies the TextContentPropertyName dependency property.
/// </summary>
public static readonly DependencyProperty TextContentPropertyNameProperty = DependencyProperty.Register( "TextContentPropertyName", typeof(string), typeof(ListOrganizerItem), new PropertyMetadata( string.Empty, TextContentPropertyNameProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value which dictates what binding is used to provide content for the items in the list.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value which dictates what binding is used to provide content for the items in the list.")]
[Localizability(LocalizationCategory.None)]
public string TextContentPropertyName
{
get
{
return (string) GetValue(TextContentPropertyNameProperty);
}
set
{
SetValue(TextContentPropertyNameProperty,value);
}
}
static private void TextContentPropertyNameProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ListOrganizerItem obj = (ListOrganizerItem) o;
obj.OnTextContentPropertyNameChanged( new PropertyChangedEventArgs<string>((string)e.OldValue, (string)e.NewValue) );
}
/// <summary>
/// Occurs when TextContentPropertyName property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<string>> TextContentPropertyNameChanged;
/// <summary>
/// Called when TextContentPropertyName property changes.
/// </summary>
protected virtual void OnTextContentPropertyNameChanged(PropertyChangedEventArgs<string> e)
{
OnTextContentPropertyNameChangedImplementation(e);
RaisePropertyChangedEvent(TextContentPropertyNameChanged, e);
}
partial void OnTextContentPropertyNameChangedImplementation(PropertyChangedEventArgs<string> e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
//
// OnApplyTemplate
//
/// <summary>
/// Called when ApplyTemplate is called.
/// </summary>
public override void OnApplyTemplate()
{
PreOnApplyTemplate();
base.OnApplyTemplate();
this.deleteButton = WpfHelp.GetTemplateChild<Button>(this,"PART_DeleteButton");
this.editBox = WpfHelp.GetTemplateChild<TextBox>(this,"PART_EditBox");
this.linkButton = WpfHelp.GetTemplateChild<Button>(this,"PART_LinkButton");
this.renameButton = WpfHelp.GetTemplateChild<ToggleButton>(this,"PART_RenameButton");
PostOnApplyTemplate();
}
partial void PreOnApplyTemplate();
partial void PostOnApplyTemplate();
//
// Static constructor
//
/// <summary>
/// Called when the type is initialized.
/// </summary>
static ListOrganizerItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ListOrganizerItem), new FrameworkPropertyMetadata(typeof(ListOrganizerItem)));
StaticConstructorImplementation();
}
static partial void StaticConstructorImplementation();
}
}
#endregion

View File

@ -0,0 +1,260 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
namespace Microsoft.Management.UI.Internal
{
/// <content>
/// Partial class implementation for ListOrganizerItem control.
/// </content>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class ListOrganizerItem : Control
{
private string startingText;
private FrameworkElement templatedParent;
/// <summary>
/// Creates a new instance of the ListOrganizerItem class.
/// </summary>
public ListOrganizerItem()
{
// empty
}
/// <summary>
/// Gets a value indicating whether the item is in edit mode.
/// </summary>
public bool IsInEditMode
{
get
{
return (this.renameButton != null) ? this.renameButton.IsChecked.Value : false;
}
}
/// <summary>
/// Selects the current item.
/// </summary>
public void Select()
{
if (!this.IsLoaded)
{
this.Loaded += new RoutedEventHandler(this.ListOrganizerItem_Loaded_SelectItem);
this.ApplyTemplate();
return;
}
CommandHelper.ExecuteCommand(this.linkButton.Command, this.linkButton.CommandParameter, this.linkButton.CommandTarget);
}
/// <summary>
/// Allows modification of the item.
/// </summary>
public void Rename()
{
this.renameButton.IsChecked = true;
}
/// <summary>
/// Deletes the item.
/// </summary>
public void Delete()
{
CommandHelper.ExecuteCommand(this.deleteButton.Command, this.deleteButton.CommandParameter, this.deleteButton.CommandTarget);
}
/// <summary>
/// Provides class handling for the KeyDown routed event that
/// occurs when the user presses a key while this control has focus.
/// </summary>
/// <param name="e">The event data.</param>
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (this.IsInEditMode)
{
return;
}
switch (e.Key)
{
case Key.Insert:
this.Rename();
e.Handled = true;
break;
case Key.Delete:
this.Delete();
e.Handled = true;
break;
case Key.Enter:
case Key.Space:
this.Select();
e.Handled = true;
break;
default:
break;
}
}
private void TemplatedParent_OnKeyDown(object sender, KeyEventArgs e)
{
this.OnKeyDown(e);
}
private void ListOrganizerItem_Loaded_SelectItem(object sender, RoutedEventArgs e)
{
this.Loaded -= this.ListOrganizerItem_Loaded_SelectItem;
this.Select();
}
#region EditBox Event Handlers
private void EditBox_LostFocus(object sender, RoutedEventArgs e)
{
this.ChangeFromEditToDisplayMode();
}
private void EditBox_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Enter:
this.ChangeFromEditToDisplayMode();
e.Handled = true;
break;
case Key.Escape:
this.RevertTextAndChangeFromEditToDisplayMode();
e.Handled = true;
break;
default:
break;
}
}
private void RevertTextAndChangeFromEditToDisplayMode()
{
this.editBox.Text = this.startingText;
this.ChangeFromEditToDisplayMode();
}
private void ChangeFromEditToDisplayMode()
{
// NOTE : This is to resolve a race condition where clicking
// on the rename button causes the the edit box to change and
// then have re-toggle.
DependencyObject d = Mouse.DirectlyOver as DependencyObject;
if (d == null || !(this.renameButton.IsAncestorOf(d) && Mouse.LeftButton == MouseButtonState.Pressed))
{
this.renameButton.IsChecked = false;
}
if (!this.IsKeyboardFocusWithin)
{
this.Focus();
}
}
private void EditBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.editBox.IsVisible)
{
this.startingText = this.editBox.Text;
this.editBox.Focus();
this.editBox.SelectAll();
}
}
#endregion EditBox Event Handlers
partial void OnTextContentPropertyNameChangedImplementation(PropertyChangedEventArgs<string> e)
{
this.UpdateTextContentBindings();
}
private void UpdateTextContentBindings()
{
if (!this.IsLoaded)
{
this.Loaded += new RoutedEventHandler(this.ListOrganizerItem_Loaded_UpdateTextContentBindings);
this.ApplyTemplate();
return;
}
if (!string.IsNullOrEmpty(this.TextContentPropertyName))
{
Binding b = new Binding(this.TextContentPropertyName);
b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
this.linkButton.SetBinding(Button.ContentProperty, b);
this.editBox.SetBinding(TextBox.TextProperty, b);
}
else
{
BindingOperations.ClearBinding(this.linkButton, Button.ContentProperty);
BindingOperations.ClearBinding(this.editBox, TextBox.TextProperty);
}
}
private void ListOrganizerItem_Loaded_UpdateTextContentBindings(object sender, RoutedEventArgs e)
{
this.Loaded -= this.ListOrganizerItem_Loaded_UpdateTextContentBindings;
this.UpdateTextContentBindings();
}
#region OnApplyTemplate Helpers
partial void PreOnApplyTemplate()
{
this.DetachFromVisualTree();
}
partial void PostOnApplyTemplate()
{
this.AttachToVisualTree();
}
private void AttachToVisualTree()
{
this.editBox.IsVisibleChanged += new DependencyPropertyChangedEventHandler(this.EditBox_IsVisibleChanged);
this.editBox.KeyDown += new KeyEventHandler(this.EditBox_KeyDown);
this.editBox.LostFocus += new RoutedEventHandler(this.EditBox_LostFocus);
this.templatedParent = this.TemplatedParent as FrameworkElement;
if (this.templatedParent != null)
{
this.templatedParent.KeyDown += new KeyEventHandler(this.TemplatedParent_OnKeyDown);
}
}
private void DetachFromVisualTree()
{
if (this.editBox != null)
{
this.editBox.IsVisibleChanged -= this.EditBox_IsVisibleChanged;
this.editBox.KeyDown -= this.EditBox_KeyDown;
this.editBox.LostFocus -= this.EditBox_LostFocus;
}
if (this.templatedParent != null)
{
this.templatedParent.KeyDown -= this.TemplatedParent_OnKeyDown;
}
}
#endregion OnApplyTemplate Helpers
}
}

View File

@ -0,0 +1,148 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// A TextBox which shows a user provided text when its empty.
/// </summary>
[Localizability(LocalizationCategory.None)]
partial class MessageTextBox
{
//
// BackgroundText dependency property
//
/// <summary>
/// Identifies the BackgroundText dependency property.
/// </summary>
public static readonly DependencyProperty BackgroundTextProperty = DependencyProperty.Register( "BackgroundText", typeof(string), typeof(MessageTextBox), new PropertyMetadata( string.Empty, BackgroundTextProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value for text presented to user when TextBox is empty.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value for text presented to user when TextBox is empty.")]
[Localizability(LocalizationCategory.Text, Modifiability=Modifiability.Modifiable, Readability=Readability.Readable)]
public string BackgroundText
{
get
{
return (string) GetValue(BackgroundTextProperty);
}
set
{
SetValue(BackgroundTextProperty,value);
}
}
static private void BackgroundTextProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
MessageTextBox obj = (MessageTextBox) o;
obj.OnBackgroundTextChanged( new PropertyChangedEventArgs<string>((string)e.OldValue, (string)e.NewValue) );
}
/// <summary>
/// Occurs when BackgroundText property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<string>> BackgroundTextChanged;
/// <summary>
/// Called when BackgroundText property changes.
/// </summary>
protected virtual void OnBackgroundTextChanged(PropertyChangedEventArgs<string> e)
{
OnBackgroundTextChangedImplementation(e);
RaisePropertyChangedEvent(BackgroundTextChanged, e);
}
partial void OnBackgroundTextChangedImplementation(PropertyChangedEventArgs<string> e);
//
// IsBackgroundTextShown dependency property
//
/// <summary>
/// Identifies the IsBackgroundTextShown dependency property key.
/// </summary>
private static readonly DependencyPropertyKey IsBackgroundTextShownPropertyKey = DependencyProperty.RegisterReadOnly( "IsBackgroundTextShown", typeof(bool), typeof(MessageTextBox), new PropertyMetadata( BooleanBoxes.TrueBox, IsBackgroundTextShownProperty_PropertyChanged) );
/// <summary>
/// Identifies the IsBackgroundTextShown dependency property.
/// </summary>
public static readonly DependencyProperty IsBackgroundTextShownProperty = IsBackgroundTextShownPropertyKey.DependencyProperty;
/// <summary>
/// Gets a value indicating if the background text is being shown.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets a value indicating if the background text is being shown.")]
[Localizability(LocalizationCategory.None)]
public bool IsBackgroundTextShown
{
get
{
return (bool) GetValue(IsBackgroundTextShownProperty);
}
private set
{
SetValue(IsBackgroundTextShownPropertyKey,BooleanBoxes.Box(value));
}
}
static private void IsBackgroundTextShownProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
MessageTextBox obj = (MessageTextBox) o;
obj.OnIsBackgroundTextShownChanged( new PropertyChangedEventArgs<bool>((bool)e.OldValue, (bool)e.NewValue) );
}
/// <summary>
/// Occurs when IsBackgroundTextShown property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<bool>> IsBackgroundTextShownChanged;
/// <summary>
/// Called when IsBackgroundTextShown property changes.
/// </summary>
protected virtual void OnIsBackgroundTextShownChanged(PropertyChangedEventArgs<bool> e)
{
OnIsBackgroundTextShownChangedImplementation(e);
RaisePropertyChangedEvent(IsBackgroundTextShownChanged, e);
}
partial void OnIsBackgroundTextShownChangedImplementation(PropertyChangedEventArgs<bool> e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
//
// Static constructor
//
/// <summary>
/// Called when the type is initialized.
/// </summary>
static MessageTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MessageTextBox), new FrameworkPropertyMetadata(typeof(MessageTextBox)));
StaticConstructorImplementation();
}
static partial void StaticConstructorImplementation();
}
}
#endregion

View File

@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
namespace Microsoft.Management.UI.Internal
{
/// <content>
/// Partial class implementation for MessageTextBox control.
/// </content>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class MessageTextBox : TextBox
{
static partial void StaticConstructorImplementation()
{
TextProperty.OverrideMetadata(
typeof(MessageTextBox),
new FrameworkPropertyMetadata(
string.Empty,
null,
new CoerceValueCallback(OnTextBoxTextCoerce)));
}
#region Non-Public Methods
private void UpdateIsBackgroundTextShown(string text)
{
if (string.IsNullOrEmpty(text) == false && this.IsBackgroundTextShown)
{
this.IsBackgroundTextShown = false;
}
else if (string.IsNullOrEmpty(text) && this.IsBackgroundTextShown == false)
{
this.IsBackgroundTextShown = true;
}
}
private static object OnTextBoxTextCoerce(DependencyObject o, object baseValue)
{
MessageTextBox mtb = (MessageTextBox)o;
mtb.UpdateIsBackgroundTextShown((string)baseValue);
if (baseValue == null)
{
return string.Empty;
}
return baseValue;
}
#endregion Non-Public Methods
}
}

View File

@ -0,0 +1,261 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// This control provides basic functionality for Picker-like controls.
/// </summary>
/// <remarks>
///
///
/// If a custom template is provided for this control, then the template MUST provide the following template parts:
///
/// PART_DropDown - A required template part which must be of type DismissiblePopup. The dropdown which hosts the picker.
/// PART_DropDownButton - A required template part which must be of type ToggleButton. The ToggleButton which controls whether the dropdown is open.
///
/// </remarks>
[TemplatePart(Name="PART_DropDown", Type=typeof(DismissiblePopup))]
[TemplatePart(Name="PART_DropDownButton", Type=typeof(ToggleButton))]
[Localizability(LocalizationCategory.None)]
partial class PickerBase
{
//
// Fields
//
private DismissiblePopup dropDown;
private ToggleButton dropDownButton;
//
// CloseDropDown routed command
//
/// <summary>
/// Informs the PickerBase that it should close the dropdown.
/// </summary>
public static readonly RoutedCommand CloseDropDownCommand = new RoutedCommand("CloseDropDown",typeof(PickerBase));
static private void CloseDropDownCommand_CommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
PickerBase obj = (PickerBase) sender;
obj.OnCloseDropDownExecuted( e );
}
/// <summary>
/// Called when CloseDropDown executes.
/// </summary>
/// <remarks>
/// Informs the PickerBase that it should close the dropdown.
/// </remarks>
protected virtual void OnCloseDropDownExecuted(ExecutedRoutedEventArgs e)
{
OnCloseDropDownExecutedImplementation(e);
}
partial void OnCloseDropDownExecutedImplementation(ExecutedRoutedEventArgs e);
//
// DropDownButtonTemplate dependency property
//
/// <summary>
/// Identifies the DropDownButtonTemplate dependency property.
/// </summary>
public static readonly DependencyProperty DropDownButtonTemplateProperty = DependencyProperty.Register( "DropDownButtonTemplate", typeof(ControlTemplate), typeof(PickerBase), new PropertyMetadata( null, DropDownButtonTemplateProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value that controls the visual tree of the DropDown button.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value that controls the visual tree of the DropDown button.")]
[Localizability(LocalizationCategory.None)]
public ControlTemplate DropDownButtonTemplate
{
get
{
return (ControlTemplate) GetValue(DropDownButtonTemplateProperty);
}
set
{
SetValue(DropDownButtonTemplateProperty,value);
}
}
static private void DropDownButtonTemplateProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
PickerBase obj = (PickerBase) o;
obj.OnDropDownButtonTemplateChanged( new PropertyChangedEventArgs<ControlTemplate>((ControlTemplate)e.OldValue, (ControlTemplate)e.NewValue) );
}
/// <summary>
/// Occurs when DropDownButtonTemplate property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<ControlTemplate>> DropDownButtonTemplateChanged;
/// <summary>
/// Called when DropDownButtonTemplate property changes.
/// </summary>
protected virtual void OnDropDownButtonTemplateChanged(PropertyChangedEventArgs<ControlTemplate> e)
{
OnDropDownButtonTemplateChangedImplementation(e);
RaisePropertyChangedEvent(DropDownButtonTemplateChanged, e);
}
partial void OnDropDownButtonTemplateChangedImplementation(PropertyChangedEventArgs<ControlTemplate> e);
//
// DropDownStyle dependency property
//
/// <summary>
/// Identifies the DropDownStyle dependency property.
/// </summary>
public static readonly DependencyProperty DropDownStyleProperty = DependencyProperty.Register( "DropDownStyle", typeof(Style), typeof(PickerBase), new PropertyMetadata( null, DropDownStyleProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the style of the drop-down.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the style of the drop-down.")]
[Localizability(LocalizationCategory.None)]
public Style DropDownStyle
{
get
{
return (Style) GetValue(DropDownStyleProperty);
}
set
{
SetValue(DropDownStyleProperty,value);
}
}
static private void DropDownStyleProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
PickerBase obj = (PickerBase) o;
obj.OnDropDownStyleChanged( new PropertyChangedEventArgs<Style>((Style)e.OldValue, (Style)e.NewValue) );
}
/// <summary>
/// Occurs when DropDownStyle property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<Style>> DropDownStyleChanged;
/// <summary>
/// Called when DropDownStyle property changes.
/// </summary>
protected virtual void OnDropDownStyleChanged(PropertyChangedEventArgs<Style> e)
{
OnDropDownStyleChangedImplementation(e);
RaisePropertyChangedEvent(DropDownStyleChanged, e);
}
partial void OnDropDownStyleChangedImplementation(PropertyChangedEventArgs<Style> e);
//
// IsOpen dependency property
//
/// <summary>
/// Identifies the IsOpen dependency property.
/// </summary>
public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register( "IsOpen", typeof(bool), typeof(PickerBase), new PropertyMetadata( BooleanBoxes.FalseBox, IsOpenProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value indicating whether the Popup is visible.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value indicating whether the Popup is visible.")]
[Localizability(LocalizationCategory.None)]
public bool IsOpen
{
get
{
return (bool) GetValue(IsOpenProperty);
}
set
{
SetValue(IsOpenProperty,BooleanBoxes.Box(value));
}
}
static private void IsOpenProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
PickerBase obj = (PickerBase) o;
obj.OnIsOpenChanged( new PropertyChangedEventArgs<bool>((bool)e.OldValue, (bool)e.NewValue) );
}
/// <summary>
/// Occurs when IsOpen property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<bool>> IsOpenChanged;
/// <summary>
/// Called when IsOpen property changes.
/// </summary>
protected virtual void OnIsOpenChanged(PropertyChangedEventArgs<bool> e)
{
OnIsOpenChangedImplementation(e);
RaisePropertyChangedEvent(IsOpenChanged, e);
}
partial void OnIsOpenChangedImplementation(PropertyChangedEventArgs<bool> e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
//
// OnApplyTemplate
//
/// <summary>
/// Called when ApplyTemplate is called.
/// </summary>
public override void OnApplyTemplate()
{
PreOnApplyTemplate();
base.OnApplyTemplate();
this.dropDown = WpfHelp.GetTemplateChild<DismissiblePopup>(this,"PART_DropDown");
this.dropDownButton = WpfHelp.GetTemplateChild<ToggleButton>(this,"PART_DropDownButton");
PostOnApplyTemplate();
}
partial void PreOnApplyTemplate();
partial void PostOnApplyTemplate();
//
// Static constructor
//
/// <summary>
/// Called when the type is initialized.
/// </summary>
static PickerBase()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PickerBase), new FrameworkPropertyMetadata(typeof(PickerBase)));
CommandManager.RegisterClassCommandBinding( typeof(PickerBase), new CommandBinding( PickerBase.CloseDropDownCommand, CloseDropDownCommand_CommandExecuted ));
StaticConstructorImplementation();
}
static partial void StaticConstructorImplementation();
}
}
#endregion

View File

@ -0,0 +1,134 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Implements a re-usable base component useful for showing
/// Picker-like controls.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class PickerBase : HeaderedContentControl
{
/// <summary>
/// Creates a new instance of the PickerBase class.
/// </summary>
public PickerBase()
{
// empty
}
partial void OnCloseDropDownExecutedImplementation(ExecutedRoutedEventArgs e)
{
this.IsOpen = false;
}
#region DropDownButtonTemplate Changed
partial void OnDropDownButtonTemplateChangedImplementation(PropertyChangedEventArgs<ControlTemplate> e)
{
this.ApplyDropDownButtonTemplate();
}
private void ApplyDropDownButtonTemplate()
{
if (!this.IsLoaded)
{
this.ApplyTemplate();
this.Loaded += new RoutedEventHandler(this.PickerBase_Loaded_ApplyDropDownButtonTemplate);
return;
}
if (this.DropDownButtonTemplate != null && !ReferenceEquals(this.dropDownButton.Template, this.DropDownButtonTemplate))
{
this.dropDownButton.Template = this.DropDownButtonTemplate;
}
}
private void PickerBase_Loaded_ApplyDropDownButtonTemplate(object sender, RoutedEventArgs e)
{
this.Loaded -= this.PickerBase_Loaded_ApplyDropDownButtonTemplate;
this.ApplyDropDownButtonTemplate();
}
#endregion DropDownButtonTemplate Changed
#region DropDown IsOpen Handlers
private void DropDown_Opened(object sender, EventArgs e)
{
this.FocusDropDown();
}
private void FocusDropDown()
{
if (!this.dropDown.IsLoaded)
{
this.dropDown.Loaded += new RoutedEventHandler(this.DropDown_Loaded_FocusDropDown);
}
if (this.dropDown.Child != null && !this.dropDown.IsAncestorOf((DependencyObject)Keyboard.FocusedElement))
{
this.dropDown.Child.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
}
private void DropDown_Loaded_FocusDropDown(object sender, RoutedEventArgs e)
{
this.Loaded -= this.DropDown_Loaded_FocusDropDown;
this.FocusDropDown();
}
private void DropDown_Closed(object sender, EventArgs e)
{
if (this.dropDown.IsKeyboardFocusWithin || Keyboard.FocusedElement == null)
{
this.dropDownButton.Focus();
}
}
#endregion DropDown IsOpen Handlers
#region Apply Template
partial void PostOnApplyTemplate()
{
this.AttachToVisualTree();
this.ApplyDropDownButtonTemplate();
}
partial void PreOnApplyTemplate()
{
this.DetachFromVisualTree();
}
private void AttachToVisualTree()
{
this.dropDown.Opened += new EventHandler(this.DropDown_Opened);
this.dropDown.Closed += new EventHandler(this.DropDown_Closed);
}
private void DetachFromVisualTree()
{
if (this.dropDown != null)
{
this.dropDown.Opened -= this.DropDown_Opened;
this.dropDown.Closed -= this.DropDown_Closed;
}
}
#endregion Apply Template
}
}

View File

@ -0,0 +1,83 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// A toggle button which controls is a popup is open or not.
/// </summary>
[Localizability(LocalizationCategory.None)]
partial class PopupControlButton
{
//
// IsPopupOpen dependency property
//
/// <summary>
/// Identifies the IsPopupOpen dependency property.
/// </summary>
public static readonly DependencyProperty IsPopupOpenProperty = DependencyProperty.Register( "IsPopupOpen", typeof(bool), typeof(PopupControlButton), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsPopupOpenProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value indicating whether the popup is open or not.
/// </summary>
/// <remarks>
/// The Popup.IsOpen property should be two-way bound to this property.
/// </remarks>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value indicating whether the popup is open or not.")]
[Localizability(LocalizationCategory.None)]
public bool IsPopupOpen
{
get
{
return (bool) GetValue(IsPopupOpenProperty);
}
set
{
SetValue(IsPopupOpenProperty,BooleanBoxes.Box(value));
}
}
static private void IsPopupOpenProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
PopupControlButton obj = (PopupControlButton) o;
obj.OnIsPopupOpenChanged( new PropertyChangedEventArgs<bool>((bool)e.OldValue, (bool)e.NewValue) );
}
/// <summary>
/// Occurs when IsPopupOpen property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<bool>> IsPopupOpenChanged;
/// <summary>
/// Called when IsPopupOpen property changes.
/// </summary>
protected virtual void OnIsPopupOpenChanged(PropertyChangedEventArgs<bool> e)
{
OnIsPopupOpenChangedImplementation(e);
RaisePropertyChangedEvent(IsPopupOpenChanged, e);
}
partial void OnIsPopupOpenChangedImplementation(PropertyChangedEventArgs<bool> e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
}
}
#endregion

View File

@ -0,0 +1,131 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Threading;
namespace Microsoft.Management.UI.Internal
{
/// <content>
/// Partial class implementation for PopupControlButton control.
/// </content>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class PopupControlButton : ExpanderButton
{
private bool isClickInProgress = false;
/// <summary>
/// Tooltip to show to expand.
/// </summary>
protected override string ExpandToolTip
{
get { return XamlLocalizableResources.AutoResXGen_ManagementList2_ToolTip_132; }
}
/// <summary>
/// Constructs an instance of PopupControlButton.
/// </summary>
public PopupControlButton()
{
// nothing
}
/// <summary>
/// Called when the IsChecked property becomes true.
/// </summary>
/// <param name="e">The event data for the Checked event.</param>
protected override void OnChecked(RoutedEventArgs e)
{
base.OnChecked(e);
this.UpdateIsPopupOpen();
}
/// <summary>
/// Called when the IsChecked property becomes false.
/// </summary>
/// <param name="e">The event data for the Unchecked event.</param>
protected override void OnUnchecked(RoutedEventArgs e)
{
base.OnUnchecked(e);
this.UpdateIsPopupOpen();
}
private void UpdateIsPopupOpen()
{
this.IsPopupOpen = this.IsChecked.GetValueOrDefault();
}
/// <summary>
/// Invoked when an unhandled PreviewMouseLeftButtonUp routed event reaches an element in its route that is derived from this class. Implement this method to add class handling for this event.
/// </summary>
/// <param name="e">The MouseButtonEventArgs that contains the event data. The event data reports that the left mouse button was released.</param>
protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
{
////
// If the mouse is captured then we need to finish updating state after the current event it processed.
////
if (this.IsMouseCaptured && this.isClickInProgress)
{
this.isClickInProgress = false;
this.ReleaseMouseCapture();
this.Dispatcher.BeginInvoke(
new UpdateIsCheckedDelegate(this.UpdateIsChecked),
DispatcherPriority.Input,
null);
}
base.OnPreviewMouseLeftButtonUp(e);
}
private delegate void UpdateIsCheckedDelegate();
partial void OnIsPopupOpenChangedImplementation(PropertyChangedEventArgs<bool> e)
{
////
// If it looks like the button is in the act of being pressed,
// then we don't want to update the IsChecked since the button
// push will do it.
//
// However we do need to handle the case where the mouse down is on the
// button, but mouse up isn't.
//
////
if (Mouse.PrimaryDevice.LeftButton == MouseButtonState.Pressed && this.IsPopupOpen == false)
{
if (this.GetIsMouseReallyOver())
{
this.isClickInProgress = true;
this.CaptureMouse();
}
}
if (this.isClickInProgress == false)
{
this.UpdateIsChecked();
}
}
private bool GetIsMouseReallyOver()
{
Point pos = Mouse.PrimaryDevice.GetPosition(this);
if ((pos.X >= 0) && (pos.X <= ActualWidth) && (pos.Y >= 0) && (pos.Y <= ActualHeight))
{
return true;
}
return false;
}
private void UpdateIsChecked()
{
this.IsChecked = this.IsPopupOpen;
}
}
}

View File

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Management.UI.Internal
{
using System;
/// <summary>
/// An EventArgs which holds the old and new values for a property change.
/// </summary>
/// <typeparam name="T">The property type.</typeparam>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class PropertyChangedEventArgs<T> : EventArgs
{
/// <summary>
/// Creates an instance of PropertyChangedEventArgs.
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new, current, value.</param>
public PropertyChangedEventArgs(T oldValue, T newValue)
{
this.OldValue = oldValue;
this.NewValue = newValue;
}
/// <summary>
/// Gets the previous value for the property.
/// </summary>
public T OldValue
{
get;
private set;
}
/// <summary>
/// Gets the new value for the property.
/// </summary>
public T NewValue
{
get;
private set;
}
}
}

View File

@ -0,0 +1,133 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Represents a read-only ObservableCollection which also implement IAsyncProgress.
/// </summary>
/// <typeparam name="T">The type held by the collection.</typeparam>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class ReadOnlyObservableAsyncCollection<T> :
ReadOnlyCollection<T>,
IAsyncProgress,
INotifyPropertyChanged, INotifyCollectionChanged
{
#region Private fields
private IAsyncProgress asyncProgress;
#endregion Private fields
#region Constructors
/// <summary>
/// The constructor.
/// </summary>
/// <param name="list">The collection with which to create this instance of the ReadOnlyObservableAsyncCollection class.
/// The object must also implement IAsyncProgress, INotifyCollectionChanged and INotifyPropertyChanged.</param>
public ReadOnlyObservableAsyncCollection(IList<T> list)
: base(list)
{
this.asyncProgress = list as IAsyncProgress;
((INotifyCollectionChanged)this.Items).CollectionChanged += new NotifyCollectionChangedEventHandler(this.HandleCollectionChanged);
((INotifyPropertyChanged)this.Items).PropertyChanged += new PropertyChangedEventHandler(this.HandlePropertyChanged);
}
#endregion Constructors
#region Events
/// <summary>
/// Occurs when the collection changes, either by adding or removing an item.
/// </summary>
/// <remarks>
/// see <seealso cref="INotifyCollectionChanged"/>
/// </remarks>
public event NotifyCollectionChangedEventHandler CollectionChanged;
/// <summary>
/// Occurs when a property changes.
/// </summary>
/// <remarks>
/// see <seealso cref="INotifyPropertyChanged"/>
/// </remarks>
public event PropertyChangedEventHandler PropertyChanged;
#endregion Events
#region IAsyncProgress
/// <summary>
/// Gets a value indicating whether the async operation is currently running.
/// </summary>
public bool OperationInProgress
{
get
{
if (this.asyncProgress == null)
{
return false;
}
else
{
return this.asyncProgress.OperationInProgress;
}
}
}
/// <summary>
/// Gets the error for the async operation. This field is only valid if
/// OperationInProgress is false. null indicates there was no error.
/// </summary>
public Exception OperationError
{
get
{
if (this.asyncProgress == null)
{
return null;
}
else
{
return this.asyncProgress.OperationError;
}
}
}
#endregion IAsyncProgress
#region Private Methods
private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
NotifyCollectionChangedEventHandler eh = this.CollectionChanged;
if (eh != null)
{
eh(this, args);
}
}
private void OnPropertyChanged(PropertyChangedEventArgs args)
{
PropertyChangedEventHandler eh = this.PropertyChanged;
if (eh != null)
{
eh(this, args);
}
}
// forward CollectionChanged events from the base list to our listeners
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
this.OnCollectionChanged(e);
}
// forward PropertyChanged events from the base list to our listeners
private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.OnPropertyChanged(e);
}
#endregion Private Methods
}
}

View File

@ -0,0 +1,95 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Automation.Peers;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Represents an image that can render as a vector or as a bitmap.
/// </summary>
[Localizability(LocalizationCategory.None)]
partial class ScalableImage
{
//
// Source dependency property
//
/// <summary>
/// Identifies the Source dependency property.
/// </summary>
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( "Source", typeof(ScalableImageSource), typeof(ScalableImage), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.AffectsRender, SourceProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the ScalableImageSource used to render the image. This is a dependency property.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the ScalableImageSource used to render the image. This is a dependency property.")]
[Localizability(LocalizationCategory.None)]
public ScalableImageSource Source
{
get
{
return (ScalableImageSource) GetValue(SourceProperty);
}
set
{
SetValue(SourceProperty,value);
}
}
static private void SourceProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ScalableImage obj = (ScalableImage) o;
obj.OnSourceChanged( new PropertyChangedEventArgs<ScalableImageSource>((ScalableImageSource)e.OldValue, (ScalableImageSource)e.NewValue) );
}
/// <summary>
/// Occurs when Source property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<ScalableImageSource>> SourceChanged;
/// <summary>
/// Called when Source property changes.
/// </summary>
protected virtual void OnSourceChanged(PropertyChangedEventArgs<ScalableImageSource> e)
{
OnSourceChangedImplementation(e);
RaisePropertyChangedEvent(SourceChanged, e);
}
partial void OnSourceChangedImplementation(PropertyChangedEventArgs<ScalableImageSource> e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
//
// CreateAutomationPeer
//
/// <summary>
/// Create an instance of the AutomationPeer.
/// </summary>
/// <returns>
/// An instance of the AutomationPeer.
/// </returns>
protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
{
return new ExtendedFrameworkElementAutomationPeer(owner: this, controlType: AutomationControlType.Image, isControlElement: false);
}
}
}
#endregion

View File

@ -0,0 +1,117 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Data;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
/// <content>
/// Partial class implementation for ScalableImage control.
/// </content>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class ScalableImage : FrameworkElement
{
#region Structors
/// <summary>
/// Initializes a new instance of the <see cref="Microsoft.Management.UI.Internal.ScalableImage" /> class.
/// </summary>
public ScalableImage()
{
// This constructor intentionally left blank
}
#endregion
#region Overrides
/// <summary>
/// Called when the control is asked to render itself in a given area.
/// Sets the render size to use all available area when <see cref="Microsoft.Management.UI.Internal.ScalableImageSource.Brush"/> is provided.
/// </summary>
/// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param>
/// <returns>The actual size used to render the control.</returns>
protected override Size ArrangeOverride(Size finalSize)
{
// If a vector is provided, specify that the control will use all available area \\
if (this.Source != null && this.Source.Brush != null)
{
return finalSize;
}
return base.ArrangeOverride(finalSize);
}
/// <summary>
/// Called when the control is being rendered.
/// Renders the contents of the image as a vector or a bitmap, depending on which is provided.
/// </summary>
/// <param name="drawingContext">An instance of <see cref="System.Windows.Media.DrawingContext"/> used to render the control.</param>
protected override void OnRender(DrawingContext drawingContext)
{
Rect renderArea = new Rect(this.RenderSize);
// No source was provided \\
if (this.Source == null)
{
return;
}
// Prefer the vector if it's provided \\
if (this.Source.Brush != null)
{
drawingContext.DrawRectangle(this.Source.Brush, null, renderArea);
}
else if (this.Source.Image != null)
{
drawingContext.DrawImage(this.Source.Image, renderArea);
}
}
/// <summary>
/// Override of <seealso cref="UIElement.GetLayoutClip"/>.
/// Make this control to respect the ClipToBounds attribute value.
/// </summary>
/// <param name="layoutSlotSize">An instance of <see cref="System.Windows.Size"/> used for calculating an additional clip.</param>
/// <returns>Geometry to use as an additional clip in case when element is larger than available space</returns>
protected override Geometry GetLayoutClip(Size layoutSlotSize)
{
return ClipToBounds ? base.GetLayoutClip(layoutSlotSize) : null;
}
#endregion
#region Protected Methods
partial void OnSourceChangedImplementation(PropertyChangedEventArgs<ScalableImageSource> e)
{
if (e.NewValue != null)
{
// If a width was provided in the source, use it now \\
if (!e.NewValue.Size.Width.Equals(double.NaN))
{
this.Width = e.NewValue.Size.Width;
}
// If a height was provided in the source, use it now \\
if (!e.NewValue.Size.Height.Equals(double.NaN))
{
this.Height = e.NewValue.Size.Height;
}
// Bind the image's accessible name to the one set in the source \\
Binding accessibleNameBinding = new Binding(ScalableImageSource.AccessibleNameProperty.Name);
accessibleNameBinding.Source = this.Source;
this.SetBinding(AutomationProperties.NameProperty, accessibleNameBinding);
}
}
#endregion
}
}

View File

@ -0,0 +1,228 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Represents the source of an image that can render as a vector or as a bitmap.
/// </summary>
[Localizability(LocalizationCategory.None)]
partial class ScalableImageSource
{
//
// AccessibleName dependency property
//
/// <summary>
/// Identifies the AccessibleName dependency property.
/// </summary>
public static readonly DependencyProperty AccessibleNameProperty = DependencyProperty.Register( "AccessibleName", typeof(string), typeof(ScalableImageSource), new PropertyMetadata( null, AccessibleNameProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the accessible name of the image. This is used by accessibility clients to describe the image, and must be localized.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the accessible name of the image. This is used by accessibility clients to describe the image, and must be localized.")]
[Localizability(LocalizationCategory.Text, Modifiability=Modifiability.Modifiable, Readability=Readability.Readable)]
public string AccessibleName
{
get
{
return (string) GetValue(AccessibleNameProperty);
}
set
{
SetValue(AccessibleNameProperty,value);
}
}
static private void AccessibleNameProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ScalableImageSource obj = (ScalableImageSource) o;
obj.OnAccessibleNameChanged( new PropertyChangedEventArgs<string>((string)e.OldValue, (string)e.NewValue) );
}
/// <summary>
/// Occurs when AccessibleName property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<string>> AccessibleNameChanged;
/// <summary>
/// Called when AccessibleName property changes.
/// </summary>
protected virtual void OnAccessibleNameChanged(PropertyChangedEventArgs<string> e)
{
OnAccessibleNameChangedImplementation(e);
RaisePropertyChangedEvent(AccessibleNameChanged, e);
}
partial void OnAccessibleNameChangedImplementation(PropertyChangedEventArgs<string> e);
//
// Brush dependency property
//
/// <summary>
/// Identifies the Brush dependency property.
/// </summary>
public static readonly DependencyProperty BrushProperty = DependencyProperty.Register( "Brush", typeof(Brush), typeof(ScalableImageSource), new PropertyMetadata( null, BrushProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the source used to render the image as a vector.If this is set, the Image property will be ignored.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the source used to render the image as a vector.If this is set, the Image property will be ignored.")]
[Localizability(LocalizationCategory.None)]
public Brush Brush
{
get
{
return (Brush) GetValue(BrushProperty);
}
set
{
SetValue(BrushProperty,value);
}
}
static private void BrushProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ScalableImageSource obj = (ScalableImageSource) o;
obj.OnBrushChanged( new PropertyChangedEventArgs<Brush>((Brush)e.OldValue, (Brush)e.NewValue) );
}
/// <summary>
/// Occurs when Brush property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<Brush>> BrushChanged;
/// <summary>
/// Called when Brush property changes.
/// </summary>
protected virtual void OnBrushChanged(PropertyChangedEventArgs<Brush> e)
{
OnBrushChangedImplementation(e);
RaisePropertyChangedEvent(BrushChanged, e);
}
partial void OnBrushChangedImplementation(PropertyChangedEventArgs<Brush> e);
//
// Image dependency property
//
/// <summary>
/// Identifies the Image dependency property.
/// </summary>
public static readonly DependencyProperty ImageProperty = DependencyProperty.Register( "Image", typeof(ImageSource), typeof(ScalableImageSource), new PropertyMetadata( null, ImageProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the source used to render the image as a bitmap. If the Brush property is set, this will be ignored.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the source used to render the image as a bitmap. If the Brush property is set, this will be ignored.")]
[Localizability(LocalizationCategory.None)]
public ImageSource Image
{
get
{
return (ImageSource) GetValue(ImageProperty);
}
set
{
SetValue(ImageProperty,value);
}
}
static private void ImageProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ScalableImageSource obj = (ScalableImageSource) o;
obj.OnImageChanged( new PropertyChangedEventArgs<ImageSource>((ImageSource)e.OldValue, (ImageSource)e.NewValue) );
}
/// <summary>
/// Occurs when Image property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<ImageSource>> ImageChanged;
/// <summary>
/// Called when Image property changes.
/// </summary>
protected virtual void OnImageChanged(PropertyChangedEventArgs<ImageSource> e)
{
OnImageChangedImplementation(e);
RaisePropertyChangedEvent(ImageChanged, e);
}
partial void OnImageChangedImplementation(PropertyChangedEventArgs<ImageSource> e);
//
// Size dependency property
//
/// <summary>
/// Identifies the Size dependency property.
/// </summary>
public static readonly DependencyProperty SizeProperty = DependencyProperty.Register( "Size", typeof(Size), typeof(ScalableImageSource), new PropertyMetadata( new Size(double.NaN, double.NaN), SizeProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the suggested size of the image.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the suggested size of the image.")]
[Localizability(LocalizationCategory.None)]
public Size Size
{
get
{
return (Size) GetValue(SizeProperty);
}
set
{
SetValue(SizeProperty,value);
}
}
static private void SizeProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ScalableImageSource obj = (ScalableImageSource) o;
obj.OnSizeChanged( new PropertyChangedEventArgs<Size>((Size)e.OldValue, (Size)e.NewValue) );
}
/// <summary>
/// Occurs when Size property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<Size>> SizeChanged;
/// <summary>
/// Called when Size property changes.
/// </summary>
protected virtual void OnSizeChanged(PropertyChangedEventArgs<Size> e)
{
OnSizeChangedImplementation(e);
RaisePropertyChangedEvent(SizeChanged, e);
}
partial void OnSizeChangedImplementation(PropertyChangedEventArgs<Size> e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
}
}
#endregion

View File

@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
namespace Microsoft.Management.UI.Internal
{
/// <content>
/// Partial class implementation for SeparatedList control.
/// </content>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class ScalableImageSource : Freezable
{
#region Structors
/// <summary>
/// Initializes a new instance of the <see cref="Microsoft.Management.UI.Internal.ScalableImageSource" /> class.
/// </summary>
public ScalableImageSource()
{
// This constructor intentionally left blank
}
#endregion
#region Overrides
/// <summary>
/// Creates a new instance of the Freezable derived class.
/// </summary>
/// <returns>The new instance of the Freezable derived class.</returns>
protected override Freezable CreateInstanceCore()
{
return new ScalableImageSource();
}
#endregion Overrides
}
}

View File

@ -0,0 +1,84 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Base proxy class for other classes which wish to have save and restore functionality.
/// </summary>
/// <typeparam name="T">There are no restrictions on T.</typeparam>
[Serializable]
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public abstract class StateDescriptor<T>
{
private Guid id;
private string name;
/// <summary>
/// Creates a new instances of the StateDescriptor class and creates a new GUID.
/// </summary>
protected StateDescriptor()
{
this.Id = Guid.NewGuid();
}
/// <summary>
/// Constructor overload to provide name.
/// </summary>
/// <param name="name">The friendly name for the StateDescriptor.</param>
protected StateDescriptor(string name)
: this()
{
this.Name = name;
}
/// <summary>
/// Gets the global unique identification number.
/// </summary>
public Guid Id
{
get
{
return this.id;
}
protected set
{
this.id = value;
}
}
/// <summary>
/// Gets or sets the friendly display name.
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
/// <summary>
/// Saves a snapshot of the subject's current state.
/// </summary>
/// <param name="subject">The object whose state will be saved.</param>
public abstract void SaveState(T subject);
/// <summary>
/// Restores the state of subject to the saved state.
/// </summary>
/// <param name="subject">The object whose state will be restored.</param>
public abstract void RestoreState(T subject);
}
}

View File

@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Globalization;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Formatting string with a given format.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class StringFormatConverter : IValueConverter
{
/// <summary>
/// Formatting string with a given format.
/// </summary>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property. This is not used.</param>
/// <param name="parameter">The converter parameter to use. It should be a formatting string.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>The formatted string.</returns>
public object Convert(object value, Type targetType, Object parameter, CultureInfo culture)
{
if (parameter == null)
{
throw new ArgumentNullException("parameter");
}
string str = (string)value;
string formatString = (string)parameter;
if (string.IsNullOrEmpty(str))
{
return null;
}
return string.Format(culture, formatString, str);
}
/// <summary>
/// Converts a value.
/// </summary>
/// <remarks>
/// This method is not implemented.
/// </remarks>
/// <param name="value">The value that is produced by the binding target.</param>
/// <param name="targetType">The type to convert to.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>A converted value.</returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,172 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides attached properties for TextBlock control.
/// </summary>
[Localizability(LocalizationCategory.None)]
partial class TextBlockService
{
//
// IsTextTrimmed dependency property
//
/// <summary>
/// Identifies the IsTextTrimmed dependency property key.
/// </summary>
private static readonly DependencyPropertyKey IsTextTrimmedPropertyKey = DependencyProperty.RegisterAttachedReadOnly( "IsTextTrimmed", typeof(bool), typeof(TextBlockService), new PropertyMetadata( BooleanBoxes.FalseBox, IsTextTrimmedProperty_PropertyChanged) );
/// <summary>
/// Identifies the IsTextTrimmed dependency property.
/// </summary>
public static readonly DependencyProperty IsTextTrimmedProperty = IsTextTrimmedPropertyKey.DependencyProperty;
/// <summary>
/// Gets the value for IsTextTrimmedProperty that is attached to the element.
/// </summary>
/// <param name="element">The dependency object that the property is attached to.</param>
/// <returns>
/// The value of IsTextTrimmed that is attached to element.
/// </returns>
static public bool GetIsTextTrimmed(DependencyObject element)
{
return (bool) element.GetValue(IsTextTrimmedProperty);
}
/// <summary>
/// Sets the value for IsTextTrimmedProperty that is attached to the element.
/// </summary>
/// <param name="element">The dependency object that the property will be attached to.</param>
/// <param name="value">The new value.</param>
static private void SetIsTextTrimmed(DependencyObject element, bool value)
{
element.SetValue(IsTextTrimmedPropertyKey,BooleanBoxes.Box(value));
}
static private void IsTextTrimmedProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
IsTextTrimmedProperty_PropertyChangedImplementation(o, e);
}
static partial void IsTextTrimmedProperty_PropertyChangedImplementation(DependencyObject o, DependencyPropertyChangedEventArgs e);
//
// IsTextTrimmedExternally dependency property
//
/// <summary>
/// Identifies the IsTextTrimmedExternally dependency property.
/// </summary>
public static readonly DependencyProperty IsTextTrimmedExternallyProperty = DependencyProperty.RegisterAttached( "IsTextTrimmedExternally", typeof(bool), typeof(TextBlockService), new PropertyMetadata( BooleanBoxes.FalseBox, IsTextTrimmedExternallyProperty_PropertyChanged) );
/// <summary>
/// Gets a value indicating that the Text has been trimmed external to the element.
/// </summary>
/// <param name="element">The dependency object that the property is attached to.</param>
/// <returns>
/// The value of IsTextTrimmedExternally that is attached to element.
/// </returns>
static public bool GetIsTextTrimmedExternally(DependencyObject element)
{
return (bool) element.GetValue(IsTextTrimmedExternallyProperty);
}
/// <summary>
/// Sets a value indicating that the Text has been trimmed external to the element.
/// </summary>
/// <param name="element">The dependency object that the property will be attached to.</param>
/// <param name="value">The new value.</param>
static public void SetIsTextTrimmedExternally(DependencyObject element, bool value)
{
element.SetValue(IsTextTrimmedExternallyProperty,BooleanBoxes.Box(value));
}
static private void IsTextTrimmedExternallyProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
IsTextTrimmedExternallyProperty_PropertyChangedImplementation(o, e);
}
static partial void IsTextTrimmedExternallyProperty_PropertyChangedImplementation(DependencyObject o, DependencyPropertyChangedEventArgs e);
//
// IsTextTrimmedMonitoringEnabled dependency property
//
/// <summary>
/// Identifies the IsTextTrimmedMonitoringEnabled dependency property.
/// </summary>
public static readonly DependencyProperty IsTextTrimmedMonitoringEnabledProperty = DependencyProperty.RegisterAttached( "IsTextTrimmedMonitoringEnabled", typeof(bool), typeof(TextBlockService), new PropertyMetadata( BooleanBoxes.FalseBox, IsTextTrimmedMonitoringEnabledProperty_PropertyChanged) );
/// <summary>
/// Gets the value for IsTextTrimMonitoringEnabled that is attached to the element.
/// </summary>
/// <param name="element">The dependency object that the property is attached to.</param>
/// <returns>
/// The value of IsTextTrimmedMonitoringEnabled that is attached to element.
/// </returns>
static public bool GetIsTextTrimmedMonitoringEnabled(DependencyObject element)
{
return (bool) element.GetValue(IsTextTrimmedMonitoringEnabledProperty);
}
/// <summary>
/// Sets the value for IsTextTrimMonitoringEnabled that is attached to the element.
/// </summary>
/// <param name="element">The dependency object that the property will be attached to.</param>
/// <param name="value">The new value.</param>
static public void SetIsTextTrimmedMonitoringEnabled(DependencyObject element, bool value)
{
element.SetValue(IsTextTrimmedMonitoringEnabledProperty,BooleanBoxes.Box(value));
}
static private void IsTextTrimmedMonitoringEnabledProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
IsTextTrimmedMonitoringEnabledProperty_PropertyChangedImplementation(o, e);
}
static partial void IsTextTrimmedMonitoringEnabledProperty_PropertyChangedImplementation(DependencyObject o, DependencyPropertyChangedEventArgs e);
//
// UntrimmedText dependency property
//
/// <summary>
/// Identifies the UntrimmedText dependency property.
/// </summary>
public static readonly DependencyProperty UntrimmedTextProperty = DependencyProperty.RegisterAttached( "UntrimmedText", typeof(string), typeof(TextBlockService), new PropertyMetadata( string.Empty, UntrimmedTextProperty_PropertyChanged) );
/// <summary>
/// Gets the untrimmed text.
/// </summary>
/// <param name="element">The dependency object that the property is attached to.</param>
/// <returns>
/// The value of UntrimmedText that is attached to element.
/// </returns>
static public string GetUntrimmedText(DependencyObject element)
{
return (string) element.GetValue(UntrimmedTextProperty);
}
/// <summary>
/// Sets the untrimmed text.
/// </summary>
/// <param name="element">The dependency object that the property will be attached to.</param>
/// <param name="value">The new value.</param>
static public void SetUntrimmedText(DependencyObject element, string value)
{
element.SetValue(UntrimmedTextProperty,value);
}
static private void UntrimmedTextProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
UntrimmedTextProperty_PropertyChangedImplementation(o, e);
}
static partial void UntrimmedTextProperty_PropertyChangedImplementation(DependencyObject o, DependencyPropertyChangedEventArgs e);
}
}
#endregion

View File

@ -0,0 +1,91 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Attached property provider to <see cref="TextBlock"/> control.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public static partial class TextBlockService
{
static partial void IsTextTrimmedMonitoringEnabledProperty_PropertyChangedImplementation(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
TextBlock tb = o as TextBlock;
if (tb == null)
{
return;
}
if ((bool)e.OldValue == true)
{
tb.SizeChanged -= OnTextBlockSizeChanged;
}
else
{
tb.SizeChanged += OnTextBlockSizeChanged;
}
}
private static void OnTextBlockSizeChanged(object sender, SizeChangedEventArgs e)
{
var textBlock = (TextBlock)sender;
UpdateIsTextTrimmed(textBlock);
}
private static void OnTextBlockPropertyChanged(object sender, EventArgs e)
{
var textBlock = (TextBlock)sender;
UpdateIsTextTrimmed(textBlock);
}
private static void UpdateIsTextTrimmed(TextBlock textBlock)
{
Debug.Assert(textBlock != null, "textblock not null");
if (textBlock.TextWrapping != TextWrapping.NoWrap || textBlock.TextTrimming == TextTrimming.None)
{
SetIsTextTrimmed(textBlock, false);
}
else
{
SetIsTextTrimmed(textBlock, CalculateIsTextTrimmed(textBlock));
}
}
private static bool CalculateIsTextTrimmed(TextBlock textBlock)
{
if (!textBlock.IsArrangeValid)
{
return GetIsTextTrimmed(textBlock);
}
Typeface typeface = new Typeface(
textBlock.FontFamily,
textBlock.FontStyle,
textBlock.FontWeight,
textBlock.FontStretch);
#pragma warning disable 612, 618
// FormattedText is used to measure the whole width of the text held up by TextBlock container
FormattedText formattedText = new FormattedText(
textBlock.Text,
System.Threading.Thread.CurrentThread.CurrentCulture,
textBlock.FlowDirection,
typeface,
textBlock.FontSize,
textBlock.Foreground);
#pragma warning restore 612, 618
return formattedText.Width > textBlock.ActualWidth;
}
}
}

View File

@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Removes whitespace at beginning and end of a string.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class TextTrimConverter : IValueConverter
{
/// <summary>
/// Creates a new TextTrimConverter. By default, both conversion directions are trimmed.
/// </summary>
public TextTrimConverter()
{
}
#region IValueConverter Members
/// <summary>
/// Trims excess whitespace from the given string.
/// </summary>
/// <param name="value">original string</param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The trimmed string.</returns>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return TrimValue(value);
}
private static object TrimValue(object value)
{
string strValue = value as string;
if (strValue == null)
{
return value;
}
return strValue.Trim();
}
/// <summary>
/// Trims extra whitespace from the given string during backward conversion.
/// </summary>
/// <param name="value">original string</param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The trimmed string.</returns>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return TrimValue(value);
}
#endregion
}
}

View File

@ -0,0 +1,189 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
#region UserActionState enum
/// <summary>
/// Represents the availability of an action to a user.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public enum UserActionState
{
/// <summary>
/// Indicates that the action is enabled and allowed.
/// </summary>
Enabled = 0,
/// <summary>
/// Indicates that the action is disabled.
/// </summary>
Disabled = 1,
/// <summary>
/// Indicates that the action is not visible.
/// </summary>
Hidden = 2,
}
#endregion
#region ControlState enum
/// <summary>
/// Represents the ready-state of a control.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public enum ControlState
{
/// <summary>
/// Indicates that the control is ready.
/// </summary>
Ready = 0,
/// <summary>
/// Indicates that the control has an error.
/// </summary>
Error = 1,
/// <summary>
/// Indicates that the control is refreshing its data.
/// </summary>
Refreshing = 2,
}
#endregion
#region Utilities class
/// <summary>
/// Provides common methods for use in the library.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public static class Utilities
{
/// <summary>
/// Gets whether all of the items in <paramref name="items"/> are of type T.
/// </summary>
/// <typeparam name="T">The type to verify.</typeparam>
/// <param name="items">The items to check.</param>
/// <returns>Whether all of the items in <paramref name="items"/> are of type T.</returns>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
public static bool AreAllItemsOfType<T>(IEnumerable items)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
foreach (object item in items)
{
if (!(item is T))
{
return false;
}
}
return true;
}
/// <summary>
/// Searches for an element that matches the specified type, and returns the first occurrence in the entire <see cref="IEnumerable"/>.
/// </summary>
/// <typeparam name="T">The type of the item to find.</typeparam>
/// <param name="items">The <see cref="IEnumerable"/> to search.</param>
/// <returns>The first element that matches the specified type, if found; otherwise, the default value for type <typeparamref name="T"/>.</returns>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
public static T Find<T>(this IEnumerable items)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
foreach (object item in items)
{
if (item is T)
{
return (T)item;
}
}
return default(T);
}
/// <summary>
/// Method to trim the non null strings.
/// </summary>
/// <param name="value">String to Trim.</param>
/// <returns>Trimmed string.</returns>
public static string NullCheckTrim(string value)
{
if (!string.IsNullOrEmpty(value))
{
return value.Trim();
}
return value;
}
// A separate copy of ResortObservableCollection is in ADMUX Utility.cs
/// <summary>
/// Restore the original order as far as possible.
/// Columns not in the original set will appear at the end.
/// </summary>
/// <typeparam name="T">
/// Type of <paramref name="modify"/>.
/// </typeparam>
/// <param name="modify">
/// ObservableCollection to resort to order of
/// <paramref name="sorted"/>.
/// </param>
/// <param name="sorted">
/// Order to which <paramref name="modify"/> should be resorted.
/// All enumerated objects must be of type T.
/// </param>
/// <remarks>
/// Parameter <paramref name="sorted"/> is not generic to type T
/// since it may be a collection of a subclass of type T,
/// and IEnumerable'subclass is not compatible with
/// IEnumerable'baseclass.
/// </remarks>
public static void ResortObservableCollection<T>(
ObservableCollection<T> modify,
IEnumerable sorted)
{
int orderedPosition = 0;
foreach (T obj in sorted)
{
T sortedObject = (T)obj;
int foundIndex = modify.IndexOf(sortedObject);
if (foundIndex >= 0)
{
modify.Move(foundIndex, orderedPosition);
orderedPosition++;
if (modify.Count <= orderedPosition)
{
// All objects present are in the original order
break;
}
}
}
}
}
#endregion
}

View File

@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Globalization;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides a way to get the <see cref="FrameworkElement.DataContext"/> of a visual ancestor.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class VisualToAncestorDataConverter : IValueConverter
{
/// <summary>
/// Searches ancestors for data of the specified class type.
/// </summary>
/// <param name="value">The visual whose ancestors are searched.</param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The type of the data to find. The type must be a class.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The data of the specified type; or if not found, <c>null</c>.</returns>
/// <exception cref="ArgumentException">The specified value is not a class type.</exception>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (parameter == null)
{
throw new ArgumentNullException("parameter");
}
Type dataType = (Type)parameter;
if (dataType.IsClass == false)
{
throw new ArgumentException("The specified value is not a class type.", "parameter");
}
DependencyObject obj = (DependencyObject)value;
MethodInfo findVisualAncestorDataMethod = typeof(WpfHelp).GetMethod("FindVisualAncestorData");
MethodInfo genericFindVisualAncestorDataMethod = findVisualAncestorDataMethod.MakeGenericMethod(dataType);
return genericFindVisualAncestorDataMethod.Invoke(null, new object[] { obj });
}
/// <summary>
/// This method is not used.
/// </summary>
/// <param name="value">The parameter is not used.</param>
/// <param name="targetType">The parameter is not used.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="culture">The parameter is not used.</param>
/// <returns>The parameter is not used.</returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Windows;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// A common weak event listener which can be used for different kinds of events.
/// </summary>
/// <typeparam name="TEventArgs">The EventArgs type for the event.</typeparam>
internal class WeakEventListener<TEventArgs> : IWeakEventListener where TEventArgs : EventArgs
{
private EventHandler<TEventArgs> realHander;
/// <summary>
/// Constructs an instance of WeakEventListener.
/// </summary>
/// <param name="handler">The handler for the event.</param>
public WeakEventListener(EventHandler<TEventArgs> handler)
{
if (handler == null)
{
throw new ArgumentNullException("handler");
}
this.realHander = handler;
}
/// <summary>
/// Receives events from the centralized event manager.
/// </summary>
/// <param name="managerType">The type of the WeakEventManager calling this method.</param>
/// <param name="sender">Object that originated the event.</param>
/// <param name="e">Event data.</param>
/// <returns>
/// true if the listener handled the event. It is considered an error by the WeakEventManager handling in WPF to register a listener for an event that the listener does not handle. Regardless, the method should return false if it receives an event that it does not recognize or handle.
/// </returns>
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
TEventArgs realArgs = (TEventArgs)e;
this.realHander(sender, realArgs);
return true;
}
}
}

View File

@ -0,0 +1,606 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Defines a method which will be called when
/// a condition is met.
/// </summary>
/// <typeparam name="T">The type of the item.</typeparam>
/// <param name="item">The parameter to pass to the method.</param>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
internal delegate void RetryActionCallback<T>(T item);
/// <summary>
/// Provides common WPF methods for use in the library.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
internal static class WpfHelp
{
#region RetryActionAfterLoaded
private static Dictionary<FrameworkElement, RetryActionAfterLoadedDataQueue> retryActionData =
new Dictionary<FrameworkElement, RetryActionAfterLoadedDataQueue>();
/// <summary>
/// Calls a method when the Loaded event is fired on a FrameworkElement.
/// </summary>
/// <typeparam name="T">The type of the parameter to pass to the callback method.</typeparam>
/// <param name="element">The element whose Loaded state we are interested in.</param>
/// <param name="callback">The method we will call if element.IsLoaded is false.</param>
/// <param name="parameter">The parameter to pass to the callback method.</param>
/// <returns>
/// Returns true if the element is not loaded and the callback will be called
/// when the element is loaded, false otherwise.
/// </returns>
public static bool RetryActionAfterLoaded<T>(FrameworkElement element, RetryActionCallback<T> callback, T parameter)
{
if (element.IsLoaded)
{
return false;
}
RetryActionAfterLoadedDataQueue data;
if (!retryActionData.TryGetValue(element, out data))
{
data = new RetryActionAfterLoadedDataQueue();
retryActionData.Add(element, data);
}
data.Enqueue(callback, parameter);
element.Loaded += new RoutedEventHandler(Element_Loaded);
element.ApplyTemplate();
return true;
}
private static void Element_Loaded(object sender, RoutedEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
element.Loaded -= Element_Loaded;
RetryActionAfterLoadedDataQueue data;
if (!retryActionData.TryGetValue(element, out data)
|| data.IsEmpty)
{
throw new InvalidOperationException("Event loaded callback data expected.");
}
Delegate callback;
object parameter;
data.Dequeue(out callback, out parameter);
if (data.IsEmpty)
{
retryActionData.Remove(element);
}
callback.DynamicInvoke(parameter);
}
private class RetryActionAfterLoadedDataQueue
{
private Queue<Delegate> callbacks = new Queue<Delegate>();
private Queue<object> parameters = new Queue<object>();
/// <summary>
/// Adds a callback with its associated parameter to the collection.
/// </summary>
/// <param name="callback">The callback to invoke.</param>
/// <param name="parameter">The parameter to pass to the callback.</param>
public void Enqueue(Delegate callback, object parameter)
{
this.callbacks.Enqueue(callback);
this.parameters.Enqueue(parameter);
}
/// <summary>
/// Removes a callback with its associated parameter from the head of
/// the collection.
/// </summary>
/// <param name="callback">The callback to invoke.</param>
/// <param name="parameter">The parameter to pass to the callback.</param>
public void Dequeue(out Delegate callback, out object parameter)
{
callback = null;
parameter = null;
if (this.callbacks.Count < 1)
{
throw new InvalidOperationException("Trying to remove when there is no data");
}
callback = this.callbacks.Dequeue();
parameter = this.parameters.Dequeue();
}
/// <summary>
/// Gets whether there is any callback data available.
/// </summary>
public bool IsEmpty
{
get
{
return this.callbacks.Count == 0;
}
}
}
#endregion RetryActionAfterLoaded
#region RemoveFromParent/AddChild
/// <summary>
/// Removes the specified element from its parent.
/// </summary>
/// <param name="element">The element to remove.</param>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
/// <exception cref="NotSupportedException">The specified value does not have a parent that supports removal.</exception>
public static void RemoveFromParent(FrameworkElement element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
// If the element has already been detached, do nothing \\
if (element.Parent == null)
{
return;
}
ContentControl parentContentControl = element.Parent as ContentControl;
if (parentContentControl != null)
{
parentContentControl.Content = null;
return;
}
var parentDecorator = element.Parent as Decorator;
if (parentDecorator != null)
{
parentDecorator.Child = null;
return;
}
ItemsControl parentItemsControl = element.Parent as ItemsControl;
if (parentItemsControl != null)
{
parentItemsControl.Items.Remove(element);
return;
}
Panel parentPanel = element.Parent as Panel;
if (parentPanel != null)
{
parentPanel.Children.Remove(element);
return;
}
var parentAdorner = element.Parent as UIElementAdorner;
if (parentAdorner != null)
{
parentAdorner.Child = null;
return;
}
throw new NotSupportedException("The specified value does not have a parent that supports removal.");
}
/// <summary>
/// Removes the specified element from its parent.
/// </summary>
/// <param name="parent">The parent element.</param>
/// <param name="element">The element to add.</param>
/// <exception cref="NotSupportedException">The specified value does not have a parent that supports removal.</exception>
public static void AddChild(FrameworkElement parent, FrameworkElement element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
if (parent == null)
{
throw new ArgumentNullException("element");
}
ContentControl parentContentControl = parent as ContentControl;
if (parentContentControl != null)
{
parentContentControl.Content = element;
return;
}
var parentDecorator = parent as Decorator;
if (parentDecorator != null)
{
parentDecorator.Child = element;
return;
}
ItemsControl parentItemsControl = parent as ItemsControl;
if (parentItemsControl != null)
{
parentItemsControl.Items.Add(element);
return;
}
Panel parentPanel = parent as Panel;
if (parentPanel != null)
{
parentPanel.Children.Add(element);
return;
}
throw new NotSupportedException("The specified parent doesn't support children.");
}
#endregion RemoveFromParent/AddChild
#region VisualChild
/// <summary>
/// Returns the first visual child that matches the type T.
/// Performs a breadth-first search.
/// </summary>
/// <typeparam name="T">The type of the child to find.</typeparam>
/// <param name="obj">The object with a visual tree.</param>
/// <returns>Returns an object of type T if found, otherwise null.</returns>
public static T GetVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
if (obj == null)
{
return null;
}
var elementQueue = new Queue<DependencyObject>();
elementQueue.Enqueue(obj);
while (elementQueue.Count > 0)
{
var element = elementQueue.Dequeue();
T item = element as T;
if (item != null)
{
return item;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var child = VisualTreeHelper.GetChild(element, i);
elementQueue.Enqueue(child);
}
}
return null;
}
/// <summary>
/// Finds all children of type within the specified object's visual tree.
/// </summary>
/// <typeparam name="T">The type of the child to find.</typeparam>
/// <param name="obj">The object with a visual tree.</param>
/// <returns>All children of the specified object matching the specified type.</returns>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
public static List<T> FindVisualChildren<T>(DependencyObject obj)
where T : DependencyObject
{
Debug.Assert(obj != null, "obj is null");
if (obj == null)
{
throw new ArgumentNullException("obj");
}
List<T> childrenOfType = new List<T>();
// Recursively loop through children looking for children of type within their trees \\
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject childObj = VisualTreeHelper.GetChild(obj, i);
T child = childObj as T;
if (child != null)
{
childrenOfType.Add(child);
}
else
{
// Recurse \\
childrenOfType.AddRange(FindVisualChildren<T>(childObj));
}
}
return childrenOfType;
}
#endregion VisualChild
/// <summary>
/// Searches ancestors for data of the specified type.
/// </summary>
/// <typeparam name="T">The type of the data to find.</typeparam>
/// <param name="obj">The visual whose ancestors are searched.</param>
/// <returns>The data of the specified type; or if not found, <c>null</c>.</returns>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
public static T FindVisualAncestorData<T>(this DependencyObject obj)
where T : class
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
FrameworkElement parent = obj.FindVisualAncestor<FrameworkElement>();
if (parent != null)
{
T data = parent.DataContext as T;
if (data != null)
{
return data;
}
else
{
return parent.FindVisualAncestorData<T>();
}
}
return null;
}
/// <summary>
/// Walks up the visual tree looking for an ancestor of a given type.
/// </summary>
/// <typeparam name="T">The type to look for.</typeparam>
/// <param name="object">The object to start from.</param>
/// <returns>The parent of the right type, or null.</returns>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
public static T FindVisualAncestor<T>(this DependencyObject @object) where T : class
{
if (@object == null)
{
throw new ArgumentNullException("object");
}
DependencyObject parent = VisualTreeHelper.GetParent(@object);
if (parent != null)
{
T parentObj = parent as T;
if (parentObj != null)
{
return parentObj;
}
return parent.FindVisualAncestor<T>();
}
return null;
}
/// <summary>
/// Executes the <see cref="RoutedCommand"/> on the current command target if it is allowed.
/// </summary>
/// <param name="command">The routed command.</param>
/// <param name="parameter">A user defined data type.</param>
/// <param name="target">The command target.</param>
/// <returns><c>true</c> if the command could execute; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
public static bool TryExecute(this RoutedCommand command, object parameter, IInputElement target)
{
if (command == null)
{
throw new ArgumentNullException("command");
}
if (command.CanExecute(parameter, target))
{
command.Execute(parameter, target);
return true;
}
return false;
}
#region TemplateChild
/// <summary>
/// Gets the named child of an item from a templated control.
/// </summary>
/// <typeparam name="T">The type of the child.</typeparam>
/// <param name="templateParent">The parent of the control.</param>
/// <param name="childName">The name of the child.</param>
/// <returns>The reference to the child, or null if the template part wasn't found.</returns>
public static T GetOptionalTemplateChild<T>(Control templateParent, string childName) where T : FrameworkElement
{
if (templateParent == null)
{
throw new ArgumentNullException("templateParent");
}
if (string.IsNullOrEmpty(childName))
{
throw new ArgumentNullException("childName");
}
object templatePart = templateParent.Template.FindName(childName, templateParent);
T item = templatePart as T;
if (item == null && templatePart != null)
{
HandleWrongTemplatePartType<T>(childName);
}
return item;
}
/// <summary>
/// Gets the named child of an item from a templated control.
/// </summary>
/// <typeparam name="T">The type of the child.</typeparam>
/// <param name="templateParent">The parent of the control.</param>
/// <param name="childName">The name of the child.</param>
/// <returns>The reference to the child.</returns>
public static T GetTemplateChild<T>(Control templateParent, string childName) where T : FrameworkElement
{
T item = GetOptionalTemplateChild<T>(templateParent, childName);
if (item == null)
{
HandleMissingTemplatePart<T>(childName);
}
return item;
}
/// <summary>
/// Throws an exception with information about the template part with the wrong type.
/// </summary>
/// <typeparam name="T">The type of the expected template part.</typeparam>
/// <param name="name">The name of the expected template part.</param>
private static void HandleWrongTemplatePartType<T>(string name)
{
throw new ApplicationException(string.Format(
CultureInfo.CurrentCulture,
"A template part with the name of '{0}' is not of type {1}.",
name,
typeof(T).Name));
}
/// <summary>
/// Throws an exception with information about the missing template part.
/// </summary>
/// <typeparam name="T">The type of the expected template part.</typeparam>
/// <param name="name">The name of the expected template part.</param>
public static void HandleMissingTemplatePart<T>(string name)
{
throw new ApplicationException(string.Format(
CultureInfo.CurrentCulture,
"A template part with the name of '{0}' and type of {1} was not found.",
name,
typeof(T).Name));
}
#endregion TemplateChild
#region SetComponentResourceStyle
/// <summary>
/// Sets Style for control given a component resource key.
/// </summary>
/// <typeparam name="T">Type in which Component Resource Style is Defined.</typeparam>
/// <param name="element">Element whose style need to be set.</param>
/// <param name="keyName">Component Resource Key for Style.</param>
public static void SetComponentResourceStyle<T>(FrameworkElement element, string keyName) where T : FrameworkElement
{
ComponentResourceKey styleKey = new ComponentResourceKey(typeof(T), keyName);
element.Style = (Style)element.FindResource(styleKey);
}
#endregion SetComponentResourceStyle
#region CreateRoutedPropertyChangedEventArgs
/// <summary>
/// Helper function to create a RoutedPropertyChangedEventArgs from a DependencyPropertyChangedEventArgs.
/// </summary>
/// <typeparam name="T">The type for the RoutedPropertyChangedEventArgs.</typeparam>
/// <param name="propertyEventArgs">The DependencyPropertyChangedEventArgs data source.</param>
/// <returns>The created event args, configured from the parameter.</returns>
public static RoutedPropertyChangedEventArgs<T> CreateRoutedPropertyChangedEventArgs<T>(DependencyPropertyChangedEventArgs propertyEventArgs)
{
RoutedPropertyChangedEventArgs<T> eventArgs = new RoutedPropertyChangedEventArgs<T>(
(T)propertyEventArgs.OldValue,
(T)propertyEventArgs.NewValue);
return eventArgs;
}
/// <summary>
/// Helper function to create a RoutedPropertyChangedEventArgs from a DependencyPropertyChangedEventArgs.
/// </summary>
/// <typeparam name="T">The type for the RoutedPropertyChangedEventArgs.</typeparam>
/// <param name="propertyEventArgs">The DependencyPropertyChangedEventArgs data source.</param>
/// <param name="routedEvent">The routed event the property change is associated with.</param>
/// <returns>The created event args, configured from the parameter.</returns>
public static RoutedPropertyChangedEventArgs<T> CreateRoutedPropertyChangedEventArgs<T>(DependencyPropertyChangedEventArgs propertyEventArgs, RoutedEvent routedEvent)
{
RoutedPropertyChangedEventArgs<T> eventArgs = new RoutedPropertyChangedEventArgs<T>(
(T)propertyEventArgs.OldValue,
(T)propertyEventArgs.NewValue,
routedEvent);
return eventArgs;
}
#endregion CreateRoutedPropertyChangedEventArgs
#region ChangeIndex
/// <summary>
/// Moves the item in the specified collection to the specified index.
/// </summary>
/// <param name="items">The collection to move the item in.</param>
/// <param name="item">The item to move.</param>
/// <param name="newIndex">The new index of the item.</param>
/// <exception cref="ArgumentException">The specified item is not in the specified collection.</exception>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
/// <exception cref="ArgumentOutOfRangeException">The specified index is not valid for the specified collection.</exception>
public static void ChangeIndex(ItemCollection items, object item, int newIndex)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
if (!items.Contains(item))
{
throw new ArgumentException("The specified item is not in the specified collection.", "item");
}
if (newIndex < 0 || newIndex > items.Count)
{
throw new ArgumentOutOfRangeException("newIndex", "The specified index is not valid for the specified collection.");
}
int oldIndex = items.IndexOf(item);
// If the tile isn't moving, don't do anything \\
if (newIndex == oldIndex)
{
return;
}
items.Remove(item);
// If adding to the end, add instead of inserting \\
if (newIndex > items.Count)
{
items.Add(item);
}
else
{
items.Insert(newIndex, item);
}
}
#endregion ChangeIndex
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Windows.Automation.Peers;
using System.Windows.Controls;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Represents a decorator that is always visible in the automation tree, indicating that its descendents belong to a logical group.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class AutomationGroup : ContentControl
{
/// <summary>
/// Returns the <see cref="AutomationPeer"/> implementations for this control.
/// </summary>
/// <returns>The <see cref="AutomationPeer"/> implementations for this control.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
return new ExtendedFrameworkElementAutomationPeer(this, AutomationControlType.Group, true);
}
}
}

View File

@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Represents a toggle button used to expand or collapse elements.
/// </summary>
[Localizability(LocalizationCategory.None)]
partial class ExpanderButton
{
//
// CreateAutomationPeer
//
/// <summary>
/// Create an instance of the AutomationPeer.
/// </summary>
/// <returns>
/// An instance of the AutomationPeer.
/// </returns>
protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
{
return new ExpanderButtonAutomationPeer(this);
}
}
}
#endregion

View File

@ -0,0 +1,129 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Represents a toggle button used to expand or collapse elements.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public partial class ExpanderButton : ToggleButton
{
/// <summary>
/// Tooltip to show to expand.
/// </summary>
protected virtual string ExpandToolTip
{
get { return XamlLocalizableResources.AutoResXGen_ManagementList2_ToolTip_32; }
}
/// <summary>
/// Tooltip to show to collapse.
/// </summary>
protected virtual string CollapseToolTip
{
get { return XamlLocalizableResources.CollapsingTabControl_ExpandButton_AutomationName; }
}
/// <summary>
/// Initializes a new instance of the <see cref="ExpanderButton" /> class.
/// </summary>
public ExpanderButton()
{
// This constructor intentionally left blank
}
/// <summary>
/// Invoked whenever the effective value of any dependency property on this <see cref="ExpanderButton"/> has been updated. The specific dependency property that changed is reported in the arguments parameter. Overrides <see cref="FrameworkElement.OnPropertyChanged"/>.
/// </summary>
/// <param name="e">The event data that describes the property that changed, as well as old and new values.</param>
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == ExpanderButton.IsCheckedProperty)
{
this.OnIsCheckedChanged(e);
}
}
/// <summary>
/// Called when the <see cref="ToggleButton.IsChecked"/> property changes.
/// </summary>
/// <param name="args">The event data that describes the property that changed, as well as old and new values.</param>
protected void OnIsCheckedChanged(DependencyPropertyChangedEventArgs args)
{
if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
{
var peer = UIElementAutomationPeer.CreatePeerForElement(this);
if (peer != null)
{
var oldValue = (bool?)args.OldValue;
var newValue = (bool?)args.NewValue;
peer.RaisePropertyChangedEvent(
ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty,
(oldValue == true) ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed,
(newValue == true) ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed);
}
}
SetToolTip();
ToolTip toolTip = (ToolTip)this.ToolTip;
if (toolTip.IsOpen)
{
// need to reset so content changes if already open
toolTip.IsOpen = false;
toolTip.IsOpen = true;
}
}
/// <summary>
/// Called when it has keyboard focus.
/// </summary>
/// <param name="args">The event data that describes getting keyboard focus.</param>
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs args)
{
SetToolTip();
((ToolTip)this.ToolTip).IsOpen = true;
}
/// <summary>
/// Called when it lost keyboard focus.
/// </summary>
/// <param name="args">The event data that describes losing keyboard focus.</param>
protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs args)
{
if (this.ToolTip is ToolTip toolTip)
{
toolTip.IsOpen = false;
}
}
private void SetToolTip()
{
ToolTip toolTip;
if (this.ToolTip is ToolTip)
{
toolTip = (ToolTip)this.ToolTip;
}
else
{
toolTip = new ToolTip();
}
toolTip.Content = (this.IsChecked == true) ? CollapseToolTip : ExpandToolTip;
toolTip.PlacementTarget = this;
toolTip.Placement = PlacementMode.Bottom;
this.ToolTip = toolTip;
}
}
}

View File

@ -0,0 +1,114 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Diagnostics.CodeAnalysis;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides an automation peer for <see cref="ExpanderButton"/>.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class ExpanderButtonAutomationPeer : ToggleButtonAutomationPeer, IExpandCollapseProvider
{
#region Fields
private ExpanderButton expanderButton;
#endregion
#region Structors
/// <summary>
/// Initializes a new instance of the <see cref="ExpanderButtonAutomationPeer" /> class.
/// </summary>
/// <param name="owner">The owner of the automation peer.</param>
public ExpanderButtonAutomationPeer(ExpanderButton owner)
: base(owner)
{
this.expanderButton = owner;
}
#endregion
#region Overrides
/// <summary>
/// Gets the class name.
/// </summary>
/// <returns>The class name.</returns>
protected override string GetClassNameCore()
{
return this.Owner.GetType().Name;
}
/// <summary>
/// Gets the control pattern for the <see cref="ExpanderButton"/> that is associated with this <see cref="ExpanderButtonAutomationPeer"/>.
/// </summary>
/// <param name="patternInterface">Specifies the control pattern that is returned.</param>
/// <returns>The control pattern for the <see cref="ExpanderButton"/> that is associated with this <see cref="ExpanderButtonAutomationPeer"/>.</returns>
public override object GetPattern(PatternInterface patternInterface)
{
if (patternInterface == PatternInterface.ExpandCollapse ||
patternInterface == PatternInterface.Toggle)
{
return this;
}
return null;
}
#endregion
#region IExpandCollapseProvider Implementations
/// <summary>
/// Gets the expand/collapse state of this <see cref="ExpanderButton"/> instance.
/// </summary>
ExpandCollapseState IExpandCollapseProvider.ExpandCollapseState
{
get
{
if (this.expanderButton.IsChecked == true)
{
return ExpandCollapseState.Expanded;
}
else
{
return ExpandCollapseState.Collapsed;
}
}
}
/// <summary>
/// Expands this instance of <see cref="ExpanderButton"/>.
/// </summary>
void IExpandCollapseProvider.Expand()
{
if (!this.IsEnabled())
{
throw new ElementNotEnabledException();
}
this.expanderButton.IsChecked = true;
}
/// <summary>
/// Collapses this instance of <see cref="ExpanderButton"/>.
/// </summary>
void IExpandCollapseProvider.Collapse()
{
if (!this.IsEnabled())
{
throw new ElementNotEnabledException();
}
this.expanderButton.IsChecked = false;
}
#endregion
}
}

View File

@ -0,0 +1,416 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Resizer adds a resizing grip and behavior to any control.
/// </summary>
/// <remarks>
///
///
/// If a custom template is provided for this control, then the template MUST provide the following template parts:
///
/// PART_LeftGrip - A required template part which must be of type Thumb. The grip on the left.
/// PART_RightGrip - A required template part which must be of type Thumb. The grip on the right.
///
/// </remarks>
[TemplatePart(Name="PART_LeftGrip", Type=typeof(Thumb))]
[TemplatePart(Name="PART_RightGrip", Type=typeof(Thumb))]
[Localizability(LocalizationCategory.None)]
partial class Resizer
{
//
// Fields
//
private Thumb leftGrip;
private Thumb rightGrip;
//
// DraggingTemplate dependency property
//
/// <summary>
/// Identifies the DraggingTemplate dependency property.
/// </summary>
public static readonly DependencyProperty DraggingTemplateProperty = DependencyProperty.Register( "DraggingTemplate", typeof(DataTemplate), typeof(Resizer), new PropertyMetadata( null, DraggingTemplateProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the template used for the dragging indicator when ResizeWhileDragging is false.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the template used for the dragging indicator when ResizeWhileDragging is false.")]
[Localizability(LocalizationCategory.None)]
public DataTemplate DraggingTemplate
{
get
{
return (DataTemplate) GetValue(DraggingTemplateProperty);
}
set
{
SetValue(DraggingTemplateProperty,value);
}
}
static private void DraggingTemplateProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
Resizer obj = (Resizer) o;
obj.OnDraggingTemplateChanged( new PropertyChangedEventArgs<DataTemplate>((DataTemplate)e.OldValue, (DataTemplate)e.NewValue) );
}
/// <summary>
/// Occurs when DraggingTemplate property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<DataTemplate>> DraggingTemplateChanged;
/// <summary>
/// Called when DraggingTemplate property changes.
/// </summary>
protected virtual void OnDraggingTemplateChanged(PropertyChangedEventArgs<DataTemplate> e)
{
OnDraggingTemplateChangedImplementation(e);
RaisePropertyChangedEvent(DraggingTemplateChanged, e);
}
partial void OnDraggingTemplateChangedImplementation(PropertyChangedEventArgs<DataTemplate> e);
//
// GripBrush dependency property
//
/// <summary>
/// Identifies the GripBrush dependency property.
/// </summary>
public static readonly DependencyProperty GripBrushProperty = DependencyProperty.Register( "GripBrush", typeof(Brush), typeof(Resizer), new PropertyMetadata( new SolidColorBrush(Colors.Black), GripBrushProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the color of the resize grips.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the color of the resize grips.")]
[Localizability(LocalizationCategory.None)]
public Brush GripBrush
{
get
{
return (Brush) GetValue(GripBrushProperty);
}
set
{
SetValue(GripBrushProperty,value);
}
}
static private void GripBrushProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
Resizer obj = (Resizer) o;
obj.OnGripBrushChanged( new PropertyChangedEventArgs<Brush>((Brush)e.OldValue, (Brush)e.NewValue) );
}
/// <summary>
/// Occurs when GripBrush property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<Brush>> GripBrushChanged;
/// <summary>
/// Called when GripBrush property changes.
/// </summary>
protected virtual void OnGripBrushChanged(PropertyChangedEventArgs<Brush> e)
{
OnGripBrushChangedImplementation(e);
RaisePropertyChangedEvent(GripBrushChanged, e);
}
partial void OnGripBrushChangedImplementation(PropertyChangedEventArgs<Brush> e);
//
// GripLocation dependency property
//
/// <summary>
/// Identifies the GripLocation dependency property.
/// </summary>
public static readonly DependencyProperty GripLocationProperty = DependencyProperty.Register( "GripLocation", typeof(ResizeGripLocation), typeof(Resizer), new PropertyMetadata( ResizeGripLocation.Right, GripLocationProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value of what grips.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value of what grips.")]
[Localizability(LocalizationCategory.None)]
public ResizeGripLocation GripLocation
{
get
{
return (ResizeGripLocation) GetValue(GripLocationProperty);
}
set
{
SetValue(GripLocationProperty,value);
}
}
static private void GripLocationProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
Resizer obj = (Resizer) o;
obj.OnGripLocationChanged( new PropertyChangedEventArgs<ResizeGripLocation>((ResizeGripLocation)e.OldValue, (ResizeGripLocation)e.NewValue) );
}
/// <summary>
/// Occurs when GripLocation property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<ResizeGripLocation>> GripLocationChanged;
/// <summary>
/// Called when GripLocation property changes.
/// </summary>
protected virtual void OnGripLocationChanged(PropertyChangedEventArgs<ResizeGripLocation> e)
{
OnGripLocationChangedImplementation(e);
RaisePropertyChangedEvent(GripLocationChanged, e);
}
partial void OnGripLocationChangedImplementation(PropertyChangedEventArgs<ResizeGripLocation> e);
//
// GripWidth dependency property
//
/// <summary>
/// Identifies the GripWidth dependency property.
/// </summary>
public static readonly DependencyProperty GripWidthProperty = DependencyProperty.Register( "GripWidth", typeof(double), typeof(Resizer), new PropertyMetadata( 4.0, GripWidthProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the width of the grips.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the width of the grips.")]
[Localizability(LocalizationCategory.None)]
public double GripWidth
{
get
{
return (double) GetValue(GripWidthProperty);
}
set
{
SetValue(GripWidthProperty,value);
}
}
static private void GripWidthProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
Resizer obj = (Resizer) o;
obj.OnGripWidthChanged( new PropertyChangedEventArgs<double>((double)e.OldValue, (double)e.NewValue) );
}
/// <summary>
/// Occurs when GripWidth property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<double>> GripWidthChanged;
/// <summary>
/// Called when GripWidth property changes.
/// </summary>
protected virtual void OnGripWidthChanged(PropertyChangedEventArgs<double> e)
{
OnGripWidthChangedImplementation(e);
RaisePropertyChangedEvent(GripWidthChanged, e);
}
partial void OnGripWidthChangedImplementation(PropertyChangedEventArgs<double> e);
//
// ResizeWhileDragging dependency property
//
/// <summary>
/// Identifies the ResizeWhileDragging dependency property.
/// </summary>
public static readonly DependencyProperty ResizeWhileDraggingProperty = DependencyProperty.Register( "ResizeWhileDragging", typeof(bool), typeof(Resizer), new PropertyMetadata( BooleanBoxes.TrueBox, ResizeWhileDraggingProperty_PropertyChanged) );
/// <summary>
/// Gets or sets a value indicating if resizing occurs while dragging.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets a value indicating if resizing occurs while dragging.")]
[Localizability(LocalizationCategory.None)]
public bool ResizeWhileDragging
{
get
{
return (bool) GetValue(ResizeWhileDraggingProperty);
}
set
{
SetValue(ResizeWhileDraggingProperty,BooleanBoxes.Box(value));
}
}
static private void ResizeWhileDraggingProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
Resizer obj = (Resizer) o;
obj.OnResizeWhileDraggingChanged( new PropertyChangedEventArgs<bool>((bool)e.OldValue, (bool)e.NewValue) );
}
/// <summary>
/// Occurs when ResizeWhileDragging property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<bool>> ResizeWhileDraggingChanged;
/// <summary>
/// Called when ResizeWhileDragging property changes.
/// </summary>
protected virtual void OnResizeWhileDraggingChanged(PropertyChangedEventArgs<bool> e)
{
OnResizeWhileDraggingChangedImplementation(e);
RaisePropertyChangedEvent(ResizeWhileDraggingChanged, e);
}
partial void OnResizeWhileDraggingChangedImplementation(PropertyChangedEventArgs<bool> e);
//
// ThumbGripLocation dependency property
//
/// <summary>
/// Identifies the ThumbGripLocation dependency property.
/// </summary>
public static readonly DependencyProperty ThumbGripLocationProperty = DependencyProperty.RegisterAttached( "ThumbGripLocation", typeof(ResizeGripLocation), typeof(Resizer), new PropertyMetadata( ResizeGripLocation.Right, ThumbGripLocationProperty_PropertyChanged) );
/// <summary>
/// Gets the location for a grip.
/// </summary>
/// <param name="element">The dependency object that the property is attached to.</param>
/// <returns>
/// The value of ThumbGripLocation that is attached to element.
/// </returns>
static public ResizeGripLocation GetThumbGripLocation(DependencyObject element)
{
return (ResizeGripLocation) element.GetValue(ThumbGripLocationProperty);
}
/// <summary>
/// Sets the location for a grip.
/// </summary>
/// <param name="element">The dependency object that the property will be attached to.</param>
/// <param name="value">The new value.</param>
static public void SetThumbGripLocation(DependencyObject element, ResizeGripLocation value)
{
element.SetValue(ThumbGripLocationProperty,value);
}
static private void ThumbGripLocationProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ThumbGripLocationProperty_PropertyChangedImplementation(o, e);
}
static partial void ThumbGripLocationProperty_PropertyChangedImplementation(DependencyObject o, DependencyPropertyChangedEventArgs e);
//
// VisibleGripWidth dependency property
//
/// <summary>
/// Identifies the VisibleGripWidth dependency property.
/// </summary>
public static readonly DependencyProperty VisibleGripWidthProperty = DependencyProperty.Register( "VisibleGripWidth", typeof(double ), typeof(Resizer), new PropertyMetadata( 1.0, VisibleGripWidthProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the visible width of the grips.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the visible width of the grips.")]
[Localizability(LocalizationCategory.None)]
public double VisibleGripWidth
{
get
{
return (double ) GetValue(VisibleGripWidthProperty);
}
set
{
SetValue(VisibleGripWidthProperty,value);
}
}
static private void VisibleGripWidthProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
Resizer obj = (Resizer) o;
obj.OnVisibleGripWidthChanged( new PropertyChangedEventArgs<double >((double )e.OldValue, (double )e.NewValue) );
}
/// <summary>
/// Occurs when VisibleGripWidth property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<double >> VisibleGripWidthChanged;
/// <summary>
/// Called when VisibleGripWidth property changes.
/// </summary>
protected virtual void OnVisibleGripWidthChanged(PropertyChangedEventArgs<double > e)
{
OnVisibleGripWidthChangedImplementation(e);
RaisePropertyChangedEvent(VisibleGripWidthChanged, e);
}
partial void OnVisibleGripWidthChangedImplementation(PropertyChangedEventArgs<double > e);
/// <summary>
/// Called when a property changes.
/// </summary>
private void RaisePropertyChangedEvent<T>(EventHandler<PropertyChangedEventArgs<T>> eh, PropertyChangedEventArgs<T> e)
{
if (eh != null)
{
eh(this,e);
}
}
//
// OnApplyTemplate
//
/// <summary>
/// Called when ApplyTemplate is called.
/// </summary>
public override void OnApplyTemplate()
{
PreOnApplyTemplate();
base.OnApplyTemplate();
this.leftGrip = WpfHelp.GetTemplateChild<Thumb>(this,"PART_LeftGrip");
this.rightGrip = WpfHelp.GetTemplateChild<Thumb>(this,"PART_RightGrip");
PostOnApplyTemplate();
}
partial void PreOnApplyTemplate();
partial void PostOnApplyTemplate();
//
// Static constructor
//
/// <summary>
/// Called when the type is initialized.
/// </summary>
static Resizer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Resizer), new FrameworkPropertyMetadata(typeof(Resizer)));
StaticConstructorImplementation();
}
static partial void StaticConstructorImplementation();
}
}
#endregion

View File

@ -0,0 +1,227 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The resize grip possibilities.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public enum ResizeGripLocation
{
/// <summary>
/// One grip is shown, on the right side.
/// </summary>
Right,
/// <summary>
/// One grip is shown, on the left side.
/// </summary>
Left,
}
/// <content>
/// Partial class implementation for Resizer control.
/// </content>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public partial class Resizer : ContentControl
{
private AdornerLayer adornerLayer;
private UIElementAdorner adorner;
private ContentControl adornerContent;
/// <summary>
/// Creates an instance of Resizer.
/// </summary>
public Resizer()
{
// nothing
}
internal static Thickness CreateGripThickness(double visibleGripWidth, ResizeGripLocation gripLocation)
{
Thickness thickness;
if (visibleGripWidth < 0.0 || double.IsNaN(visibleGripWidth))
{
throw new ArgumentOutOfRangeException("visibleGripWidth", "The value must be greater than or equal to 0.");
}
if (double.IsInfinity(visibleGripWidth))
{
throw new ArgumentOutOfRangeException("visibleGripWidth", "The value must be less than infinity.");
}
switch (gripLocation)
{
case ResizeGripLocation.Right:
thickness = new Thickness(0, 0, visibleGripWidth, 0);
break;
case ResizeGripLocation.Left:
thickness = new Thickness(visibleGripWidth, 0, 0, 0);
break;
default:
throw new InvalidEnumArgumentException("gripLocation", (int)gripLocation, typeof(ResizeGripLocation));
}
return thickness;
}
partial void PreOnApplyTemplate()
{
if (this.rightGrip != null)
{
this.rightGrip.DragDelta -= this.OnRightGripDragDelta;
this.rightGrip.DragStarted -= this.OnRightGripDragStarted;
this.rightGrip.DragCompleted -= this.OnRightGripDragCompleted;
}
if (this.leftGrip != null)
{
this.leftGrip.DragDelta -= this.OnLeftGripDragDelta;
this.leftGrip.DragStarted -= this.OnLeftGripDragStarted;
this.leftGrip.DragCompleted -= this.OnLeftGripDragCompleted;
}
}
partial void PostOnApplyTemplate()
{
this.rightGrip.DragDelta += this.OnRightGripDragDelta;
this.rightGrip.DragStarted += this.OnRightGripDragStarted;
this.rightGrip.DragCompleted += this.OnRightGripDragCompleted;
this.leftGrip.DragDelta += this.OnLeftGripDragDelta;
this.leftGrip.DragStarted += this.OnLeftGripDragStarted;
this.leftGrip.DragCompleted += this.OnLeftGripDragCompleted;
}
private void CreateAdorner()
{
this.adornerLayer = AdornerLayer.GetAdornerLayer(this);
this.adorner = new UIElementAdorner(this);
this.adornerContent = new ContentControl();
this.adornerContent.Name = "ResizerAdornerContent";
this.adornerContent.HorizontalContentAlignment = HorizontalAlignment.Stretch;
this.adornerContent.VerticalContentAlignment = VerticalAlignment.Stretch;
this.adornerContent.ContentTemplate = this.DraggingTemplate;
this.adorner.Child = this.adornerContent;
}
private void RemoveAdorner()
{
this.adornerLayer.Remove(this.adorner);
}
private void OnLeftGripDragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
this.StopDragging(ResizeGripLocation.Left, e);
}
private void OnLeftGripDragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
this.StartDragging(ResizeGripLocation.Left);
}
private void OnLeftGripDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
this.PerformDrag(ResizeGripLocation.Left, e);
}
private void OnRightGripDragCompleted(object sender, DragCompletedEventArgs e)
{
this.StopDragging(ResizeGripLocation.Right, e);
}
private void OnRightGripDragStarted(object sender, DragStartedEventArgs e)
{
this.StartDragging(ResizeGripLocation.Right);
}
private void OnRightGripDragDelta(object sender, DragDeltaEventArgs e)
{
this.PerformDrag(ResizeGripLocation.Right, e);
}
private void PerformDrag(ResizeGripLocation location, DragDeltaEventArgs e)
{
double newWidth = this.GetNewWidth(location, e.HorizontalChange);
if (this.ResizeWhileDragging)
{
this.Width = newWidth;
}
else
{
this.adorner.Width = newWidth;
}
}
private void StartDragging(ResizeGripLocation location)
{
if (this.ResizeWhileDragging == false)
{
if (this.adornerLayer == null)
{
this.CreateAdorner();
}
this.adornerContent.Content = location;
this.adornerLayer.Add(this.adorner);
this.adorner.Height = this.ActualHeight;
this.adorner.Width = this.ActualWidth;
}
}
private void StopDragging(ResizeGripLocation location, DragCompletedEventArgs e)
{
if (this.ResizeWhileDragging == false)
{
this.RemoveAdorner();
double newWidth = this.GetNewWidth(location, e.HorizontalChange);
this.Width = newWidth;
}
}
private double GetNewWidth(ResizeGripLocation location, double horzDelta)
{
var realDelta = this.GetHorizontalDelta(location, horzDelta);
double newWidth = this.ActualWidth + realDelta;
return this.GetConstrainedValue(newWidth, this.MaxWidth, this.MinWidth);
}
private double GetHorizontalDelta(ResizeGripLocation location, double horzDelta)
{
double realDelta;
if (location == ResizeGripLocation.Right)
{
realDelta = horzDelta;
}
else
{
Debug.Assert(location == ResizeGripLocation.Left, "location is left");
realDelta = -horzDelta;
}
return realDelta;
}
private double GetConstrainedValue(double value, double max, double min)
{
return Math.Min(max, Math.Max(value, min));
}
}
}

View File

@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// A converter which creates the proper thickness for the content of the Resizer, depending on the grip visual size
/// and grip position.
/// </summary>
/// <remarks>
/// The first value needs to be a double which is the visible grip size.
/// The second value needs to the be ResizeGripLocation value used.
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public class ResizerGripThicknessConverter : IMultiValueConverter
{
/// <summary>
/// Creates an instance of ResizerGripThicknessConverter.
/// </summary>
public ResizerGripThicknessConverter()
{
// nothing
}
/// <summary>
/// Converts a value.
/// </summary>
/// <param name="values">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>A converted value. If the method returns nullNothingnullptra null reference (Nothing in Visual Basic), the valid null value is used.</returns>
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (object.ReferenceEquals(values[0], DependencyProperty.UnsetValue) ||
object.ReferenceEquals(values[1], DependencyProperty.UnsetValue))
{
return DependencyProperty.UnsetValue;
}
var resizerVisibleGripWidth = (double)values[0];
var gripLocation = (ResizeGripLocation)values[1];
return Resizer.CreateGripThickness(resizerVisibleGripWidth, gripLocation);
}
/// <summary>
/// Converts a value.
/// </summary>
/// <param name="value">The value that is produced by the binding target.</param>
/// <param name="targetTypes">The type to convert to.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>A converted values. If the method returns nullNothingnullptra null reference (Nothing in Visual Basic), the valid null value is used.</returns>
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,81 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region StyleCop Suppression - generated code
using System;
using System.ComponentModel;
using System.Windows;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// An Adorner which displays a given UIElement.
/// </summary>
[Localizability(LocalizationCategory.None)]
partial class UIElementAdorner
{
//
// Child dependency property
//
/// <summary>
/// Identifies the Child dependency property.
/// </summary>
public static readonly DependencyProperty ChildProperty = DependencyProperty.Register( "Child", typeof(UIElement), typeof(UIElementAdorner), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions. AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure , ChildProperty_PropertyChanged) );
/// <summary>
/// Gets or sets the child element.
/// </summary>
[Bindable(true)]
[Category("Common Properties")]
[Description("Gets or sets the child element.")]
[Localizability(LocalizationCategory.None)]
public UIElement Child
{
get
{
return (UIElement) GetValue(ChildProperty);
}
set
{
SetValue(ChildProperty,value);
}
}
static private void ChildProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
UIElementAdorner obj = (UIElementAdorner) o;
obj.OnChildChanged( new PropertyChangedEventArgs<UIElement>((UIElement)e.OldValue, (UIElement)e.NewValue) );
}
/// <summary>
/// Occurs when Child property changes.
/// </summary>
public event EventHandler<PropertyChangedEventArgs<UIElement>> ChildChanged;
/// <summary>
/// Called when Child property changes.
/// </summary>
private void RaiseChildChanged(PropertyChangedEventArgs<UIElement> e)
{
var eh = this.ChildChanged;
if (eh != null)
{
eh(this,e);
}
}
/// <summary>
/// Called when Child property changes.
/// </summary>
protected virtual void OnChildChanged(PropertyChangedEventArgs<UIElement> e)
{
OnChildChangedImplementation(e);
RaiseChildChanged(e);
}
partial void OnChildChangedImplementation(PropertyChangedEventArgs<UIElement> e);
}
}
#endregion

View File

@ -0,0 +1,105 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
namespace Microsoft.Management.UI.Internal
{
/// <content>
/// Partial class implementation for UIElementAdorner.
/// </content>
internal partial class UIElementAdorner : Adorner
{
private VisualCollection children;
/// <summary>
/// Constructs an instance of UIElementAdorner.
/// </summary>
/// <param name="adornedElement">The adorned element.</param>
public UIElementAdorner(UIElement adornedElement)
: base(adornedElement)
{
this.children = new VisualCollection(this);
}
/// <summary>
/// Overrides Visual.GetVisualChild, and returns a child at the specified index from a collection of child elements.
/// </summary>
/// <param name="index">The zero-based index of the requested child element in the collection. </param>
/// <returns>The requested child element. This should not return null; if the provided index is out of range, an exception is thrown.</returns>
protected override Visual GetVisualChild(int index)
{
return this.children[index];
}
/// <summary>
/// Gets the number of visual child elements within this element.
/// </summary>
protected override int VisualChildrenCount
{
get
{
return this.children.Count;
}
}
/// <summary>
/// Implements any custom measuring behavior for the popupAdorner.
/// </summary>
/// <param name="constraint">A size to constrain the popupAdorner to. </param>
/// <returns>A Size object representing the amount of layout space needed by the popupAdorner.</returns>
protected override Size MeasureOverride(Size constraint)
{
if (this.Child != null)
{
this.Child.Measure(constraint);
return this.Child.DesiredSize;
}
else
{
return base.MeasureOverride(constraint);
}
}
/// <summary>
/// When overridden in a derived class, positions child elements and determines a size for a FrameworkElement derived class.
/// </summary>
/// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param>
/// <returns>The actual size used.</returns>
protected override Size ArrangeOverride(Size finalSize)
{
if (this.Child != null)
{
Point location = new Point(0, 0);
Rect rect = new Rect(location, finalSize);
this.Child.Arrange(rect);
return this.Child.RenderSize;
}
else
{
return base.ArrangeOverride(finalSize);
}
}
partial void OnChildChangedImplementation(PropertyChangedEventArgs<UIElement> e)
{
if (e.OldValue != null)
{
this.children.Remove(e.OldValue);
this.RemoveLogicalChild(e.OldValue);
}
if (this.Child != null)
{
this.children.Add(this.Child);
this.AddLogicalChild(this.Child);
}
}
}
}

View File

@ -0,0 +1,351 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The BuiltinDataErrorInfoValidationRuleFactory creates default settings for the
/// builtin FilterRules.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class DefaultFilterRuleCustomizationFactory : FilterRuleCustomizationFactory
{
private IPropertyValueGetter propertyValueGetter;
/// <summary>
/// Gets or sets a <see cref="IPropertyValueGetter"/> that can retrieve the values of properties on a given object.
/// </summary>
public override IPropertyValueGetter PropertyValueGetter
{
get
{
if (this.propertyValueGetter == null)
{
this.propertyValueGetter = new PropertyValueGetter();
}
return this.propertyValueGetter;
}
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
this.propertyValueGetter = value;
}
}
/// <summary>
/// Returns a collection containing the default rules used by a PropertyValueSelectorFilterRule
/// for type t.
/// </summary>
/// <typeparam name="T">
/// The type used to determine what rules to include.
/// </typeparam>
/// <returns>
/// Returns a collection of FilterRules.
/// </returns>
public override ICollection<FilterRule> CreateDefaultFilterRulesForPropertyValueSelectorFilterRule<T>()
{
Collection<FilterRule> rules = new Collection<FilterRule>();
Type t = typeof(T);
if (t == typeof(string))
{
rules.Add(new TextContainsFilterRule());
rules.Add(new TextDoesNotContainFilterRule());
rules.Add(new TextStartsWithFilterRule());
rules.Add(new TextEqualsFilterRule());
rules.Add(new TextDoesNotEqualFilterRule());
rules.Add(new TextEndsWithFilterRule());
rules.Add(new IsEmptyFilterRule());
rules.Add(new IsNotEmptyFilterRule());
}
else if (t == typeof(bool))
{
rules.Add(new EqualsFilterRule<T>());
}
else if (t.IsEnum)
{
rules.Add(new EqualsFilterRule<T>());
rules.Add(new DoesNotEqualFilterRule<T>());
}
else
{
rules.Add(new IsLessThanFilterRule<T>());
rules.Add(new IsGreaterThanFilterRule<T>());
rules.Add(new IsBetweenFilterRule<T>());
rules.Add(new EqualsFilterRule<T>());
rules.Add(new DoesNotEqualFilterRule<T>());
rules.Add(new TextContainsFilterRule());
rules.Add(new TextDoesNotContainFilterRule());
}
return rules;
}
/// <summary>
/// Transfers the values from the old rule into the new rule.
/// </summary>
/// <param name="oldRule">
/// The old filter rule.
/// </param>
/// <param name="newRule">
/// The new filter rule.
/// </param>
public override void TransferValues(FilterRule oldRule, FilterRule newRule)
{
if (oldRule == null)
{
throw new ArgumentNullException("oldRule");
}
if (newRule == null)
{
throw new ArgumentNullException("newRule");
}
if (this.TryTransferValuesAsSingleValueComparableValueFilterRule(oldRule, newRule))
{
return;
}
}
/// <summary>
/// Clears the values from the filter rule.
/// </summary>
/// <param name="rule">
/// The rule to clear.
/// </param>
public override void ClearValues(FilterRule rule)
{
if (rule == null)
{
throw new ArgumentNullException("rule");
}
if (this.TryClearValueFromSingleValueComparableValueFilterRule(rule))
{
return;
}
if (this.TryClearIsBetweenFilterRule(rule))
{
return;
}
}
/// <summary>
/// Get an error message to display to a user when they
/// provide a string value that cannot be parsed to type
/// typeToParseTo.
/// </summary>
/// <param name="value">
/// The value entered by the user.
/// </param>
/// <param name="typeToParseTo">
/// The desired type to parse value to.
/// </param>
/// <returns>
/// An error message to a user to explain how they can
/// enter a valid value.
/// </returns>
public override string GetErrorMessageForInvalidValue(string value, Type typeToParseTo)
{
if (typeToParseTo == null)
{
throw new ArgumentNullException("typeToParseTo");
}
bool isNumericType = false
|| typeToParseTo == typeof(byte)
|| typeToParseTo == typeof(sbyte)
|| typeToParseTo == typeof(short)
|| typeToParseTo == typeof(ushort)
|| typeToParseTo == typeof(int)
|| typeToParseTo == typeof(uint)
|| typeToParseTo == typeof(long)
|| typeToParseTo == typeof(ulong)
|| typeToParseTo == typeof(Single)
|| typeToParseTo == typeof(double);
if (isNumericType)
{
return string.Format(CultureInfo.CurrentCulture, UICultureResources.ErrorMessageForUnparsableNumericType);
}
if (typeToParseTo == typeof(DateTime))
{
return string.Format(CultureInfo.CurrentCulture, UICultureResources.ErrorMessageForUnparsableDateTimeType, CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern);
}
return string.Format(CultureInfo.CurrentCulture, UICultureResources.ErrorTextBoxTypeConversionErrorText, typeToParseTo.Name);
}
#region Private Methods
#region Helpers
private bool TryGetGenericParameterForComparableValueFilterRule(FilterRule rule, out Type genericParameter)
{
genericParameter = null;
TextFilterRule textRule = rule as TextFilterRule;
if (textRule != null)
{
genericParameter = typeof(string);
return true;
}
Type ruleType = rule.GetType();
if (!ruleType.IsGenericType)
{
return false;
}
genericParameter = ruleType.GetGenericArguments()[0];
return true;
}
private object GetValueFromValidatingValue(FilterRule rule, string propertyName)
{
Debug.Assert(rule != null && !string.IsNullOrEmpty(propertyName), "rule and propertyname are not null");
// NOTE: This isn't needed but OACR is complaining
if (rule == null)
{
throw new ArgumentNullException("rule");
}
Type ruleType = rule.GetType();
PropertyInfo property = ruleType.GetProperty(propertyName);
object validatingValue = property.GetValue(rule, null);
property = property.PropertyType.GetProperty("Value");
return property.GetValue(validatingValue, null);
}
private void SetValueOnValidatingValue(FilterRule rule, string propertyName, object value)
{
Debug.Assert(rule != null && !string.IsNullOrEmpty(propertyName), "rule and propertyname are not null");
// NOTE: This isn't needed but OACR is complaining
if (rule == null)
{
throw new ArgumentNullException("rule");
}
Type ruleType = rule.GetType();
PropertyInfo property = ruleType.GetProperty(propertyName);
object validatingValue = property.GetValue(rule, null);
property = property.PropertyType.GetProperty("Value");
property.SetValue(validatingValue, value, null);
}
#endregion Helpers
#region SingleValueComparableValueFilterRule
private bool TryTransferValuesAsSingleValueComparableValueFilterRule(FilterRule oldRule, FilterRule newRule)
{
Debug.Assert(oldRule != null && newRule != null, "oldrule and newrule are not null");
bool areCorrectType = this.IsSingleValueComparableValueFilterRule(oldRule) && this.IsSingleValueComparableValueFilterRule(newRule);
if (!areCorrectType)
{
return false;
}
object value = this.GetValueFromValidatingValue(oldRule, "Value");
this.SetValueOnValidatingValue(newRule, "Value", value);
return true;
}
private bool TryClearValueFromSingleValueComparableValueFilterRule(FilterRule rule)
{
Debug.Assert(rule != null, "rule is not null");
if (!this.IsSingleValueComparableValueFilterRule(rule))
{
return false;
}
this.SetValueOnValidatingValue(rule, "Value", null);
return true;
}
private bool IsSingleValueComparableValueFilterRule(FilterRule rule)
{
Debug.Assert(rule != null, "rule is not null");
Type genericParameter;
if (!this.TryGetGenericParameterForComparableValueFilterRule(rule, out genericParameter))
{
return false;
}
Type ruleType = rule.GetType();
Type baseGenericType = typeof(SingleValueComparableValueFilterRule<>);
Type baseType = baseGenericType.MakeGenericType(genericParameter);
return baseType.Equals(ruleType) || ruleType.IsSubclassOf(baseType);
}
#endregion SingleValueComparableValueFilterRule
#region IsBetweenFilterRule
private bool TryClearIsBetweenFilterRule(FilterRule rule)
{
Debug.Assert(rule != null, "rule is not null");
if (!this.IsIsBetweenFilterRule(rule))
{
return false;
}
this.SetValueOnValidatingValue(rule, "StartValue", null);
this.SetValueOnValidatingValue(rule, "EndValue", null);
return true;
}
private bool IsIsBetweenFilterRule(FilterRule rule)
{
Debug.Assert(rule != null, "rule is not null");
Type genericParameter;
if (!this.TryGetGenericParameterForComparableValueFilterRule(rule, out genericParameter))
{
return false;
}
Type ruleType = rule.GetType();
Type baseGenericType = typeof(IsBetweenFilterRule<>);
Type baseType = baseGenericType.MakeGenericType(genericParameter);
return baseType.Equals(ruleType) || ruleType.IsSubclassOf(baseType);
}
#endregion IsBetweenFilterRule
#endregion Private Methods
}
}

View File

@ -0,0 +1,246 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The FilterEvaluator class is responsible for allowing the registeration of
/// the FilterExpressionProviders and producing a FilterExpression composed of
/// the FilterExpression returned from the providers.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public abstract class FilterEvaluator : IFilterExpressionProvider, INotifyPropertyChanged
{
#region Properties
private Collection<IFilterExpressionProvider> filterExpressionProviders = new Collection<IFilterExpressionProvider>();
/// <summary>
/// Gets a readonly collection of the registered FilterExpressionProviders.
/// </summary>
public ReadOnlyCollection<IFilterExpressionProvider> FilterExpressionProviders
{
get
{
return new ReadOnlyCollection<IFilterExpressionProvider>(this.filterExpressionProviders);
}
}
private FilterStatus filterStatus = FilterStatus.NotApplied;
/// <summary>
/// Gets a value indicating the status of the filter evaluation.
/// </summary>
public FilterStatus FilterStatus
{
get
{
return this.filterStatus;
}
protected set
{
this.filterStatus = value;
this.NotifyPropertyChanged("FilterStatus");
}
}
private bool startFilterOnExpressionChanged = true;
/// <summary>
/// Gets a value indicating the status of the filter evaluation.
/// </summary>
public bool StartFilterOnExpressionChanged
{
get
{
return this.startFilterOnExpressionChanged;
}
set
{
this.startFilterOnExpressionChanged = value;
this.NotifyPropertyChanged("StartFilterOnExpressionChanged");
}
}
private bool hasFilterExpression = false;
/// <summary>
/// Gets a value indicating whether this provider currently has a non-empty filter expression.
/// </summary>
public bool HasFilterExpression
{
get
{
return this.hasFilterExpression;
}
protected set
{
this.hasFilterExpression = value;
this.NotifyPropertyChanged("HasFilterExpression");
}
}
#endregion Properties
#region Events
/// <summary>
/// Notifies listeners that a property has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion Events
#region Public Methods
/// <summary>
/// Applies the filter.
/// </summary>
public abstract void StartFilter();
/// <summary>
/// Stops the filter.
/// </summary>
public abstract void StopFilter();
/// <summary>
/// Returns a FilterExpression composed of FilterExpressions returned from the
/// registered providers.
/// </summary>
/// <returns>
/// The FilterExpression composed of FilterExpressions returned from the
/// registered providers.
/// </returns>
public FilterExpressionNode FilterExpression
{
get
{
FilterExpressionAndOperatorNode andNode = new FilterExpressionAndOperatorNode();
foreach (IFilterExpressionProvider provider in this.FilterExpressionProviders)
{
FilterExpressionNode node = provider.FilterExpression;
if (node != null)
{
andNode.Children.Add(node);
}
}
return (andNode.Children.Count != 0) ? andNode : null;
}
}
/// <summary>
/// Adds a FilterExpressionProvider to the FilterEvaluator.
/// </summary>
/// <param name="provider">
/// The provider to add.
/// </param>
public void AddFilterExpressionProvider(IFilterExpressionProvider provider)
{
if (provider == null)
{
throw new ArgumentNullException("provider");
}
this.filterExpressionProviders.Add(provider);
provider.FilterExpressionChanged += new EventHandler(this.FilterProvider_FilterExpressionChanged);
}
/// <summary>
/// Removes a FilterExpressionProvider from the FilterEvaluator.
/// </summary>
/// <param name="provider">
/// The provider to remove.
/// </param>
public void RemoveFilterExpressionProvider(IFilterExpressionProvider provider)
{
if (provider == null)
{
throw new ArgumentNullException("provider");
}
this.filterExpressionProviders.Remove(provider);
provider.FilterExpressionChanged -= new EventHandler(this.FilterProvider_FilterExpressionChanged);
}
#region NotifyPropertyChanged
/// <summary>
/// Notifies listeners that a property has changed.
/// </summary>
/// <param name="propertyName">
/// The propertyName which has changed.
/// </param>
protected void NotifyPropertyChanged(string propertyName)
{
Debug.Assert(!string.IsNullOrEmpty(propertyName), "propertyName is not null");
PropertyChangedEventHandler eh = this.PropertyChanged;
if (eh != null)
{
eh(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion NotifyPropertyChanged
#endregion Public Methods
#region Private Methods
/// <summary>
/// Occurs when the filter expression has changed.
/// </summary>
public event EventHandler FilterExpressionChanged;
/// <summary>
/// Notifies any listeners that the filter expression has changed.
/// </summary>
protected virtual void NotifyFilterExpressionChanged()
{
EventHandler eh = this.FilterExpressionChanged;
if (eh != null)
{
eh(this, new EventArgs());
}
}
private void FilterProvider_FilterExpressionChanged(object sender, EventArgs e)
{
// Update HasFilterExpression \\
var hasFilterExpression = false;
foreach (IFilterExpressionProvider provider in this.FilterExpressionProviders)
{
if (provider.HasFilterExpression)
{
hasFilterExpression = true;
break;
}
}
this.HasFilterExpression = hasFilterExpression;
// Update FilterExpression \\
this.NotifyFilterExpressionChanged();
this.NotifyPropertyChanged("FilterExpression");
// Start filtering if requested \\
if (this.StartFilterOnExpressionChanged)
{
this.StartFilter();
}
}
#endregion Private Methods
}
}

View File

@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The EventArgs detailing the exception raised while
/// evaluating the filter.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class FilterExceptionEventArgs : EventArgs
{
/// <summary>
/// Gets the Exception that was raised when filtering was
/// evaluated.
/// </summary>
public Exception Exception
{
get;
private set;
}
/// <summary>
/// Initializes a new instance of the FilterExceptionEventArgs
/// class.
/// </summary>
/// <param name="exception">
/// The Exception that was raised when filtering was evaluated.
/// </param>
public FilterExceptionEventArgs(Exception exception)
{
if (exception == null)
{
throw new ArgumentNullException("exception");
}
this.Exception = exception;
}
}
}

View File

@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The FilterExpressionAndOperatorNode class is responsible for containing children
/// FilterExpressionNodes which will be AND'ed together during evaluation.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class FilterExpressionAndOperatorNode : FilterExpressionNode
{
#region Properties
private List<FilterExpressionNode> children = new List<FilterExpressionNode>();
/// <summary>
/// Gets a collection FilterExpressionNode children used during evaluation.
/// </summary>
public ICollection<FilterExpressionNode> Children
{
get
{
return this.children;
}
}
#endregion Properties
#region Ctor
/// <summary>
/// Initializes a new instance of the FilterExpressionAndOperatorNode
/// class.
/// </summary>
public FilterExpressionAndOperatorNode()
{
// empty
}
/// <summary>
/// Initializes a new instance of the FilterExpressionAndOperatorNode
/// class.
/// </summary>
/// <param name="children">
/// A collection of children which will be added to the
/// FilterExpressionAndOperatorNode's Children collection.
/// </param>
public FilterExpressionAndOperatorNode(IEnumerable<FilterExpressionNode> children)
{
if (children == null)
{
throw new ArgumentNullException("children");
}
this.children.AddRange(children);
}
#endregion Ctor
#region Public Methods
/// <summary>
/// Evaluates the children FilterExpressionNodes and returns
/// the AND'ed result of their results.
/// </summary>
/// <param name="item">
/// The item to evaluate against.
/// </param>
/// <returns>
/// True if all FilterExpressionNode children evaluate to true,
/// false otherwise.
/// </returns>
public override bool Evaluate(object item)
{
if (this.Children.Count == 0)
{
return false;
}
foreach (FilterExpressionNode node in this.Children)
{
if (!node.Evaluate(item))
{
return false;
}
}
return true;
}
#endregion Public Methods
}
}

View File

@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The FilterExpressionNode class is the base class for derived
/// FilterExpressionNodes. FilterExpressionNodes are used to
/// construct a logical evaluation tree which holds FilterRules as
/// its operands.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public abstract class FilterExpressionNode : IEvaluate
{
/// <summary>
/// In derived classes, this evaluation will return a true or
/// false result based upon some criteria.
/// </summary>
/// <param name="item">
/// The item to evaluate against.
/// </param>
/// <returns>
/// True if the criteria is met, false otherwise.
/// </returns>
public abstract bool Evaluate(object item);
/// <summary>
/// Retrieves all elements of the specified type within the entire expression tree.
/// </summary>
/// <typeparam name="T">The type of the items to find.</typeparam>
/// <returns>All elements of the specified type within the entire expression tree.</returns>
public ICollection<T> FindAll<T>()
{
var ts = new List<T>();
var operandNode = this as FilterExpressionOperandNode;
if (operandNode != null)
{
if (typeof(T).IsInstanceOfType(operandNode.Rule))
{
object obj = operandNode.Rule;
ts.Add((T)obj);
}
}
var operatorAndNode = this as FilterExpressionAndOperatorNode;
if (operatorAndNode != null)
{
foreach (var childNode in operatorAndNode.Children)
{
ts.AddRange(childNode.FindAll<T>());
}
}
var operatorOrNode = this as FilterExpressionOrOperatorNode;
if (operatorOrNode != null)
{
foreach (var childNode in operatorOrNode.Children)
{
ts.AddRange(childNode.FindAll<T>());
}
}
return ts;
}
}
}

View File

@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The FilterExpressionOperandNode class is responsible for holding a
/// FilterRule within the FilterExpression tree.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class FilterExpressionOperandNode : FilterExpressionNode
{
#region Properties
/// <summary>
/// The FilterRule to evaluate.
/// </summary>
public FilterRule Rule
{
get;
protected set;
}
#endregion Properties
#region Ctor
/// <summary>
/// Initializes a new instance of the FilterExpressionOperandNode
/// class.
/// </summary>
/// <param name="rule">
/// The FilterRule to hold for evaluation.
/// </param>
public FilterExpressionOperandNode(FilterRule rule)
{
if (rule == null)
{
throw new ArgumentNullException("rule");
}
this.Rule = rule;
}
#endregion Ctor
#region Public Methods
/// <summary>
/// Evaluates the item against the contained FilterRule.
/// </summary>
/// <param name="item">
/// The item to pass to the contained FilterRule.
/// </param>
/// <returns>
/// Returns true if the contained FilterRule evaluates to
/// true, false otherwise.
/// </returns>
public override bool Evaluate(object item)
{
Debug.Assert(this.Rule != null, "rule is not null");
return this.Rule.Evaluate(item);
}
#endregion Public Methods
}
}

View File

@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The FilterExpressionOrOperatorNode class is responsible for containing children
/// FilterExpressionNodes which will be OR'ed together during evaluation.
/// </summary>
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class FilterExpressionOrOperatorNode : FilterExpressionNode
{
#region Properties
private List<FilterExpressionNode> children = new List<FilterExpressionNode>();
/// <summary>
/// Gets a collection FilterExpressionNode children used during evaluation.
/// </summary>
public ICollection<FilterExpressionNode> Children
{
get
{
return this.children;
}
}
#endregion Properties
#region Ctor
/// <summary>
/// Initializes a new instance of the FilterExpressionOrOperatorNode
/// class.
/// </summary>
public FilterExpressionOrOperatorNode()
{
// empty
}
/// <summary>
/// Initializes a new instance of the FilterExpressionOrOperatorNode
/// class.
/// </summary>
/// <param name="children">
/// A collection of children which will be added to the
/// FilterExpressionOrOperatorNode's Children collection.
/// </param>
public FilterExpressionOrOperatorNode(IEnumerable<FilterExpressionNode> children)
{
if (children == null)
{
throw new ArgumentNullException("children");
}
this.children.AddRange(children);
}
#endregion Ctor
#region Public Methods
/// <summary>
/// Evaluates the children FilterExpressionNodes and returns
/// the OR'ed result of their results.
/// </summary>
/// <param name="item">
/// The item to evaluate against.
/// </param>
/// <returns>
/// True if any FilterExpressionNode child evaluates to true,
/// false otherwise.
/// </returns>
public override bool Evaluate(object item)
{
if (this.Children.Count == 0)
{
return false;
}
foreach (FilterExpressionNode node in this.Children)
{
if (node.Evaluate(item))
{
return true;
}
}
return false;
}
#endregion Public Methods
}
}

View File

@ -0,0 +1,109 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The FilterRuleCustomizationFactory class provides a central location
/// a return an abstract factory which creates the standard settings and rules
/// used by the builtin FilterRules.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public abstract class FilterRuleCustomizationFactory
{
private static FilterRuleCustomizationFactory factoryInstance;
/// <summary>
/// Gets or sets a factory instance which is used by builtin
/// filter rules.
/// </summary>
public static FilterRuleCustomizationFactory FactoryInstance
{
get
{
Debug.Assert(factoryInstance != null, "factoryInstance not null");
return factoryInstance;
}
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
factoryInstance = value;
}
}
/// <summary>
/// Initializes the static state of the DataErrorInfoValidationRuleFactory class.
/// </summary>
static FilterRuleCustomizationFactory()
{
FactoryInstance = new DefaultFilterRuleCustomizationFactory();
}
/// <summary>
/// Gets or sets a <see cref="IPropertyValueGetter"/> that can retrieve the values of properties on a given object.
/// </summary>
public abstract IPropertyValueGetter PropertyValueGetter
{
get;
set;
}
/// <summary>
/// Returns a collection containing the default rules used by a PropertyValueSelectorFilterRule
/// for type T.
/// </summary>
/// <typeparam name="T">
/// The type used to determine what rules to include.
/// </typeparam>
/// <returns>
/// Returns a collection of FilterRules.
/// </returns>
public abstract ICollection<FilterRule> CreateDefaultFilterRulesForPropertyValueSelectorFilterRule<T>() where T : IComparable;
/// <summary>
/// Transfers the values from the old rule into the new rule.
/// </summary>
/// <param name="oldRule">
/// The old filter rule.
/// </param>
/// <param name="newRule">
/// The new filter rule.
/// </param>
public abstract void TransferValues(FilterRule oldRule, FilterRule newRule);
/// <summary>
/// Clears the values from the filter rule.
/// </summary>
/// <param name="rule">
/// The rule to clear.
/// </param>
public abstract void ClearValues(FilterRule rule);
/// <summary>
/// Get an error message to display to a user when they
/// provide a string value that cannot be parsed to type
/// typeToParseTo.
/// </summary>
/// <param name="value">
/// The value entered by the user.
/// </param>
/// <param name="typeToParseTo">
/// The desired type to parse value to.
/// </param>
/// <returns>
/// An error message to a user to explain how they can
/// enter a valid value.
/// </returns>
public abstract string GetErrorMessageForInvalidValue(string value, Type typeToParseTo);
}
}

View File

@ -0,0 +1,78 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The ComparableValueFilterRule provides support for derived classes
/// that evaluate against IComparable values.
/// </summary>
/// <typeparam name="T">
/// The generic parameter.
/// </typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public abstract class ComparableValueFilterRule<T> : FilterRule where T : IComparable
{
#region Properties
/// <summary>
/// Gets or sets a value indicating whether null objects passed to Evaluate will
/// evaluate to true or false.
/// </summary>
protected bool DefaultNullValueEvaluation
{
get;
set;
}
#endregion Properties
#region Public Methods
/// <summary>
/// Determines if item matches a derived classes criteria.
/// </summary>
/// <param name="item">
/// The item to match evaluate.
/// </param>
/// <returns>
/// Returns true if the item matches, false otherwise.
/// </returns>
public override bool Evaluate(object item)
{
if (item == null)
{
return this.DefaultNullValueEvaluation;
}
if (!this.IsValid)
{
return false;
}
T castItem;
if (!FilterUtilities.TryCastItem<T>(item, out castItem))
{
return false;
}
return this.Evaluate(castItem);
}
/// <summary>
/// Determines if item matches a derived classes criteria.
/// </summary>
/// <param name="data">
/// The item to match evaluate.
/// </param>
/// <returns>
/// Returns true if the item matches, false otherwise.
/// </returns>
protected abstract bool Evaluate(T data);
#endregion Public Methods
}
}

View File

@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The DoesNotEqualFilterRule class evaluates an IComparable item to
/// check if it is not equal to the rule's value.
/// </summary>
/// <typeparam name="T">
/// The generic parameter.
/// </typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class DoesNotEqualFilterRule<T> : EqualsFilterRule<T> where T : IComparable
{
/// <summary>
/// Initializes a new instance of the DoesNotEqualFilterRule class.
/// </summary>
public DoesNotEqualFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_DoesNotEqual;
this.DefaultNullValueEvaluation = true;
}
/// <summary>
/// Determines if item is not equal to Value.
/// </summary>
/// <param name="data">
/// The data to compare against.
/// </param>
/// <returns>
/// Returns true if data is not equal to Value, false otherwise.
/// </returns>
protected override bool Evaluate(T data)
{
return !base.Evaluate(data);
}
}
}

View File

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The EqualsFilterRule class evaluates an IComparable item to
/// check if it is equal to the rule's value.
/// </summary>
/// <typeparam name="T">
/// The generic parameter.
/// </typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class EqualsFilterRule<T> : SingleValueComparableValueFilterRule<T> where T : IComparable
{
/// <summary>
/// Initializes a new instance of the EqualsFilterRule class.
/// </summary>
public EqualsFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_Equals;
}
/// <summary>
/// Determines if item is equal to Value.
/// </summary>
/// <param name="data">
/// The data to compare against.
/// </param>
/// <returns>
/// Returns true if data is equal to Value.
/// </returns>
protected override bool Evaluate(T data)
{
Debug.Assert(this.IsValid, "isValid");
int result = CustomTypeComparer.Compare<T>(this.Value.GetCastValue(), data);
return result == 0;
}
}
}

View File

@ -0,0 +1,79 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The base class for all filtering rules.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public abstract class FilterRule : IEvaluate
{
/// <summary>
/// Gets a value indicating whether the FilterRule can be
/// evaluated in its current state.
/// </summary>
public virtual bool IsValid
{
get
{
return true;
}
}
/// <summary>
/// Gets a display friendly name for the FilterRule.
/// </summary>
public string DisplayName
{
get;
protected set;
}
/// <summary>
/// Initializes a new instance of the FilterRule class.
/// </summary>
protected FilterRule()
{
// HACK : Is there a way to statically enforce this? No... not ISerializable...
if (!this.GetType().IsSerializable)
{
throw new InvalidOperationException("FilterRules must be serializable.");
}
}
/// <summary>
/// Gets a value indicating whether the supplied item meets the
/// criteria specified by this rule.
/// </summary>
/// <param name="item">The item to evaluate.</param>
/// <returns>Returns true if the item meets the criteria. False otherwise.</returns>
public abstract bool Evaluate(object item);
#region EvaluationResultInvalidated
/// <summary>
/// Occurs when the values of this rule changes.
/// </summary>
[field: NonSerialized]
public event EventHandler EvaluationResultInvalidated;
/// <summary>
/// Fires <see cref="EvaluationResultInvalidated"/>.
/// </summary>
protected void NotifyEvaluationResultInvalidated()
{
var eh = this.EvaluationResultInvalidated;
if (eh != null)
{
eh(this, new EventArgs());
}
}
#endregion
}
}

View File

@ -0,0 +1,56 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The FilterRuleExtensions class provides extension methods
/// for FilterRule classes.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public static class FilterRuleExtensions
{
/// <summary>
/// Creates a deep copy of a FilterRule.
/// </summary>
/// <param name="rule">
/// The FilterRule to clone.
/// </param>
/// <returns>
/// Returns a deep copy of the passed in rule.
/// </returns>
public static FilterRule DeepCopy(this FilterRule rule)
{
if (rule == null)
{
throw new ArgumentNullException("rule");
}
Debug.Assert(rule.GetType().IsSerializable, "rule is serializable");
BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
MemoryStream ms = new MemoryStream();
FilterRule copy = null;
try
{
formatter.Serialize(ms, rule);
ms.Position = 0;
copy = (FilterRule)formatter.Deserialize(ms);
}
finally
{
ms.Close();
}
return copy;
}
}
}

View File

@ -0,0 +1,120 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IsBetweenFilterRule class evaluates an item to see if it is between
/// the StartValue and EndValue of the rule.
/// </summary>
/// <typeparam name="T">
/// The generic parameter.
/// </typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IsBetweenFilterRule<T> : ComparableValueFilterRule<T> where T : IComparable
{
#region Properties
/// <summary>
/// Gets a value indicating whether the FilterRule can be
/// evaluated in its current state.
/// </summary>
public override bool IsValid
{
get
{
return this.StartValue.IsValid && this.EndValue.IsValid;
}
}
/// <summary>
/// Gets the start value for the range.
/// </summary>
public ValidatingValue<T> StartValue
{
get;
protected set;
}
/// <summary>
/// Gets the end value for the range.
/// </summary>
public ValidatingValue<T> EndValue
{
get;
protected set;
}
#endregion Properties
#region Ctor
/// <summary>
/// Initializes a new instance of the IsBetweenFilterRule class.
/// </summary>
public IsBetweenFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_IsBetween;
this.StartValue = new ValidatingValue<T>();
this.StartValue.PropertyChanged += new PropertyChangedEventHandler(this.Value_PropertyChanged);
this.EndValue = new ValidatingValue<T>();
this.EndValue.PropertyChanged += new PropertyChangedEventHandler(this.Value_PropertyChanged);
}
#endregion Ctor
#region Public Methods
/// <summary>
/// Evaluates data and determines if it is between
/// StartValue and EndValue.
/// </summary>
/// <param name="data">
/// The data to evaluate.
/// </param>
/// <returns>
/// Returns true if data is between StartValue and EndValue,
/// false otherwise.
/// </returns>
protected override bool Evaluate(T data)
{
Debug.Assert(this.IsValid, "is valid");
int startValueComparedToData = CustomTypeComparer.Compare<T>(this.StartValue.GetCastValue(), data);
int endValueComparedToData = CustomTypeComparer.Compare<T>(this.EndValue.GetCastValue(), data);
bool isBetweenForward = startValueComparedToData < 0 && endValueComparedToData > 0;
bool isBetweenBackwards = endValueComparedToData < 0 && startValueComparedToData > 0;
return isBetweenForward || isBetweenBackwards;
}
#endregion Public Methods
#region Value Change Handlers
private void Value_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Value")
{
this.NotifyEvaluationResultInvalidated();
}
}
[OnDeserialized]
private void Initialize(StreamingContext context)
{
this.StartValue.PropertyChanged += new PropertyChangedEventHandler(this.Value_PropertyChanged);
this.EndValue.PropertyChanged += new PropertyChangedEventHandler(this.Value_PropertyChanged);
}
#endregion Value Change Handlers
}
}

View File

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IsEmptyFilterRule evaluates an item to determine whether it
/// is empty or not.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IsEmptyFilterRule : FilterRule
{
/// <summary>
/// Initializes a new instance of the IsEmptyFilterRule class.
/// </summary>
public IsEmptyFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_IsEmpty;
}
/// <summary>
/// Gets a values indicating whether the supplied item is empty.
/// </summary>
/// <param name="item">The item to evaluate.</param>
/// <returns>
/// Returns true if the item is null or if the item is a string
/// composed of whitespace. False otherwise.
/// </returns>
public override bool Evaluate(object item)
{
if (item == null)
{
return true;
}
Type type = item.GetType();
if (typeof(string) == type)
{
return ((string)item).Trim().Length == 0;
}
return false;
}
}
}

View File

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IsGreaterThanFilterRule class evaluates an IComparable item to
/// check if it is greater than its value.
/// </summary>
/// <typeparam name="T">
/// The generic parameter.
/// </typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IsGreaterThanFilterRule<T> : SingleValueComparableValueFilterRule<T> where T : IComparable
{
/// <summary>
/// Initializes a new instance of the IsGreaterThanFilterRule class.
/// </summary>
public IsGreaterThanFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_GreaterThanOrEqual;
}
/// <summary>
/// Determines if item is greater than Value.
/// </summary>
/// <param name="data">
/// The data to compare against.
/// </param>
/// <returns>
/// Returns true if data is greater than Value.
/// </returns>
protected override bool Evaluate(T data)
{
Debug.Assert(this.IsValid, "is valid");
int result = CustomTypeComparer.Compare<T>(this.Value.GetCastValue(), data);
return result <= 0;
}
}
}

View File

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IsLessThanFilterRule class evaluates an IComparable item to
/// check if it is less than the rule's value.
/// </summary>
/// <typeparam name="T">
/// The generic parameter.
/// </typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IsLessThanFilterRule<T> : SingleValueComparableValueFilterRule<T> where T : IComparable
{
/// <summary>
/// Initializes a new instance of the IsLessThanFilterRule class.
/// </summary>
public IsLessThanFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_LessThanOrEqual;
}
/// <summary>
/// Determines if item is less than Value.
/// </summary>
/// <param name="item">
/// The data to compare against.
/// </param>
/// <returns>
/// Returns true if data is less than Value.
/// </returns>
protected override bool Evaluate(T item)
{
Debug.Assert(this.IsValid, "is valid");
int result = CustomTypeComparer.Compare<T>(this.Value.GetCastValue(), item);
return result >= 0;
}
}
}

View File

@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IsNotEmptyFilterRule evaluates an item to determine whether it
/// is empty or not.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IsNotEmptyFilterRule : IsEmptyFilterRule
{
/// <summary>
/// Initializes a new instance of the IsNotEmptyFilterRule class.
/// </summary>
public IsNotEmptyFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_IsNotEmpty;
}
/// <summary>
/// Gets a values indicating whether the supplied item is not empty.
/// </summary>
/// <param name="item">The item to evaluate.</param>
/// <returns>
/// Returns false if the item is null or if the item is a string
/// composed of whitespace. True otherwise.
/// </returns>
public override bool Evaluate(object item)
{
return !base.Evaluate(item);
}
}
}

View File

@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IsNotEmptyValidationRule checks a value to see if a value is not empty.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class IsNotEmptyValidationRule : DataErrorInfoValidationRule
{
#region Properties
private static readonly DataErrorInfoValidationResult EmptyValueResult = new DataErrorInfoValidationResult(false, null, string.Empty);
#endregion Properties
#region Public Methods
/// <summary>
/// Determines if value is not empty.
/// </summary>
/// <param name="value">
/// The value to validate.
/// </param>
/// <param name="cultureInfo">
/// The culture info to use while validating.
/// </param>
/// <returns>
/// Returns true if the value is not empty, false otherwise.
/// </returns>
public override DataErrorInfoValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
if (value == null)
{
return EmptyValueResult;
}
Type t = value.GetType();
if (typeof(string) == t)
{
return IsStringNotEmpty((string)value) ? DataErrorInfoValidationResult.ValidResult : EmptyValueResult;
}
else
{
return DataErrorInfoValidationResult.ValidResult;
}
}
#endregion Public Methods
internal static bool IsStringNotEmpty(string value)
{
return !(string.IsNullOrEmpty(value) || value.Trim().Length == 0);
}
}
}

View File

@ -0,0 +1,130 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Represents a filter rule that searches for text within properties on an object.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class PropertiesTextContainsFilterRule : TextFilterRule
{
private static readonly string TextContainsCharactersRegexPattern = "{0}";
private static readonly string TextContainsWordsRegexPattern = WordBoundaryRegexPattern + TextContainsCharactersRegexPattern + WordBoundaryRegexPattern;
private Regex cachedRegex;
/// <summary>
/// Initializes a new instance of the <see cref="PropertiesTextContainsFilterRule"/> class.
/// </summary>
public PropertiesTextContainsFilterRule()
{
this.PropertyNames = new List<string>();
this.EvaluationResultInvalidated += new EventHandler(this.PropertiesTextContainsFilterRule_EvaluationResultInvalidated);
}
/// <summary>
/// Gets a collection of the names of properties to search in.
/// </summary>
public ICollection<string> PropertyNames
{
get;
private set;
}
/// <summary>
/// Evaluates whether the specified properties on <paramref name="item"/> contain the current value.
/// </summary>
/// <param name="item">The item to evaluate.</param>
/// <returns><c>true</c> if <paramref name="item"/> is not <c>null</c>, the current value is valid, and the specified properties on <paramref name="item"/> contain the current value; otherwise, <c>false</c>.</returns>
public override bool Evaluate(object item)
{
if (item == null)
{
return false;
}
if (!this.IsValid)
{
return false;
}
foreach (string propertyName in this.PropertyNames)
{
object propertyValue;
if (!FilterRuleCustomizationFactory.FactoryInstance.PropertyValueGetter.TryGetPropertyValue(propertyName, item, out propertyValue))
{
continue;
}
if (propertyValue != null)
{
string data = propertyValue.ToString();
if (this.Evaluate(data))
{
return true;
}
}
}
return false;
}
/// <summary>
/// Evaluates whether the specified data contains the current value.
/// </summary>
/// <param name="data">The data to evaluate.</param>
/// <returns><c>true</c> if <paramref name="data"/> contains the current value; otherwise, <c>false</c>.</returns>
protected override bool Evaluate(string data)
{
if (this.cachedRegex == null)
{
this.UpdateCachedRegex();
}
return this.cachedRegex.IsMatch(data);
}
/// <summary>
/// Called when the evaluation result is invalidated.
/// Updates the cached Regex pattern.
/// </summary>
protected virtual void OnEvaluationResultInvalidated()
{
this.UpdateCachedRegex();
}
/// <summary>
/// Updates the cached Regex with the current value.
/// If the current value is invalid, the Regex will not be updated because it will not be evaluated.
/// </summary>
private void UpdateCachedRegex()
{
if (this.IsValid)
{
var parsedPattern = this.GetRegexPattern(TextContainsCharactersRegexPattern, TextContainsWordsRegexPattern);
this.cachedRegex = new Regex(parsedPattern, this.GetRegexOptions());
}
}
private void PropertiesTextContainsFilterRule_EvaluationResultInvalidated(object sender, EventArgs e)
{
this.OnEvaluationResultInvalidated();
}
[OnDeserialized]
private void Initialize(StreamingContext context)
{
this.EvaluationResultInvalidated += new EventHandler(this.PropertiesTextContainsFilterRule_EvaluationResultInvalidated);
}
}
}

View File

@ -0,0 +1,149 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The PropertyValueSelectorFilterRule class supports filtering against a
/// property of an object. Based on the type of the property a collection of
/// filter rules are available to be used.
/// </summary>
/// <typeparam name="T">
/// The generic parameter.
/// </typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class PropertyValueSelectorFilterRule<T> : SelectorFilterRule where T : IComparable
{
#region Properties
/// <summary>
/// Gets the name of the property on the item to evaluate which holds
/// the real value which should be evaluated.
/// </summary>
public string PropertyName
{
get;
protected set;
}
#endregion Properties
#region Ctor
/// <summary>
/// Creates a new PropertyValueSelectorFilterRule instance.
/// </summary>
/// <param name="propertyName">
/// Gets the name of the property on the item to evaluate which holds
/// the real value which should be evaluated.
/// </param>
/// <param name="propertyDisplayName">
/// The display friendly representation of the property name.
/// </param>
public PropertyValueSelectorFilterRule(string propertyName, string propertyDisplayName)
: this(propertyName, propertyDisplayName, FilterRuleCustomizationFactory.FactoryInstance.CreateDefaultFilterRulesForPropertyValueSelectorFilterRule<T>())
{
// Empty
}
/// <summary>
/// Creates a new PropertyValueSelectorFilterRule instance.
/// </summary>
/// <param name="propertyName">
/// The propertyName on the item to evaluate which holds the real
/// value which should be evaluated.
/// </param>
/// <param name="propertyDisplayName">
/// The display friendly representation of the propertyName.
/// </param>
/// <param name="rules">
/// The collection of available rules.
/// </param>
public PropertyValueSelectorFilterRule(string propertyName, string propertyDisplayName, IEnumerable<FilterRule> rules)
{
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentNullException("propertyName");
}
if (string.IsNullOrEmpty(propertyDisplayName))
{
throw new ArgumentNullException("propertyDisplayName");
}
if (rules == null)
{
throw new ArgumentNullException("rules");
}
this.PropertyName = propertyName;
this.DisplayName = propertyDisplayName;
foreach (FilterRule rule in rules)
{
if (rule == null)
{
throw new ArgumentException("A value within rules is null", "rules");
}
this.AvailableRules.AvailableValues.Add(rule);
}
this.AvailableRules.DisplayNameConverter = new FilterRuleToDisplayNameConverter();
}
#endregion Ctor
#region Public Methods
/// <summary>
/// Evaluates whether the item is inclusive.
/// </summary>
/// <param name="item">
/// The item to evaluate.
/// </param>
/// <returns>
/// Returns true if the item matches the filtering criteria, false otherwise.
/// </returns>
public override bool Evaluate(object item)
{
if (!this.IsValid)
{
return false;
}
if (item == null)
{
return false;
}
T propertyValue;
if (!this.TryGetPropertyValue(item, out propertyValue))
{
return false;
}
return this.AvailableRules.SelectedValue.Evaluate(propertyValue);
}
#endregion Public Methods
#region Private Methods
private bool TryGetPropertyValue(object item, out T propertyValue)
{
propertyValue = default(T);
Debug.Assert(item != null, "item not null");
return FilterRuleCustomizationFactory.FactoryInstance.PropertyValueGetter.TryGetPropertyValue<T>(this.PropertyName, item, out propertyValue);
}
#endregion Private Methods
}
}

View File

@ -0,0 +1,118 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Runtime.Serialization;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The SelectorFilterRule represents a rule composed of other rules.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class SelectorFilterRule : FilterRule
{
#region Properties
/// <summary>
/// Gets a value indicating whether the rule can be evaluated.
/// </summary>
public override bool IsValid
{
get
{
return this.AvailableRules.IsValid && this.AvailableRules.SelectedValue.IsValid;
}
}
/// <summary>
/// Gets the collection of available rules.
/// </summary>
public ValidatingSelectorValue<FilterRule> AvailableRules
{
get;
protected set;
}
#endregion Properties
#region Ctor
/// <summary>
/// Creates a new SelectorFilterRule instance.
/// </summary>
public SelectorFilterRule()
{
this.AvailableRules = new ValidatingSelectorValue<FilterRule>();
this.AvailableRules.SelectedValueChanged += new EventHandler<PropertyChangedEventArgs<FilterRule>>(this.AvailableRules_SelectedValueChanged);
}
#endregion Ctor
#region Public Methods
/// <summary>
/// Evaluates whether the item is inclusive.
/// </summary>
/// <param name="item">
/// The item to evaluate.
/// </param>
/// <returns>
/// Returns true if the item matches the filtering criteria, false otherwise.
/// </returns>
public override bool Evaluate(object item)
{
if (!this.IsValid)
{
return false;
}
return this.AvailableRules.SelectedValue.Evaluate(item);
}
/// <summary>
/// Called when the SelectedValue within AvailableRules changes.
/// </summary>
/// <param name="oldValue">
/// The old FilterRule.
/// </param>
/// <param name="newValue">
/// The new FilterRule.
/// </param>
protected void OnSelectedValueChanged(FilterRule oldValue, FilterRule newValue)
{
FilterRuleCustomizationFactory.FactoryInstance.ClearValues(newValue);
FilterRuleCustomizationFactory.FactoryInstance.TransferValues(oldValue, newValue);
FilterRuleCustomizationFactory.FactoryInstance.ClearValues(oldValue);
newValue.EvaluationResultInvalidated += new EventHandler(this.SelectedValue_EvaluationResultInvalidated);
oldValue.EvaluationResultInvalidated -= new EventHandler(this.SelectedValue_EvaluationResultInvalidated);
this.NotifyEvaluationResultInvalidated();
}
private void SelectedValue_EvaluationResultInvalidated(object sender, EventArgs e)
{
this.NotifyEvaluationResultInvalidated();
}
#endregion Public Methods
#region Private Methods
[OnDeserialized]
private void Initialize(StreamingContext context)
{
this.AvailableRules.SelectedValueChanged += new EventHandler<PropertyChangedEventArgs<FilterRule>>(this.AvailableRules_SelectedValueChanged);
this.AvailableRules.SelectedValue.EvaluationResultInvalidated += new EventHandler(this.SelectedValue_EvaluationResultInvalidated);
}
private void AvailableRules_SelectedValueChanged(object sender, PropertyChangedEventArgs<FilterRule> e)
{
this.OnSelectedValueChanged(e.OldValue, e.NewValue);
}
#endregion Private Methods
}
}

View File

@ -0,0 +1,71 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The SingleValueComparableValueFilterRule provides support for derived classes
/// that take a single input and evaluate against IComparable values.
/// </summary>
/// <typeparam name="T">The generic parameter.</typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public abstract class SingleValueComparableValueFilterRule<T> : ComparableValueFilterRule<T> where T : IComparable
{
#region Properties
/// <summary>
/// Gets a value that holds user input.
/// </summary>
public ValidatingValue<T> Value
{
get;
protected set;
}
/// <summary>
/// Gets a value indicating whether the FilterRule can be
/// evaluated in its current state.
/// </summary>
public override bool IsValid
{
get
{
return this.Value.IsValid;
}
}
#endregion Properties
#region Ctor
/// <summary>
/// Initializes a new instance of the SingleValueComparableValueFilterRule class.
/// </summary>
protected SingleValueComparableValueFilterRule()
{
this.Value = new ValidatingValue<T>();
this.Value.PropertyChanged += new PropertyChangedEventHandler(this.Value_PropertyChanged);
}
#endregion Ctor
private void Value_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Value")
{
this.NotifyEvaluationResultInvalidated();
}
}
[OnDeserialized]
private void Initialize(StreamingContext context)
{
this.Value.PropertyChanged += new PropertyChangedEventHandler(this.Value_PropertyChanged);
}
}
}

View File

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The TextContainsFilterRule class evaluates a string item to
/// check if it is contains the rule's value within it.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class TextContainsFilterRule : TextFilterRule
{
private static readonly string TextContainsCharactersRegexPattern = "{0}";
private static readonly string TextContainsWordsRegexPattern = WordBoundaryRegexPattern + TextContainsCharactersRegexPattern + WordBoundaryRegexPattern;
/// <summary>
/// Initializes a new instance of the TextContainsFilterRule class.
/// </summary>
public TextContainsFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_Contains;
}
/// <summary>
/// Determines if Value is contained within data.
/// </summary>
/// <param name="data">
/// The data to compare with.
/// </param>
/// <returns>
/// Returns true if data contains Value, false otherwise.
/// </returns>
protected override bool Evaluate(string data)
{
Debug.Assert(this.IsValid, "is valid");
// True "text contains": \\
return this.ExactMatchEvaluate(data, TextContainsCharactersRegexPattern, TextContainsWordsRegexPattern);
}
}
}

View File

@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The TextDoesNotContainFilterRule class evaluates a string item to
/// check if it is does not contain the rule's value within it.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class TextDoesNotContainFilterRule : TextContainsFilterRule
{
/// <summary>
/// Initializes a new instance of the TextDoesNotContainFilterRule class.
/// </summary>
public TextDoesNotContainFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_DoesNotContain;
this.DefaultNullValueEvaluation = true;
}
/// <summary>
/// Determines if Value is not contained within data.
/// </summary>
/// <param name="data">
/// The data to compare with.
/// </param>
/// <returns>
/// Returns true if data does not contain Value, false otherwise.
/// </returns>
protected override bool Evaluate(string data)
{
return !base.Evaluate(data);
}
}
}

View File

@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The TextDoesNotEqualFilterRule class evaluates a string item to
/// check if it is not equal to the rule's value.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class TextDoesNotEqualFilterRule : TextEqualsFilterRule
{
/// <summary>
/// Initializes a new instance of the TextDoesNotEqualFilterRule class.
/// </summary>
public TextDoesNotEqualFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_DoesNotEqual;
this.DefaultNullValueEvaluation = true;
}
/// <summary>
/// Determines if data is not equal to Value.
/// </summary>
/// <param name="data">
/// The value to compare against.
/// </param>
/// <returns>
/// Returns true is data does not equal Value, false otherwise.
/// </returns>
protected override bool Evaluate(string data)
{
return !base.Evaluate(data);
}
}
}

View File

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The TextEndsWithFilterRule class evaluates a string item to
/// check if it ends with the rule's value.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class TextEndsWithFilterRule : TextFilterRule
{
private static readonly string TextEndsWithCharactersRegexPattern = "{0}$";
private static readonly string TextEndsWithWordsRegexPattern = WordBoundaryRegexPattern + TextEndsWithCharactersRegexPattern;
/// <summary>
/// Initializes a new instance of the TextEndsWithFilterRule class.
/// </summary>
public TextEndsWithFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_TextEndsWith;
}
/// <summary>
/// Determines if data ends with Value.
/// </summary>
/// <param name="data">
/// The value to compare with.
/// </param>
/// <returns>
/// Returns true is data ends with Value, false otherwise.
/// </returns>
protected override bool Evaluate(string data)
{
Debug.Assert(this.IsValid, "is valid");
return this.ExactMatchEvaluate(data, TextEndsWithCharactersRegexPattern, TextEndsWithWordsRegexPattern);
}
}
}

View File

@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The TextEqualsFilterRule class evaluates a string item to
/// check if it is equal to the rule's value.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class TextEqualsFilterRule : TextFilterRule
{
private static readonly string TextEqualsCharactersRegexPattern = "^{0}$";
/// <summary>
/// Initializes a new instance of the TextEqualsFilterRule class.
/// </summary>
public TextEqualsFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_Equals;
}
/// <summary>
/// Determines if data is equal to Value.
/// </summary>
/// <param name="data">
/// The value to compare against.
/// </param>
/// <returns>
/// Returns true is data equals Value, false otherwise.
/// </returns>
protected override bool Evaluate(string data)
{
Debug.Assert(this.IsValid, "is valid");
return this.ExactMatchEvaluate(data, TextEqualsCharactersRegexPattern, TextEqualsCharactersRegexPattern);
}
}
}

View File

@ -0,0 +1,169 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Text.RegularExpressions;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The TextFilterRule class supports derived rules by offering services for
/// evaluating string operations.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public abstract class TextFilterRule : SingleValueComparableValueFilterRule<string>
{
/// <summary>
/// Gets a regex pattern that describes a word boundary that can include symbols.
/// </summary>
protected static readonly string WordBoundaryRegexPattern = @"(^|$|\W|\b)";
private bool ignoreCase;
private bool cultureInvariant;
/// <summary>
/// Gets or sets whether to ignore case when evaluating.
/// </summary>
public bool IgnoreCase
{
get
{
return this.ignoreCase;
}
set
{
this.ignoreCase = value;
this.NotifyEvaluationResultInvalidated();
}
}
/// <summary>
/// Gets or sets whether culture differences in language are ignored when evaluating.
/// </summary>
public bool CultureInvariant
{
get
{
return this.cultureInvariant;
}
set
{
this.cultureInvariant = value;
this.NotifyEvaluationResultInvalidated();
}
}
/// <summary>
/// Initializes a new instance of the TextFilterRule class.
/// </summary>
protected TextFilterRule()
{
this.IgnoreCase = true;
this.CultureInvariant = false;
}
/// <summary>
/// Gets the current value and determines whether it should be evaluated as an exact match.
/// </summary>
/// <param name="evaluateAsExactMatch">Whether the current value should be evaluated as an exact match.</param>
/// <returns>The current value.</returns>
protected internal string GetParsedValue(out bool evaluateAsExactMatch)
{
var parsedValue = this.Value.GetCastValue();
// Consider it an exact-match value if it starts with a quote; trailing quotes and other requirements can be added later if need be \\
evaluateAsExactMatch = parsedValue.StartsWith("\"", StringComparison.Ordinal);
// If it's an exact-match value, remove quotes and use the exact-match pattern \\
if (evaluateAsExactMatch)
{
parsedValue = parsedValue.Replace("\"", string.Empty);
}
return parsedValue;
}
/// <summary>
/// Gets a regular expression pattern based on the current value and the specified patterns.
/// If the current value is an exact-match string, <paramref name="exactMatchPattern"/> will be used; otherwise, <paramref name="pattern"/> will be used.
/// </summary>
/// <param name="pattern">The pattern to use if the current value is not an exact-match string. The pattern must contain a <c>{0}</c> token.</param>
/// <param name="exactMatchPattern">The pattern to use if the current value is an exact-match string. The pattern must contain a <c>{0}</c> token.</param>
/// <returns>A regular expression pattern based on the current value and the specified patterns.</returns>
/// <exception cref="ArgumentNullException">The specified value is a null reference.</exception>
protected internal string GetRegexPattern(string pattern, string exactMatchPattern)
{
if (pattern == null)
{
throw new ArgumentNullException("pattern");
}
if (exactMatchPattern == null)
{
throw new ArgumentNullException("exactMatchPattern");
}
Debug.Assert(this.IsValid, "is valid");
bool evaluateAsExactMatch;
string value = this.GetParsedValue(out evaluateAsExactMatch);
if (evaluateAsExactMatch)
{
pattern = exactMatchPattern;
}
value = Regex.Escape(value);
// Format the pattern using the specified data \\
return string.Format(CultureInfo.InvariantCulture, pattern, value);
}
/// <summary>
/// Gets a <see cref="RegexOptions"/> object that matches the values of <see cref="IgnoreCase"/> and <see cref="CultureInvariant"/>.
/// </summary>
/// <returns>A <see cref="RegexOptions"/> object that matches the values of <see cref="IgnoreCase"/> and <see cref="CultureInvariant"/>.</returns>
protected internal RegexOptions GetRegexOptions()
{
RegexOptions options = RegexOptions.None;
if (this.IgnoreCase)
{
options |= RegexOptions.IgnoreCase;
}
if (this.CultureInvariant)
{
options |= RegexOptions.CultureInvariant;
}
return options;
}
/// <summary>
/// Gets a value indicating whether the specified data matches one of the specified patterns.
/// If the current value is an exact-match string, <paramref name="exactMatchPattern"/> will be used; otherwise, <paramref name="pattern"/> will be used.
/// </summary>
/// <param name="data">The data to evaluate.</param>
/// <param name="pattern">The pattern to use if the current value is not an exact-match string. The pattern must contain a <c>{0}</c> token.</param>
/// <param name="exactMatchPattern">The pattern to use if the current value is an exact-match string. The pattern must contain a <c>{0}</c> token.</param>
/// <returns><c>true</c> if the specified data matches one of the specified patterns; otherwise, <c>false</c>.</returns>
protected internal bool ExactMatchEvaluate(string data, string pattern, string exactMatchPattern)
{
Debug.Assert(this.IsValid, "is valid");
var parsedPattern = this.GetRegexPattern(pattern, exactMatchPattern);
var options = this.GetRegexOptions();
return Regex.IsMatch(data, parsedPattern, options);
}
}
}

View File

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The TextStartsWithFilterRule class evaluates a string item to
/// check if it starts with the rule's value.
/// </summary>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public class TextStartsWithFilterRule : TextFilterRule
{
private static readonly string TextStartsWithCharactersRegexPattern = "^{0}";
private static readonly string TextStartsWithWordsRegexPattern = TextStartsWithCharactersRegexPattern + WordBoundaryRegexPattern;
/// <summary>
/// Initializes a new instance of the TextStartsWithFilterRule class.
/// </summary>
public TextStartsWithFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_TextStartsWith;
}
/// <summary>
/// Determines if data starts with Value.
/// </summary>
/// <param name="data">
/// The value to compare with.
/// </param>
/// <returns>
/// Returns true is data starts with Value, false otherwise.
/// </returns>
protected override bool Evaluate(string data)
{
Debug.Assert(this.IsValid, "is valid");
return this.ExactMatchEvaluate(data, TextStartsWithCharactersRegexPattern, TextStartsWithWordsRegexPattern);
}
}
}

View File

@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The FilterStatus enum is used to classify the current status a <see cref="FilterEvaluator" /> is in.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public enum FilterStatus
{
/// <summary>
/// A FilterStatus of NotApplied indicates that the filter is currently
/// not applied.
/// </summary>
NotApplied = 0,
/// <summary>
/// A FilterStatus of InProgress indicates that the filter is being
/// applied but is not done.
/// </summary>
InProgress = 1,
/// <summary>
/// A FilterStatus of Applied indicates that the filter has been
/// applied.
/// </summary>
Applied = 2
}
}

View File

@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Provides common utilities for filtering.
/// </summary>
internal static class FilterUtilities
{
internal static bool TryCastItem<T>(object item, out T castItem)
{
castItem = default(T);
bool isItemUncastable = item == null && typeof(T).IsValueType;
if (isItemUncastable)
{
return false;
}
bool shouldCastToString = item != null && typeof(string) == typeof(T);
if (shouldCastToString)
{
// NOTE: string => T doesn't compile. We confuse the type system
// and use string => object => T to make this work.
object stringPropertyValue = item.ToString();
castItem = (T)stringPropertyValue;
return true;
}
try
{
castItem = (T)item;
return true;
}
catch (InvalidCastException e)
{
Debug.Print(e.ToString());
}
return false;
}
}
}

View File

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IEvaluate interface provides the most basic
/// support for the evaluation of an item against
/// criteria defined in a derived class.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public interface IEvaluate
{
/// <summary>
/// Gets a values indicating whether the supplied item has meet the
/// criteria rule specificed by the rule.
/// </summary>
/// <param name="item">
/// The item to evaluate.
/// </param>
/// <returns>
/// Returns true if the item meets the criteria. False otherwise.
/// </returns>
bool Evaluate(object item);
}
}

View File

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// The IFilterExpressionProvider interface defines the contract between
/// providers of FilterExpressions and consumers thereof.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public interface IFilterExpressionProvider
{
/// <summary>
/// Gets a FilterExpression representing the current
/// relational organization of FilterRules for this provider.
/// </summary>
FilterExpressionNode FilterExpression
{
get;
}
/// <summary>
/// Gets a value indicating whether this provider currently has a non-empty filter expression.
/// </summary>
bool HasFilterExpression
{
get;
}
/// <summary>
/// Raised when the FilterExpression of this provider
/// has changed.
/// </summary>
event EventHandler FilterExpressionChanged;
}
}

Some files were not shown because too many files have changed in this diff Show More