Add GraphicalHost
assembly to enable Out-GridView
, Show-Command
, and Get-Help -ShowWindow
(#10899)
This commit is contained in:
parent
5a76137d14
commit
ca68d9dbc5
@ -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>
|
||||
|
@ -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"
|
||||
)
|
||||
}
|
||||
|
71
src/Microsoft.Management.UI.Internal/CommonHelper.cs
Normal file
71
src/Microsoft.Management.UI.Internal/CommonHelper.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
283
src/Microsoft.Management.UI.Internal/HelpWindow/HelpViewModel.cs
Normal file
283
src/Microsoft.Management.UI.Internal/HelpWindow/HelpViewModel.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
247
src/Microsoft.Management.UI.Internal/HelpWindow/HelpWindowSettings.Designer.cs
generated
Normal file
247
src/Microsoft.Management.UI.Internal/HelpWindow/HelpWindowSettings.Designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
@ -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>
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user