Handling ProgressBar's Value change with UIAutomation - microsoft-ui-automation

How can I be notified when ProgressBar's Value changes with .NET UIAutomation framework? I dont see such property in AutomationElement class.

I drew this sample directly from the MSDN documentation, changing only the property:
AutomationPropertyChangedEventHandler propChangeHandler;
/// <summary>
/// Adds a handler for property-changed event; in particular, a change in the value
/// </summary>
/// <param name="element">The UI Automation element whose state is being monitored.</param>
public void SubscribePropertyChange(AutomationElement element)
{
Automation.AddAutomationPropertyChangedEventHandler(element,
TreeScope.Element,
propChangeHandler = new AutomationPropertyChangedEventHandler(OnPropertyChange),
ValuePattern.ValueProperty);
}
/// <summary>
/// Handler for property changes.
/// </summary>
/// <param name="src">The source whose properties changed.</param>
/// <param name="e">Event arguments.</param>
private void OnPropertyChange(object src, AutomationPropertyChangedEventArgs e)
{
AutomationElement sourceElement = src as AutomationElement;
if (e.Property == ValuePattern.ValueProperty)
{
// TODO: Do something with the new value.
// The element that raised the event can be identified by its runtime ID property.
}
else
{
// TODO: Handle other property-changed events.
}
}
public void UnsubscribePropertyChange(AutomationElement element)
{
if (propChangeHandler != null)
{
Automation.RemoveAutomationPropertyChangedEventHandler(element, propChangeHandler);
}
}

Related

Microsoft Azure Spatial anchors script problem

I haven't find so far any good and update script for manage the Microsoft Spatial Azure Anchors, could you please review this code and tell me more or less if i am in the right way or not ? Actually I am trying to minimize the code for having the pure functionality, but i am stack and i can't even find an understandable guideline
hope the code is readable and well documented.
thanks in advance.
Andrea
using Microsoft.Azure;
using Microsoft.Azure.SpatialAnchors;
using Microsoft.Azure.SpatialAnchors.Unity;
using Microsoft.MixedReality.OpenXR;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.XR.WSA;
using UnityEngine.XR.WSA.Input;
public class AnchorsManager : MonoBehaviour
{
/// <summary>
/// Input
/// </summary>
private GameObject localAnchor;
/// <summary>
/// AZURE settings AccountId
/// </summary>
private string AccountId = "00886172-b41a-....";
/// <summary>
/// AZURE settings AccountKey
/// </summary>
private string AccountKey = "09c3eddc-....";
/// <summary>
/// AZURE settings AccountDomain
/// </summary>
private string AccountDomain = "northeurope.mixedreality.azure.com";
/// <summary>
/// Azure session
/// </summary>
private CloudSpatialAnchorSession cloudSession;
/// <summary>
/// For Storing the object Ids
/// </summary>
private AnchorLocateCriteria criteria = new AnchorLocateCriteria();
protected List<string> anchorIdsToLocate = new List<string>();
void Start()
{
InitializeSession();
}
/// <summary>
/// Only when the user drag an object we can save the anchor with the latest position
/// </summary>
void onMouseObjectDown(GameObject prefab)
{
this.localAnchor = prefab;
this.cloudSession.Start();
}
/// <summary>
/// Inizialize the cloudSpatialAnchorSession.
/// </summary>
void InitializeSession()
{
try {
this.cloudSession = new CloudSpatialAnchorSession();
this.cloudSession.Configuration.AccountId = this.AccountId;
this.cloudSession.Configuration.AccountKey = this.AccountKey;
this.cloudSession.Configuration.AccountDomain = this.AccountDomain;
this.cloudSession.SessionUpdated += (sender, args) =>
{
if (args.Status.RecommendedForCreateProgress != 0)
{
this.CreateAnchor();
}
};
//WATCHERS
this.cloudSession.CreateWatcher(criteria);
this.cloudSession.AnchorLocated += (object sender, AnchorLocatedEventArgs args) =>
{
switch (args.Status)
{
case LocateAnchorStatus.Located:
CloudSpatialAnchor foundAnchor = args.Anchor;
Debug.Log("ASA Info: Anchor located! Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.AlreadyTracked:
Debug.Log("This anchor has already been reported and is being tracked" + args.Identifier);
break;
case LocateAnchorStatus.NotLocated:
Debug.Log("ASA Info: Anchor not located. Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.NotLocatedAnchorDoesNotExist:
Debug.LogError("ASA Error: Anchor not located does not exist. Identifier: " + args.Identifier);
break;
}
};
}
catch (Exception ex) {
Debug.LogError("Error on initialize the session: " + ex.Message);
}
}
/// <summary>
/// CreateAnchor
/// </summary>
async void CreateAnchor()
{
// Create Anchor in local;
localAnchor.AddComponent<CloudNativeAnchor>();
CloudNativeAnchor cloudNativeAnchor = localAnchor.GetComponent<CloudNativeAnchor>();
if (cloudNativeAnchor.CloudAnchor == null) { await cloudNativeAnchor.NativeToCloud(); }
// Add Anchor property;
CloudSpatialAnchor cloudAnchor = cloudNativeAnchor.CloudAnchor;
cloudAnchor.AppProperties[#"room"] = #"bagno";
cloudAnchor.AppProperties[#"product"] = #"saponetta";
cloudAnchor.Expiration = DateTimeOffset.Now.AddDays(7);
// Create Anchor
await cloudSession.CreateAnchorAsync(cloudAnchor);
Debug.Log("Cloud anchor created with ID = " + cloudAnchor.Identifier);
// Save Anchor ID
this.anchorIdsToLocate.Add(cloudAnchor.Identifier);
this.criteria.Identifiers = anchorIdsToLocate.ToArray();
Debug.Log("Anchor Id has been saved on the array");
}
}

error CS0117: 'EditorUtility' does not contain a definition for 'RequestScriptReload'

In unity I keep on getting this error that keeps on bugging me, I tried to remove packages to leave one of these errors and it kept on going on and on, i am developing a game right now using unity engine and the errors are a big pain for me, this is the code that someone asked for, i dont really have much else to write other than this, stackoverlow isnt letting me just post it because its too short
using System;
using System.IO;
using UnityEngine;
namespace UnityEditor.SettingsManagement
{
/// <inheritdoc />
/// <summary>
/// A settings repository that stores data local to a Unity project.
/// </summary>
[Serializable]
public sealed class PackageSettingsRepository : ISettingsRepository
{
const string k_PackageSettingsDirectory = "ProjectSettings/Packages";
const bool k_PrettyPrintJson = true;
bool m_Initialized;
[SerializeField]
string m_Name;
[SerializeField]
string m_Path;
[SerializeField]
SettingsDictionary m_Dictionary = new SettingsDictionary();
/// <summary>
/// Constructor sets the serialized data path.
/// </summary>
/// <param name="package">
/// The package name.
/// </param>
/// <param name="name">
/// A name for this settings file. Settings are saved in `ProjectSettings/Packages/{package}/{name}.json`.
/// </param>
public PackageSettingsRepository(string package, string name)
{
m_Name = name;
m_Path = GetSettingsPath(package, name);
m_Initialized = false;
AssemblyReloadEvents.beforeAssemblyReload += Save;
EditorApplication.quitting += Save;
}
void Init()
{
if (m_Initialized)
return;
m_Initialized = true;
if (File.Exists(path))
{
m_Dictionary = null;
var json = File.ReadAllText(path);
EditorJsonUtility.FromJsonOverwrite(json, this);
if(m_Dictionary == null)
m_Dictionary = new SettingsDictionary();
}
}
/// <value>
/// This repository implementation is relevant to the Project scope.
/// </value>
/// <inheritdoc cref="ISettingsRepository.scope"/>
public SettingsScope scope
{
get { return SettingsScope.Project; }
}
/// <value>
/// The full path to the settings file.
/// This corresponds to `Unity Project/Project Settings/Packages/com.unity.package/name`.
/// </value>
/// <inheritdoc cref="ISettingsRepository.path"/>
public string path
{
get { return m_Path; }
}
/// <summary>
/// The name of this settings file.
/// </summary>
public string name
{
get { return m_Name; }
}
// Cannot call FindFromAssembly from a constructor or field initializer
// static string CreateSettingsPath(Assembly assembly, string name)
// {
// var info = PackageManager.PackageInfo.FindForAssembly(assembly);
// return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, info.name, name);
// }
/// <summary>
/// Get a path for a settings file relative to the calling assembly package directory.
/// </summary>
/// <param name="packageName">The name of the package requesting this setting.</param>
/// <param name="name">An optional name for the settings file. Default is "Settings."</param>
/// <returns>A package-scoped path to the settings file within Project Settings.</returns>
public static string GetSettingsPath(string packageName, string name = "Settings")
{
return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, packageName, name);
}
/// <summary>
/// Save all settings to their serialized state.
/// </summary>
/// <inheritdoc cref="ISettingsRepository.Save"/>
public void Save()
{
Init();
if (!File.Exists(path))
{
var directory = Path.GetDirectoryName(path);
Directory.CreateDirectory(directory);
}
#if UNITY_2019_3_OR_NEWER
if (!AssetDatabase.IsOpenForEdit(path))
{
if (!AssetDatabase.MakeEditable(path))
{
Debug.LogWarning($"Could not save package settings to {path}");
return;
}
}
#endif
try
{
File.WriteAllText(path, EditorJsonUtility.ToJson(this, k_PrettyPrintJson));
}
catch (UnauthorizedAccessException)
{
Debug.LogWarning($"Could not save package settings to {path}");
}
}
/// <summary>
/// Set a value for key of type T.
/// </summary>
/// <param name="key">The settings key.</param>
/// <param name="value">The value to set. Must be serializable.</param>
/// <typeparam name="T">Type of value.</typeparam>
/// <inheritdoc cref="ISettingsRepository.Set{T}"/>
public void Set<T>(string key, T value)
{
Init();
m_Dictionary.Set<T>(key, value);
}
/// <summary>
/// Get a value with key of type T, or return the fallback value if no matching key is found.
/// </summary>
/// <param name="key">The settings key.</param>
/// <param name="fallback">If no key with a value of type T is found, this value is returned.</param>
/// <typeparam name="T">Type of value to search for.</typeparam>
/// <inheritdoc cref="ISettingsRepository.Get{T}"/>
public T Get<T>(string key, T fallback = default(T))
{
Init();
return m_Dictionary.Get<T>(key, fallback);
}
/// <summary>
/// Does the repository contain a setting with key and type.
/// </summary>
/// <param name="key">The settings key.</param>
/// <typeparam name="T">The type of value to search for.</typeparam>
/// <returns>True if a setting matching both key and type is found, false if no entry is found.</returns>
/// <inheritdoc cref="ISettingsRepository.ContainsKey{T}"/>
public bool ContainsKey<T>(string key)
{
Init();
return m_Dictionary.ContainsKey<T>(key);
}
/// <summary>
/// Remove a key value pair from the settings repository.
/// </summary>
/// <param name="key"></param>
/// <typeparam name="T"></typeparam>
/// <inheritdoc cref="ISettingsRepository.Remove{T}"/>
public void Remove<T>(string key)
{
Init();
m_Dictionary.Remove<T>(key);
By the definition of 'RequestScriptReload' :
"The Unity Editor reloads script assemblies asynchronously on the next frame. This resets the state of all the scripts, but Unity does not compile any code that has changed since the previous compilation."
That means that your problem is probably with something that you changed.
You can try:
Going back to the last time everything wored and go on from there.
Closing all of you unity and scripting applications and opening it again.

FlowListView not fully updating UI when changing ObservableCollection<T>

When I remove objects from the list the UI doesn't reflect the current state of the list, normally failling by only one item.
Example: If I remove 4 items, on the UI only shows that I removed 3 items
private ObservableCollection<Card> _cards;
public ObservableCollection<Card> Cards
{
get
{
if (_cards == null)
{
_cards = new ObservableCollection<Card>();
return _cards;
}
return _cards;
}
set
{
SetValue(ref _cards, value);
}
}
My remove method
private void RemoveFromCards(Card card)
{
for (int i = Cards.Count - 1; i >= 0; i--)
{
if (Cards[i].Id == card.Id)
{
Cards.RemoveAt(i);
/* I tried this but doesn't work also
*
*
ObservableCollection<Card> copy = Cards;
copy.RemoveAt(i);
Cards = copy;
*/
}
}
}
Calling remove method
private void RemoveCardsFromView(List<Archive> cards)
{
foreach (Archive a in cards)
{
Card c = new Card {Id = a.CardId};
RemoveFromCards(c);
}
}
Calling code
public async Task RefreshCardsView()
{
if (!CrossConnectivity.Current.IsConnected)
{
BuildToast(false,"No internet connection");
return;
}
try
{
JsonResult cards = (JsonResult) await HttpMiddleman.GetCards();
RemoveCardsFromView(cards.Data.DeletedCards);
AddCardsToView(cards.Data.AddedCards);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
BuildToast(false,"Could not refresh");
}
}
My binding in FlowListView
<controls:FlowListView x:Name="Board" HasUnevenRows="True"
BackgroundColor="Black"
FlowColumnCount="2"
FlowItemTappedCommand="{Binding ExecuteActionCommand}"
FlowColumnMinWidth="110"
IsPullToRefreshEnabled="True"
IsRefreshing="{Binding IsRefreshing}"
RefreshCommand="{Binding RefreshViewCommand}"
FlowItemsSource="{Binding Cards}"> .....
Thanks in advance guys
make sure that you fire correctly OnPropertyChanged after SetValue() in property statement
and
try with this class (from xamarin) and pass ienumerable of card instead card only object.
Example
private void RemoveFromCards(Card card)
{
Cards.RemoveRange(new []{card});
}
//or directly from
private void RemoveCardsFromView(List<Archive> cards)
{
Cards.RemoveRange(cards.Select(s=> new Card {Id = a.CardId}));
}
/// <summary>
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObservableRangeCollection<T> : ObservableCollection<T>
{
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class.
/// </summary>
public ObservableRangeCollection()
: base()
{
}
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection.
/// </summary>
/// <param name="collection">collection: The collection from which the elements are copied.</param>
/// <exception cref="System.ArgumentNullException">The collection parameter cannot be null.</exception>
public ObservableRangeCollection(IEnumerable<T> collection)
: base(collection)
{
}
/// <summary>
/// Adds the elements of the specified collection to the end of the ObservableCollection(Of T).
/// </summary>
public void AddRange(IEnumerable<T> collection, NotifyCollectionChangedAction notificationMode = NotifyCollectionChangedAction.Add)
{
if (collection == null)
throw new ArgumentNullException("collection");
CheckReentrancy();
if (notificationMode == NotifyCollectionChangedAction.Reset)
{
foreach (var i in collection)
{
Items.Add(i);
}
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
return;
}
int startIndex = Count;
var changedItems = collection is List<T> ? (List<T>)collection : new List<T>(collection);
foreach (var i in changedItems)
{
Items.Add(i);
}
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, changedItems, startIndex));
}
/// <summary>
/// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T).
/// </summary>
public void RemoveRange(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
foreach (var i in collection)
Items.Remove(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>
/// Clears the current collection and replaces it with the specified item.
/// </summary>
public void Replace(T item)
{
ReplaceRange(new T[] { item });
}
/// <summary>
/// Clears the current collection and replaces it with the specified collection.
/// </summary>
public void ReplaceRange(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
Items.Clear();
AddRange(collection, NotifyCollectionChangedAction.Reset);
}
}

How do I fix this error when trying to use the Watson SDK for Unity?

thanks for taking a look at this. I'm new to Unity and struggling to understand how to fix this error.
Assets/Watson/Scripts/Logging/Logger.cs(115,53): error CS0311: The type IBM.Watson.DeveloperCloud.Logging.LogSystem' cannot be used as type parameter T in the generic type or method Singleton. There is no implicit reference conversion from IBM.Watson.DeveloperCloud.Logging.LogSystem' to `UnityEngine.MonoBehaviour
This is the line causing the error:
public static LogSystem Instance { get { return Singleton<LogSystem>.Instance; } }
And this is it in context:
/// <summary>
/// This singleton class maintains the of list of installed reactors and handles all LogRecord
/// objects. See the static class Log for functions the end user of this system should actually
/// be calling. This class is thread safe.
/// </summary>
public class LogSystem
{
#region Public Properties
/// <summary>
/// Returns the singleton instance of the Logger object.
/// </summary>
**public static LogSystem Instance { get { return Singleton<LogSystem>.Instance; } }**
#endregion
#region Private Data
private static bool sm_bInstalledDefaultReactors = false;
List<ILogReactor> m_Reactors = new List<ILogReactor>();
#endregion
#region Public Functions
public static List<ILogReactor> ReactorsInstalled
{
get
{
return LogSystem.Instance.m_Reactors;
}
}
/// <summary>
/// Install a default debug and file reactor.
/// </summary>
public static void InstallDefaultReactors(int logHistory = 2, LogLevel logLevelFileReactor = LogLevel.STATUS)
{
if (!sm_bInstalledDefaultReactors)
{
// install the default reactors...
sm_bInstalledDefaultReactors = true;
#if UNITY_EDITOR || UNITY_IOS || UNITY_ANDROID
LogSystem.Instance.InstallReactor(new DebugReactor());
#endif
if (!string.IsNullOrEmpty(Constants.Path.LOG_FOLDER) && !System.IO.Directory.Exists(Application.persistentDataPath + Constants.Path.LOG_FOLDER))
System.IO.Directory.CreateDirectory(Application.persistentDataPath + Constants.Path.LOG_FOLDER);
LogSystem.Instance.InstallReactor(new FileReactor(Application.persistentDataPath + Constants.Path.LOG_FOLDER + "/" + Application.productName + ".log", logLevelFileReactor, logHistory));
Application.logMessageReceived += UnityLogCallback;
}
}
static void UnityLogCallback(string condition, string stacktrace, LogType type)
{
if (type == LogType.Exception)
Log.Critical("Unity", "Unity Exception {0} : {1}", condition, stacktrace);
}
/// <summary>
/// Installs a reactor into this Logger.
/// </summary>
/// <param name="reactor">The reactor object.</param>
public void InstallReactor(ILogReactor reactor)
{
lock (m_Reactors)
{
m_Reactors.Add(reactor);
}
// set our default reactor flag to true if the user installs their own reactors.
sm_bInstalledDefaultReactors = true;
}
/// <summary>
/// Removes a reactor from this Logger.
/// </summary>
/// <param name="reactor">The reactor to remove.</param>
/// <returns>Returns true on success.</returns>
public bool RemoveReactor(ILogReactor reactor)
{
lock (m_Reactors)
{
return m_Reactors.Remove(reactor);
}
}
/// <summary>
/// Send the given LogRecord to all installed reactors.
/// </summary>
/// <param name="log">The LogRecord to pass to all reactors.</param>
public void ProcessLog(LogRecord log)
{
lock (m_Reactors)
{
foreach (var reactor in m_Reactors)
reactor.ProcessLog(log);
}
}
#endregion
}
public static LogSystem Instance
{
get
{
return instance;
}
}
private static LogSystem instance;
// Ctor of the class
public LogSystem()
{
if(instance == null) { instance = this;}
}
This is a very basic singleton pattern implementation. You can find more advanced ones online.

CRM 2011 Plugin - Check if OptionSet is not empty

I am writing a plugin where I check if a particular value of a field, an Option Set is equal to a specific value and if so, then I do certain actions.
Now, within the plugin C# code, how can I check that the Option Set field is not null - i.e., is set to the Default Value?
What I did (clearly, that is wrong) because, it never went past the Null check statement. And, if I did not have the check, then I get this error message
Error:
Unexpected exception from plug-in (Execute): CRM.AppStateHandler.Plugins.PostApplicationCreate: System.NullReferenceException: Object reference not set to an instance of an object.
Code:
application applicationEntity = entity.ToEntity<new_application>();
if (new_applicationEntity.new_Applicationstatus != null)
{
var applicationStatus = applicationEntity.new_Applicationstatus.Value;
if (applicationStatus == CRMConstants.EntityApplication.Attributes.ApplicationStatusOptions.Applying)
{
//my logic
}
}
File constants.cs has the following
class CRMConstants
{
public struct EntityApplication
{
public struct Attributes
{
public struct ApplicationStatusOptions
{
// More before this
public const int Applying = 100000006;
// More to come
}
}
}
I think SergeyS has your fix, but I'll add some other (hopefully) helpful comments.
Don't custom create structs for your Option Set Values. Use the CrmSrvcUtil to create enums for you automatically.
I get annoyed with having to check for OptionSetValues being null or not, so I use these extension methods to make my life easier:
/// <summary>
/// Returns the value of the OptionSetValue, or int.MinValue if it is null
/// </summary>
/// <param name="osv"></param>
/// <param name="value"></param>
/// <returns></returns>
public static int GetValueOrDefault(this OptionSetValue osv)
{
return GetValueOrDefault(osv, int.MinValue);
}
/// <summary>
/// Returns the value of the OptionSetValue, or int.MinValue if it is null
/// </summary>
/// <param name="osv"></param>
/// <param name="value"></param>
/// <returns></returns>
public static int GetValueOrDefault(this OptionSetValue osv, int defaultValue)
{
if (osv == null)
{
return defaultValue;
}
else
{
return osv.Value;
}
}
/// <summary>
/// Allows for Null safe Equals Comparison for more concise code. ie.
/// if(contact.GenderCode.NullSafeEquals(1))
/// vs.
/// if(contact.GenderCode != null && contact.gendercode.Value == 1)
/// </summary>
/// <param name="osv"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool NullSafeEquals(this OptionSetValue osv, int value)
{
if (osv == null)
{
return false;
}
else
{
return osv.Value == value;
}
}
/// <summary>
/// Allows for Null safe Equals Comparison for more concise code. ie.
/// if(contact.GenderCode.NullSafeEquals(new OptionSet(1)))
/// vs.
/// if(contact.GenderCode != null && contact.gendercode.Value == new OptionSet(1))
/// </summary>
/// <param name="osv"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool NullSafeEquals(this OptionSetValue osv, OptionSetValue value)
{
if (osv == null)
{
return osv == value;
}
else
{
return osv.Equals(value);
}
}
There are two methods each with an overload:
GetValueOrDefault - This is equivalent to the Nullable.GetValueOrDefault(). The one difference is rather than defaulting to 0, I default to int.MinValue to make sure I don't accidentally match on a 0 optionset value. The Overload allows you to specify the default value if you'd like.
NullSafeEquals - This is the one you'd be using in your code to not have to check for null
application applicationEntity = entity.ToEntity<new_application>();
if (applicationEntity.new_Applicationstatus.NullSafeEquals(CRMConstants.EntityApplication.Attributes.ApplicationStatusOptions.Applying))
{
//my logic
}
You are checking:
if (new_applicationEntity.new_Applicationstatus != null)
but you need to check:
if (applicationEntity.new_Applicationstatus != null)