mirror of https://github.com/dahall/Vanara.git
Exposed ReadOnlyPropertyStore and PropertyStore as public non-abstract classes with constructors to get properties directly for a file system item. Adjusted properties and methods from ShellItemPropertyStore to lower-level classes.
parent
eff69a6fe8
commit
fea9ff85c4
|
@ -29,11 +29,34 @@ public class PropertyDescription : IDisposable
|
||||||
key = pkey ?? iDesc.GetPropertyKey();
|
key = pkey ?? iDesc.GetPropertyKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PropertyDescription"/> class from a specified property key.</summary>
|
||||||
|
/// <param name="propkey">The property key.</param>
|
||||||
|
public PropertyDescription(PROPERTYKEY propkey)
|
||||||
|
{
|
||||||
|
PSGetPropertyDescription(propkey, typeof(IPropertyDescription).GUID, out var ppv).ThrowIfFailed();
|
||||||
|
iDesc = (IPropertyDescription)ppv;
|
||||||
|
key = propkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PropertyDescription"/> class from a property name.</summary>
|
||||||
|
/// <param name="name">A string that identifies the property.</param>
|
||||||
|
public PropertyDescription(string name)
|
||||||
|
{
|
||||||
|
PSGetPropertyDescriptionByName(name, typeof(IPropertyDescription).GUID, out var ppv).ThrowIfFailed();
|
||||||
|
iDesc = (IPropertyDescription)ppv;
|
||||||
|
key = iDesc.GetPropertyKey();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Creates a <see cref="PropertyDescription"/> instance from a specified property key.</summary>
|
/// <summary>Creates a <see cref="PropertyDescription"/> instance from a specified property key.</summary>
|
||||||
/// <param name="propkey">The property key.</param>
|
/// <param name="propkey">The property key.</param>
|
||||||
/// <returns>An associated instance of <see cref="PropertyDescription"/> or <see langword="null"/> if the PROPERTYKEY does not exist in the schema subsystem cache.</returns>
|
/// <returns>An associated instance of <see cref="PropertyDescription"/> or <see langword="null"/> if the PROPERTYKEY does not exist in the schema subsystem cache.</returns>
|
||||||
public static PropertyDescription? Create(PROPERTYKEY propkey) => PSGetPropertyDescription(propkey, typeof(IPropertyDescription).GUID, out var ppv).Succeeded ? new PropertyDescription((IPropertyDescription)ppv, propkey) : null;
|
public static PropertyDescription? Create(PROPERTYKEY propkey) => PSGetPropertyDescription(propkey, typeof(IPropertyDescription).GUID, out var ppv).Succeeded ? new PropertyDescription((IPropertyDescription)ppv, propkey) : null;
|
||||||
|
|
||||||
|
/// <summary>Creates a <see cref="PropertyDescription"/> instance from a property key name.</summary>
|
||||||
|
/// <param name="name">A string that identifies the property.</param>
|
||||||
|
/// <returns>An associated instance of <see cref="PropertyDescription"/> or <see langword="null"/> if the PROPERTYKEY does not exist in the schema subsystem cache.</returns>
|
||||||
|
public static PropertyDescription? Create(string name) => PSGetPropertyDescriptionByName(name, typeof(IPropertyDescription).GUID, out var ppv).Succeeded ? new PropertyDescription((IPropertyDescription)ppv) : null;
|
||||||
|
|
||||||
/// <summary>Tries to create a <see cref="PropertyDescription"/> instance from a specified property key.</summary>
|
/// <summary>Tries to create a <see cref="PropertyDescription"/> instance from a specified property key.</summary>
|
||||||
/// <param name="propkey">The property key.</param>
|
/// <param name="propkey">The property key.</param>
|
||||||
/// <param name="desc">
|
/// <param name="desc">
|
||||||
|
@ -152,7 +175,7 @@ public class PropertyDescription : IDisposable
|
||||||
/// <returns>An IconLocation for the image associated with the property value.</returns>
|
/// <returns>An IconLocation for the image associated with the property value.</returns>
|
||||||
public IconLocation GetImageLocationForValue(object obj)
|
public IconLocation GetImageLocationForValue(object obj)
|
||||||
{
|
{
|
||||||
if (iDesc2 == null) iDesc2 = iDesc as IPropertyDescription2;
|
iDesc2 ??= iDesc as IPropertyDescription2;
|
||||||
return iDesc2 != null && IconLocation.TryParse(iDesc2.GetImageReferenceForValue(new PROPVARIANT(obj), out var img).Succeeded ? img : null, out var loc) ? loc : new IconLocation();
|
return iDesc2 != null && IconLocation.TryParse(iDesc2.GetImageReferenceForValue(new PROPVARIANT(obj), out var img).Succeeded ? img : null, out var loc) ? loc : new IconLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,23 @@ namespace Vanara.Windows.Shell;
|
||||||
/// <summary>Encapsulates the IPropertyStore object.</summary>
|
/// <summary>Encapsulates the IPropertyStore object.</summary>
|
||||||
/// <seealso cref="IDictionary{PROPERTYKEY, Object}"/>
|
/// <seealso cref="IDictionary{PROPERTYKEY, Object}"/>
|
||||||
/// <seealso cref="IDisposable"/>
|
/// <seealso cref="IDisposable"/>
|
||||||
public abstract class PropertyStore : ReadOnlyPropertyStore, IDictionary<PROPERTYKEY, object?>, IDisposable, INotifyPropertyChanged
|
public class PropertyStore : ReadOnlyPropertyStore, IDictionary<PROPERTYKEY, object?>, IDisposable, INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
private bool noICapabilities = false;
|
private bool noICapabilities = false;
|
||||||
private IPropertyStoreCapabilities? pCapabilities;
|
private IPropertyStoreCapabilities? pCapabilities;
|
||||||
|
|
||||||
/// <summary>Initializes a new instance of the <see cref="PropertyStore"/> class.</summary>
|
/// <summary>Initializes a new instance of the <see cref="PropertyStore"/> class.</summary>
|
||||||
protected PropertyStore() { }
|
protected PropertyStore() => flags |= GETPROPERTYSTOREFLAGS.GPS_READWRITE;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PropertyStore"/> class from a file system path.</summary>
|
||||||
|
/// <param name="path">A string that specifies the item path.</param>
|
||||||
|
/// <param name="propChangedHandler">The optional property changed handler.</param>
|
||||||
|
public PropertyStore(string path, PropertyChangedEventHandler? propChangedHandler = null) : base(path)
|
||||||
|
{
|
||||||
|
flags |= GETPROPERTYSTOREFLAGS.GPS_READWRITE;
|
||||||
|
if (propChangedHandler != null)
|
||||||
|
PropertyChanged += propChangedHandler;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Occurs when a property value changes.</summary>
|
/// <summary>Occurs when a property value changes.</summary>
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
@ -25,15 +35,14 @@ public abstract class PropertyStore : ReadOnlyPropertyStore, IDictionary<PROPERT
|
||||||
/// <value><c>true</c> if this instance is dirty; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this instance is dirty; otherwise, <c>false</c>.</value>
|
||||||
public bool IsDirty { get; protected set; }
|
public bool IsDirty { get; protected set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override bool IsReadOnly => false;
|
|
||||||
|
|
||||||
/// <summary>Gets an <see cref="ICollection{T}"/> containing the keys of the <see cref="IDictionary{PROPERTYKEY, Object}"/>.</summary>
|
/// <summary>Gets an <see cref="ICollection{T}"/> containing the keys of the <see cref="IDictionary{PROPERTYKEY, Object}"/>.</summary>
|
||||||
public new ICollection<PROPERTYKEY> Keys => base.Keys.ToList();
|
public new ICollection<PROPERTYKEY> Keys => base.Keys.ToList();
|
||||||
|
|
||||||
/// <summary>Gets an <see cref="ICollection{T}"/> containing the values in the <see cref="IDictionary{PROPERTYKEY, Object}"/>.</summary>
|
/// <summary>Gets an <see cref="ICollection{T}"/> containing the values in the <see cref="IDictionary{PROPERTYKEY, Object}"/>.</summary>
|
||||||
public new ICollection<object?> Values => base.Values.ToList();
|
public new ICollection<object?> Values => base.Values.ToList();
|
||||||
|
|
||||||
|
bool ICollection<KeyValuePair<PROPERTYKEY, object?>>.IsReadOnly => ReadOnly;
|
||||||
|
|
||||||
/// <summary>Gets or sets the value of the property with the specified known key.</summary>
|
/// <summary>Gets or sets the value of the property with the specified known key.</summary>
|
||||||
/// <value>The value.</value>
|
/// <value>The value.</value>
|
||||||
/// <param name="knownKey">The known key of the property (e.g. "System.Title"}.</param>
|
/// <param name="knownKey">The known key of the property (e.g. "System.Title"}.</param>
|
||||||
|
@ -61,7 +70,7 @@ public abstract class PropertyStore : ReadOnlyPropertyStore, IDictionary<PROPERT
|
||||||
{
|
{
|
||||||
if (ps is null)
|
if (ps is null)
|
||||||
throw new InvalidOperationException("Property store does not exist.");
|
throw new InvalidOperationException("Property store does not exist.");
|
||||||
if (IsReadOnly)
|
if (ReadOnly)
|
||||||
throw new InvalidOperationException("Property store is read-only.");
|
throw new InvalidOperationException("Property store is read-only.");
|
||||||
ps.SetValue(key, value, false);
|
ps.SetValue(key, value, false);
|
||||||
OnPropertyChanged(key.ToString());
|
OnPropertyChanged(key.ToString());
|
||||||
|
@ -94,7 +103,7 @@ public abstract class PropertyStore : ReadOnlyPropertyStore, IDictionary<PROPERT
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public bool IsPropertyWritable(in PROPERTYKEY key)
|
public bool IsPropertyWritable(in PROPERTYKEY key)
|
||||||
{
|
{
|
||||||
if (IsReadOnly) return false;
|
if (ReadOnly) return false;
|
||||||
|
|
||||||
// Check for an IPropertyStoreCapabilities if possible
|
// Check for an IPropertyStoreCapabilities if possible
|
||||||
if (pCapabilities is null && !noICapabilities)
|
if (pCapabilities is null && !noICapabilities)
|
||||||
|
|
|
@ -1,26 +1,53 @@
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Vanara.PInvoke;
|
using Vanara.PInvoke;
|
||||||
using static Vanara.PInvoke.Ole32;
|
using static Vanara.PInvoke.Ole32;
|
||||||
using static Vanara.PInvoke.PropSys;
|
using static Vanara.PInvoke.PropSys;
|
||||||
|
using static Vanara.PInvoke.Shell32;
|
||||||
|
|
||||||
namespace Vanara.Windows.Shell;
|
namespace Vanara.Windows.Shell;
|
||||||
|
|
||||||
/// <summary>Encapsulates the IPropertyStore object.</summary>
|
/// <summary>Encapsulates the IPropertyStore object.</summary>
|
||||||
/// <seealso cref="IDictionary{PROPERTYKEY, Object}"/>
|
/// <seealso cref="IDictionary{PROPERTYKEY, Object}"/>
|
||||||
/// <seealso cref="IDisposable"/>
|
/// <seealso cref="IDisposable"/>
|
||||||
public abstract class ReadOnlyPropertyStore : IReadOnlyDictionary<PROPERTYKEY, object?>, IDisposable
|
public class ReadOnlyPropertyStore : IReadOnlyDictionary<PROPERTYKEY, object?>, IDisposable
|
||||||
{
|
{
|
||||||
|
/// <summary>The flags.</summary>
|
||||||
|
protected GETPROPERTYSTOREFLAGS flags = GETPROPERTYSTOREFLAGS.GPS_BESTEFFORT;
|
||||||
|
|
||||||
|
/// <summary>An optional IBindCtx object, which provides access to a bind context.</summary>
|
||||||
|
protected System.Runtime.InteropServices.ComTypes.IBindCtx? iBindCtx = null;
|
||||||
|
|
||||||
/// <summary>The IPropertyStore instance.</summary>
|
/// <summary>The IPropertyStore instance.</summary>
|
||||||
protected IPropertyStore? iPropertyStore;
|
protected IPropertyStore? iPropertyStore;
|
||||||
|
|
||||||
|
/// <summary>If specified, the path to the file system item.</summary>
|
||||||
|
protected string? itemPath = null;
|
||||||
|
|
||||||
private PropertyDescriptionDictionary? descriptions;
|
private PropertyDescriptionDictionary? descriptions;
|
||||||
|
|
||||||
/// <summary>Initializes a new instance of the <see cref="PropertyStore"/> class.</summary>
|
/// <summary>Initializes a new instance of the <see cref="ReadOnlyPropertyStore"/> class.</summary>
|
||||||
protected ReadOnlyPropertyStore() { }
|
protected ReadOnlyPropertyStore() { }
|
||||||
|
|
||||||
|
/// <summary>Returns a property store for an item, given a path or parsing name.</summary>
|
||||||
|
/// <param name="path">A string that specifies the item path.</param>
|
||||||
|
/// <param name="flags">One or more values from the GETPROPERTYSTOREFLAGS constants.</param>
|
||||||
|
/// <param name="pbc">An optional IBindCtx object, which provides access to a bind context.</param>
|
||||||
|
protected ReadOnlyPropertyStore(string path, GETPROPERTYSTOREFLAGS? flags = null, System.Runtime.InteropServices.ComTypes.IBindCtx? pbc = null)
|
||||||
|
{
|
||||||
|
itemPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(path));
|
||||||
|
if (flags.HasValue) this.flags = flags.Value;
|
||||||
|
iBindCtx = pbc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="ReadOnlyPropertyStore"/> class from a file system path.</summary>
|
||||||
|
/// <param name="path">A string that specifies the item path.</param>
|
||||||
|
public ReadOnlyPropertyStore(string path) : this(path, GETPROPERTYSTOREFLAGS.GPS_DEFAULT) { }
|
||||||
|
|
||||||
/// <summary>Gets the number of properties in the current property store.</summary>
|
/// <summary>Gets the number of properties in the current property store.</summary>
|
||||||
public int Count => Run(ps => (int)(ps?.GetCount() ?? 0));
|
public int Count => Run(ps => (int)(ps?.GetCount() ?? 0));
|
||||||
|
|
||||||
|
@ -28,8 +55,77 @@ public abstract class ReadOnlyPropertyStore : IReadOnlyDictionary<PROPERTYKEY, o
|
||||||
/// <value>The property descriptions.</value>
|
/// <value>The property descriptions.</value>
|
||||||
public virtual IReadOnlyDictionary<PROPERTYKEY, PropertyDescription> Descriptions => descriptions ??= new PropertyDescriptionDictionary(this);
|
public virtual IReadOnlyDictionary<PROPERTYKEY, PropertyDescription> Descriptions => descriptions ??= new PropertyDescriptionDictionary(this);
|
||||||
|
|
||||||
/// <summary>Gets a value indicating whether the <see cref="ICollection{T}"/> is read-only.</summary>
|
/// <summary>Gets or sets a value indicating whether to include slow properties.</summary>
|
||||||
public virtual bool IsReadOnly => true;
|
/// <value><c>true</c> if including slow properties; otherwise, <c>false</c>.</value>
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool IncludeSlow
|
||||||
|
{
|
||||||
|
get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_OPENSLOWITEM);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (IncludeSlow == value) return;
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_OPENSLOWITEM, value);
|
||||||
|
if (value)
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Gets or sets a value indicating whether to include only properties directly from the property handler.</summary>
|
||||||
|
/// <value><c>true</c> if no inherited properties; otherwise, <c>false</c>.</value>
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool NoInheritedProperties
|
||||||
|
{
|
||||||
|
get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (NoInheritedProperties == value) return;
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY, value);
|
||||||
|
if (value)
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_BESTEFFORT | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Gets or sets a value indicating whether properties can be read and written.</summary>
|
||||||
|
/// <value><c>true</c> if properties are read/write; otherwise, <c>false</c>.</value>
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool ReadOnly
|
||||||
|
{
|
||||||
|
get => !flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_READWRITE);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (ReadOnly == value) return;
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_READWRITE, !value);
|
||||||
|
if (!value)
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_DELAYCREATION | GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_BESTEFFORT | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false);
|
||||||
|
else
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this <see cref="ShellItemPropertyStore"/> provides a writable store, with no initial
|
||||||
|
/// properties, that exists for the lifetime of the Shell item instance; basically, a property bag attached to the item instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if temporary; otherwise, <c>false</c>.</value>
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool Temporary
|
||||||
|
{
|
||||||
|
get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Temporary == value) return;
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY, value);
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
flags = GETPROPERTYSTOREFLAGS.GPS_TEMPORARY;
|
||||||
|
ReadOnly = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Gets an <see cref="IEnumerable{T}"/> containing the keys of the <see cref="IReadOnlyDictionary{PROPERTYKEY, Object}"/>.</summary>
|
/// <summary>Gets an <see cref="IEnumerable{T}"/> containing the keys of the <see cref="IReadOnlyDictionary{PROPERTYKEY, Object}"/>.</summary>
|
||||||
public IEnumerable<PROPERTYKEY> Keys => Run(ps => GetKeyEnum(ps).ToList())!;
|
public IEnumerable<PROPERTYKEY> Keys => Run(ps => GetKeyEnum(ps).ToList())!;
|
||||||
|
@ -170,7 +266,7 @@ public abstract class ReadOnlyPropertyStore : IReadOnlyDictionary<PROPERTYKEY, o
|
||||||
/// <summary>Returns an enumerator that iterates through the collection.</summary>
|
/// <summary>Returns an enumerator that iterates through the collection.</summary>
|
||||||
/// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.</returns>
|
/// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.</returns>
|
||||||
IEnumerator<KeyValuePair<PROPERTYKEY, object?>> IEnumerable<KeyValuePair<PROPERTYKEY, object?>>.GetEnumerator() =>
|
IEnumerator<KeyValuePair<PROPERTYKEY, object?>> IEnumerable<KeyValuePair<PROPERTYKEY, object?>>.GetEnumerator() =>
|
||||||
(Run(ps => GetKeyEnum(ps).Select(k => new KeyValuePair<PROPERTYKEY, object?>(k, TryGetValue(ps, k, out object? pv) ? pv : null))) ?? new KeyValuePair<PROPERTYKEY, object?>[0]).GetEnumerator();
|
(Run(ps => GetKeyEnum(ps).Select(k => new KeyValuePair<PROPERTYKEY, object?>(k, TryGetValue(ps, k, out object? pv) ? pv : null))) ?? []).GetEnumerator();
|
||||||
|
|
||||||
/// <summary>Returns an enumerator that iterates through a collection.</summary>
|
/// <summary>Returns an enumerator that iterates through a collection.</summary>
|
||||||
/// <returns>An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.</returns>
|
/// <returns>An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.</returns>
|
||||||
|
@ -191,7 +287,12 @@ public abstract class ReadOnlyPropertyStore : IReadOnlyDictionary<PROPERTYKEY, o
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>The IPropertyStore instance. This can be null.</summary>
|
/// <summary>The IPropertyStore instance. This can be null.</summary>
|
||||||
protected virtual IPropertyStore? GetIPropertyStore() => iPropertyStore;
|
protected virtual IPropertyStore? GetIPropertyStore()
|
||||||
|
{
|
||||||
|
if (iPropertyStore is null && itemPath is not null)
|
||||||
|
SHGetPropertyStoreFromParsingName(itemPath, iBindCtx, flags, typeof(IPropertyStore).GUID, out iPropertyStore).ThrowIfFailed();
|
||||||
|
return iPropertyStore;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Gets an enumeration of the keys in the property store.</summary>
|
/// <summary>Gets an enumeration of the keys in the property store.</summary>
|
||||||
/// <returns>Keys in the property store.</returns>
|
/// <returns>Keys in the property store.</returns>
|
||||||
|
@ -221,24 +322,20 @@ public abstract class ReadOnlyPropertyStore : IReadOnlyDictionary<PROPERTYKEY, o
|
||||||
return iPropertyStore is null ? default : action.Invoke(iPropertyStore);
|
return iPropertyStore is null ? default : action.Invoke(iPropertyStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PropertyDescriptionDictionary : IReadOnlyDictionary<PROPERTYKEY, PropertyDescription>
|
private class PropertyDescriptionDictionary(ReadOnlyPropertyStore ps) : IReadOnlyDictionary<PROPERTYKEY, PropertyDescription>
|
||||||
{
|
{
|
||||||
private readonly ReadOnlyPropertyStore store;
|
public IEnumerable<PropertyDescription> Values => ps.Keys.Select(GetPropertyDescription).ToList();
|
||||||
|
|
||||||
public PropertyDescriptionDictionary(ReadOnlyPropertyStore ps) => store = ps;
|
public int Count => ps.Count;
|
||||||
|
|
||||||
public IEnumerable<PropertyDescription> Values => store.Keys.Select(GetPropertyDescription).ToList();
|
public IEnumerable<PROPERTYKEY> Keys => ps.Keys;
|
||||||
|
|
||||||
public int Count => store.Count;
|
|
||||||
|
|
||||||
public IEnumerable<PROPERTYKEY> Keys => store.Keys;
|
|
||||||
|
|
||||||
public PropertyDescription this[PROPERTYKEY key] => GetPropertyDescription(key);
|
public PropertyDescription this[PROPERTYKEY key] => GetPropertyDescription(key);
|
||||||
|
|
||||||
public bool ContainsKey(PROPERTYKEY key) => store.ContainsKey(key);
|
public bool ContainsKey(PROPERTYKEY key) => ps.ContainsKey(key);
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<PROPERTYKEY, PropertyDescription>> GetEnumerator() =>
|
public IEnumerator<KeyValuePair<PROPERTYKEY, PropertyDescription>> GetEnumerator() =>
|
||||||
store.Keys.Select(k => new KeyValuePair<PROPERTYKEY, PropertyDescription>(k, GetPropertyDescription(k))).ToList().GetEnumerator();
|
ps.Keys.Select(k => new KeyValuePair<PROPERTYKEY, PropertyDescription>(k, GetPropertyDescription(k))).ToList().GetEnumerator();
|
||||||
|
|
||||||
#if NET40_OR_GREATER || NETSTANDARD2_0_OR_GREATER && !NET5_0_OR_GREATER
|
#if NET40_OR_GREATER || NETSTANDARD2_0_OR_GREATER && !NET5_0_OR_GREATER
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
@ -247,7 +344,7 @@ public abstract class ReadOnlyPropertyStore : IReadOnlyDictionary<PROPERTYKEY, o
|
||||||
public bool TryGetValue(PROPERTYKEY key, [MaybeNullWhen(false)] out PropertyDescription value)
|
public bool TryGetValue(PROPERTYKEY key, [MaybeNullWhen(false)] out PropertyDescription value)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (store.ContainsKey(key))
|
if (ps.ContainsKey(key))
|
||||||
{
|
{
|
||||||
value = this[key];
|
value = this[key];
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.ComponentModel;
|
||||||
using System.ComponentModel;
|
|
||||||
using Vanara.PInvoke;
|
using Vanara.PInvoke;
|
||||||
using static Vanara.PInvoke.Ole32;
|
using static Vanara.PInvoke.Ole32;
|
||||||
using static Vanara.PInvoke.PropSys;
|
using static Vanara.PInvoke.PropSys;
|
||||||
|
@ -11,10 +10,7 @@ namespace Vanara.Windows.Shell;
|
||||||
public sealed class ShellItemPropertyStore : PropertyStore
|
public sealed class ShellItemPropertyStore : PropertyStore
|
||||||
{
|
{
|
||||||
/// <summary>The shell item</summary>
|
/// <summary>The shell item</summary>
|
||||||
private ShellItem shellItem;
|
private readonly ShellItem shellItem;
|
||||||
|
|
||||||
/// <summary>The flags.</summary>
|
|
||||||
private GETPROPERTYSTOREFLAGS flags = GETPROPERTYSTOREFLAGS.GPS_BESTEFFORT;
|
|
||||||
|
|
||||||
/// <summary>Initializes a new instance of the <see cref="ShellItemPropertyStore"/> class.</summary>
|
/// <summary>Initializes a new instance of the <see cref="ShellItemPropertyStore"/> class.</summary>
|
||||||
/// <param name="item">The ShellItem instance.</param>
|
/// <param name="item">The ShellItem instance.</param>
|
||||||
|
@ -35,39 +31,6 @@ public sealed class ShellItemPropertyStore : PropertyStore
|
||||||
[DefaultValue(null)]
|
[DefaultValue(null)]
|
||||||
public ICreateObject? Creator { get; set; }
|
public ICreateObject? Creator { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets a value indicating whether to include slow properties.</summary>
|
|
||||||
/// <value><c>true</c> if including slow properties; otherwise, <c>false</c>.</value>
|
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool IncludeSlow
|
|
||||||
{
|
|
||||||
get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_OPENSLOWITEM);
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (IncludeSlow == value) return;
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_OPENSLOWITEM, value);
|
|
||||||
if (value)
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Gets a value indicating whether the <see cref="ICollection{T}"/> is read-only.</summary>
|
|
||||||
public override bool IsReadOnly => ReadOnly;
|
|
||||||
|
|
||||||
/// <summary>Gets or sets a value indicating whether to include only properties directly from the property handler.</summary>
|
|
||||||
/// <value><c>true</c> if no inherited properties; otherwise, <c>false</c>.</value>
|
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool NoInheritedProperties
|
|
||||||
{
|
|
||||||
get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY);
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (NoInheritedProperties == value) return;
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY, value);
|
|
||||||
if (value)
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_BESTEFFORT | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a set of properties used to filter the property store. This value can be <see langword="null"/>. This value will be
|
/// Gets or sets a set of properties used to filter the property store. This value can be <see langword="null"/>. This value will be
|
||||||
/// ignored if <see cref="Creator"/> is also set.
|
/// ignored if <see cref="Creator"/> is also set.
|
||||||
|
@ -76,48 +39,6 @@ public sealed class ShellItemPropertyStore : PropertyStore
|
||||||
[DefaultValue(null)]
|
[DefaultValue(null)]
|
||||||
public PROPERTYKEY[]? PropertyFilter { get; set; }
|
public PROPERTYKEY[]? PropertyFilter { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets a value indicating whether properties can be read and written.</summary>
|
|
||||||
/// <value><c>true</c> if properties are read/write; otherwise, <c>false</c>.</value>
|
|
||||||
[DefaultValue(true)]
|
|
||||||
public bool ReadOnly
|
|
||||||
{
|
|
||||||
get => !flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_READWRITE);
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (ReadOnly == value) return;
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_READWRITE, !value);
|
|
||||||
if (!value)
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_DELAYCREATION | GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_BESTEFFORT | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false);
|
|
||||||
else
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether this <see cref="ShellItemPropertyStore"/> provides a writable store, with no initial
|
|
||||||
/// properties, that exists for the lifetime of the Shell item instance; basically, a property bag attached to the item instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if temporary; otherwise, <c>false</c>.</value>
|
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool Temporary
|
|
||||||
{
|
|
||||||
get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY);
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Temporary == value) return;
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY, value);
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
flags = GETPROPERTYSTOREFLAGS.GPS_TEMPORARY;
|
|
||||||
ReadOnly = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue