public static void Start(this PropertyChangedEventHandler?Handler, object Sender, params string[] PropertyName) { if (PropertyName is null) { throw new ArgumentNullException(nameof(PropertyName)); } if (Handler is null || PropertyName.Length == 0) { return; } var args = PropertyName.ToArray(name => new PropertyChangedEventArgs(name)); foreach (var d in Handler.GetInvocationList()) { switch (d.Target) { case ISynchronizeInvoke { InvokeRequired: true } synchronize_invoke: foreach (var arg in args) { synchronize_invoke.Invoke(d, new[] { Sender, arg }); } break; default: foreach (var arg in args) { d.DynamicInvoke(Sender, arg); } break; } } }
public static bool MutateVerbose <TProperty>(this INotifyPropertyChanged self, ref TProperty property, TProperty value, PropertyChangedEventHandler?eventHandler, Dispatcher?dispatcher = null, [CallerMemberName] string?propertyName = null) { if (EqualityComparer <TProperty> .Default.Equals(property, value)) { return(false); } property = value; if (eventHandler == null) { return(true); } if (dispatcher == null || dispatcher.CheckAccess()) { eventHandler.Invoke(self, new PropertyChangedEventArgs(propertyName)); } else { dispatcher.Invoke(() => eventHandler.Invoke(self, new PropertyChangedEventArgs(propertyName))); } return(true); }
/// <summary> /// Adds a handler, returning whether or not this has caused the underlying handler /// to go from "subscribed" to "unsubscribed". /// </summary> /// <param name="value">The handler to add.</param> /// <returns>true if there were previously no handlers, but now there's at least one; false otherwise.</returns> public static bool RemoveHandler(ref PropertyChangedEventHandler?field, PropertyChangedEventHandler?value) { if (value is null || field is null) { return(false); } field -= value; return(field is null); }
/// <summary> /// Raises the <see cref="PropertyChanged"/> event. /// </summary> /// <param name="propertyName">The name of the property that has changed.</param> /// <remarks> /// This method is useful when setting one property via <see cref="Update"/> /// also causes a dependent "read-only" property to be updated. /// </remarks> protected void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler?handler = this.PropertyChanged; if (handler != null) { PropertyChangedEventArgs args = new(propertyName); handler(this, args); } }
/// <summary> /// Adds a handler, returning whether or not this has caused the underlying handler /// to go from "unsubscribed" to "subscribed". /// </summary> /// <param name="value">The handler to add.</param> /// <returns>true if there were previously no handlers, but now there's at least one; false otherwise.</returns> public static bool AddHandler(ref PropertyChangedEventHandler?field, PropertyChangedEventHandler?value) { if (value is null) { return(false); } // TODO: Make this thread-safe. bool ret = field is null; field += value; return(ret); }
/// <summary> /// Raises the specified e. /// </summary> /// <param name="eventHandler">The event handler.</param> /// <param name="propertyName">Name of the property.</param> /// <returns> /// Is any raised. /// </returns> public static bool Raise( this PropertyChangedEventHandler?eventHandler, [CallerMemberName] string?propertyName = null !) { if (eventHandler == null) { return(false); } eventHandler(null, new PropertyChangedEventArgs(propertyName)); return(true); }
// https://stackoverflow.com/a/60668668/111794 public static void NotifyChanged <T>( this INotifyPropertyChanged inpc, ref T current, T newValue, PropertyChangedEventHandler?handler, [CallerMemberName] string?name = null) { if (EqualityComparer <T> .Default.Equals(current, newValue)) { return; } current = newValue; handler?.Invoke(inpc, new PropertyChangedEventArgs(name)); }
protected void WireUpForceUpdateSizeRequested(ICellController cell, UITableViewCell platformCell, UITableView tableView) { var inpc = cell as INotifyPropertyChanged; cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested; if (inpc != null) { inpc.PropertyChanged -= _onPropertyChangedEventHandler; } _onForceUpdateSizeRequested = (sender, e) => { var index = tableView?.IndexPathForCell(platformCell); if (index == null && sender is Cell c) { index = Controls.Compatibility.Platform.iOS.CellExtensions.GetIndexPath(c); } if (index != null) { tableView?.ReloadRows(new[] { index }, UITableViewRowAnimation.None); } }; _onPropertyChangedEventHandler = (sender, e) => { if (e.PropertyName == "RealCell" && sender is BindableObject bo && GetRealCell(bo) == null) { if (sender is ICellController icc) { icc.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested; } if (sender is INotifyPropertyChanged notifyPropertyChanged) { notifyPropertyChanged.PropertyChanged -= _onPropertyChangedEventHandler; } _onForceUpdateSizeRequested = null; _onPropertyChangedEventHandler = null; } }; cell.ForceUpdateSizeRequested += _onForceUpdateSizeRequested; if (inpc != null) { inpc.PropertyChanged += _onPropertyChangedEventHandler; } }
public static bool MutateVerboseIfNotNull <TProperty>(this INotifyPropertyChanged self, ref TProperty property, TProperty value, PropertyChangedEventHandler?eventHandler, Dispatcher?dispatcher = null, [CallerMemberName] string?propertyName = null) { if (value == null) { return(false); } return(self.MutateVerbose(ref property, value, eventHandler, dispatcher, propertyName)); }
public static bool RaiseAndSetIfChanged <T, U>( this T @this, ref U backingField, U newValue, PropertyChangedEventHandler?propertyChangedEventHandler, [CallerMemberName] string propertyName = "" ) where T : INotifyPropertyChanged { var changed = !EqualityComparer <U> .Default.Equals(backingField, newValue); if (changed) { backingField = newValue; propertyChangedEventHandler?.Invoke(@this, new PropertyChangedEventArgs(propertyName)); } return(changed); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual void Intercept(IInvocation invocation) { var methodName = invocation.Method.Name; if (invocation.Method.DeclaringType == _notifyChangedInterface) { if (methodName == $"add_{nameof(INotifyPropertyChanged.PropertyChanged)}") { _handler = (PropertyChangedEventHandler)Delegate.Combine( _handler, (Delegate)invocation.Arguments[0]); } else if (methodName == $"remove_{nameof(INotifyPropertyChanged.PropertyChanged)}") { _handler = (PropertyChangedEventHandler?)Delegate.Remove( _handler, (Delegate)invocation.Arguments[0]); } } else if (methodName.StartsWith("set_", StringComparison.Ordinal)) { var propertyName = FindPropertyName(invocation); var property = EntityType.FindProperty(propertyName); if (property != null) { HandleChanged(invocation, property, GetValueComparer(property)); } else { var navigation = EntityType.FindNavigation(propertyName) ?? (INavigationBase?)EntityType.FindSkipNavigation(propertyName); if (navigation != null) { HandleChanged(invocation, navigation, LegacyReferenceEqualityComparer.Instance); } else { invocation.Proceed(); } } } else { invocation.Proceed(); } }
public static void ThreadSafeInvoke( this PropertyChangedEventHandler?Event, object?sender, [NotNull, ItemCanBeNull] params string[] PropertyName) { if (PropertyName is null) { throw new ArgumentNullException(nameof(PropertyName)); } if (Event is null || PropertyName.Length == 0) { return; } var args = PropertyName.ToArray(name => new PropertyChangedEventArgs(name)); foreach (var d in Event.GetInvocationList()) { switch (d.Target) { case ISynchronizeInvoke { InvokeRequired: true } synchronize_invoke: foreach (var arg in args) { synchronize_invoke.Invoke(d, new[] { sender, arg }); } break; case DispatcherObject dispatcher_obj when !dispatcher_obj.CheckAccess(): foreach (var arg in args) { dispatcher_obj.Dispatcher.Invoke(d, arg); } break; default: foreach (var arg in args) { d.DynamicInvoke(sender, arg); } break; } } }
public static void ThreadSafeBeginInvoke( this PropertyChangedEventHandler?Handler, object?Sender, [NotNull] string PropertyName) { if (PropertyName is null) { throw new ArgumentNullException(nameof(PropertyName)); } if (Handler is null || PropertyName.Length == 0) { return; } var e = new PropertyChangedEventArgs(PropertyName); var invocation_list = Handler.GetInvocationList(); var args = new[] { Sender, e }; foreach (var d in invocation_list) { switch (d.Target) { case ISynchronizeInvoke { InvokeRequired: true } synchronize_invoke: synchronize_invoke.BeginInvoke(d, args); break; case DispatcherObject { Dispatcher: { } } dispatcher_obj when !dispatcher_obj.CheckAccess() : dispatcher_obj.Dispatcher.BeginInvoke(d, DispatcherPriority.DataBind, args); break; default: { var @delegate = d; ((Action <object[]>)(a => @delegate.DynamicInvoke(a))).BeginInvoke(args !, null, null); break; } } } }
public MethodToCommandConverter(Delegate action) { var target = action.Target; var canExecuteMethodName = "Can" + action.Method.Name; var parameters = action.Method.GetParameters(); var parameterInfo = parameters.Length == 0 ? null : parameters[0].ParameterType; if (parameterInfo == null) { execute = CreateExecute(target, action.Method); } else { execute = CreateExecute(target, action.Method, parameterInfo); } var canExecuteMethod = action.Method.DeclaringType?.GetRuntimeMethods() .FirstOrDefault(m => m.Name == canExecuteMethodName && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(object)); if (canExecuteMethod == null) { canExecute = AlwaysEnabled; } else { canExecute = CreateCanExecute(target, canExecuteMethod); dependencyProperties = canExecuteMethod .GetCustomAttributes(typeof(Metadata.DependsOnAttribute), true) .OfType <Metadata.DependsOnAttribute>() .Select(x => x.Name) .ToArray(); if (dependencyProperties.Any() && target is INotifyPropertyChanged inpc) { propertyChangedEventHandler = OnPropertyChanged; weakPropertyChanged = new WeakPropertyChangedProxy(inpc, propertyChangedEventHandler); } } }
public static void Start(this PropertyChangedEventHandler?Handler, object Sender, PropertyChangedEventArgs e) { if (Handler is null) { return; } foreach (var d in Handler.GetInvocationList()) { switch (d.Target) { case ISynchronizeInvoke { InvokeRequired: true } synchronize_invoke: synchronize_invoke.Invoke(d, new[] { Sender, e }); break; default: d.DynamicInvoke(Sender, e); break; } } }
public ISettingsBuilder SetOnPropertyChanged(PropertyChangedEventHandler value) { OnPropertyChanged = value; return(this); }
/// <summary> /// Initializes a new instance of the <see cref="SubscriptionBase"/> class. /// </summary> /// <param name="application">The UaApplication.</param> /// <param name="runtimeSubscriptionAttribute">The optional attribute created at runtime.</param> public SubscriptionBase(UaApplication?application, SubscriptionAttribute?runtimeSubscriptionAttribute = null) { this.application = application ?? throw new ArgumentNullException(nameof(application)); this.application.Completion.ContinueWith(t => this.stateMachineCts?.Cancel()); this.logger = this.application.LoggerFactory?.CreateLogger(this.GetType()); this.errors = new ErrorsContainer <string>(p => this.ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(p))); this.progress = new Progress <CommunicationState>(s => this.State = s); this.propertyChanged += this.OnPropertyChanged; this.whenSubscribed = new TaskCompletionSource <bool>(); this.whenUnsubscribed = new TaskCompletionSource <bool>(); this.whenUnsubscribed.TrySetResult(true); // register the action to be run on the ui thread, if there is one. if (SynchronizationContext.Current != null) { this.actionBlock = new ActionBlock <PublishResponse>(pr => this.OnPublishResponse(pr), new ExecutionDataflowBlockOptions { SingleProducerConstrained = true, TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext() }); } else { this.actionBlock = new ActionBlock <PublishResponse>(pr => this.OnPublishResponse(pr), new ExecutionDataflowBlockOptions { SingleProducerConstrained = true }); } var typeInfo = this.GetType().GetTypeInfo(); // read [Subscription] attribute. var sa = runtimeSubscriptionAttribute ?? typeInfo.GetCustomAttribute <SubscriptionAttribute>(); if (sa != null) { this.endpointUrl = sa.EndpointUrl; this.publishingInterval = sa.PublishingInterval; this.keepAliveCount = sa.KeepAliveCount; this.lifetimeCount = sa.LifetimeCount; } // read [MonitoredItem] attributes. foreach (var propertyInfo in typeInfo.DeclaredProperties) { var mia = propertyInfo.GetCustomAttribute <MonitoredItemAttribute>(); if (mia == null || string.IsNullOrEmpty(mia.NodeId)) { continue; } MonitoringFilter?filter = null; if (mia.AttributeId == AttributeIds.Value && (mia.DataChangeTrigger != DataChangeTrigger.StatusValue || mia.DeadbandType != DeadbandType.None)) { filter = new DataChangeFilter() { Trigger = mia.DataChangeTrigger, DeadbandType = (uint)mia.DeadbandType, DeadbandValue = mia.DeadbandValue }; } var propType = propertyInfo.PropertyType; if (propType == typeof(DataValue)) { this.monitoredItems.Add(new DataValueMonitoredItem( target: this, property: propertyInfo, nodeId: ExpandedNodeId.Parse(mia.NodeId), indexRange: mia.IndexRange, attributeId: mia.AttributeId, samplingInterval: mia.SamplingInterval, filter: filter, queueSize: mia.QueueSize, discardOldest: mia.DiscardOldest)); continue; } if (propType == typeof(BaseEvent) || propType.GetTypeInfo().IsSubclassOf(typeof(BaseEvent))) { this.monitoredItems.Add(new EventMonitoredItem( target: this, property: propertyInfo, nodeId: ExpandedNodeId.Parse(mia.NodeId), indexRange: mia.IndexRange, attributeId: mia.AttributeId, samplingInterval: mia.SamplingInterval, filter: new EventFilter() { SelectClauses = EventHelper.GetSelectClauses(propType) }, queueSize: mia.QueueSize, discardOldest: mia.DiscardOldest)); continue; } if (propType == typeof(ObservableQueue <DataValue>)) { this.monitoredItems.Add(new DataValueQueueMonitoredItem( target: this, property: propertyInfo, nodeId: ExpandedNodeId.Parse(mia.NodeId), indexRange: mia.IndexRange, attributeId: mia.AttributeId, samplingInterval: mia.SamplingInterval, filter: filter, queueSize: mia.QueueSize, discardOldest: mia.DiscardOldest)); continue; } if (propType.IsConstructedGenericType && propType.GetGenericTypeDefinition() == typeof(ObservableQueue <>)) { var elemType = propType.GenericTypeArguments[0]; if (elemType == typeof(BaseEvent) || elemType.GetTypeInfo().IsSubclassOf(typeof(BaseEvent))) { this.monitoredItems.Add((MonitoredItemBase)Activator.CreateInstance( typeof(EventQueueMonitoredItem <>).MakeGenericType(elemType), this, propertyInfo, ExpandedNodeId.Parse(mia.NodeId), mia.AttributeId, mia.IndexRange, MonitoringMode.Reporting, mia.SamplingInterval, new EventFilter() { SelectClauses = EventHelper.GetSelectClauses(elemType) }, mia.QueueSize, mia.DiscardOldest) !); continue; } } this.monitoredItems.Add(new ValueMonitoredItem( target: this, property: propertyInfo, nodeId: ExpandedNodeId.Parse(mia.NodeId), indexRange: mia.IndexRange, attributeId: mia.AttributeId, samplingInterval: mia.SamplingInterval, filter: filter, queueSize: mia.QueueSize, discardOldest: mia.DiscardOldest)); } this.stateMachineCts = new CancellationTokenSource(); this.stateMachineTask = Task.Run(() => this.StateMachineAsync(this.stateMachineCts.Token)); }
private ExternalPerSaveSettings(string id, string displayName, string folderName, string subFolder, int uiVersion, char subGroupDelimiter, PropertyChangedEventHandler?onPropertyChanged, IEnumerable <SettingsPropertyGroupDefinition> settingPropertyGroups, Dictionary <string, ISettingsPresetBuilder> presets) : base(id, displayName, folderName, subFolder, uiVersion, subGroupDelimiter, onPropertyChanged, settingPropertyGroups, presets) { }
/// <summary> /// Sets the data for the specified class at the specified index. If the class has /// changed then a full look for the slot will be performed. If the new class does /// not have the provided slot then the Expando's class will change. Only case sensitive /// setter is supported in ExpandoObject. /// </summary> internal void TrySetValue(object?indexClass, int index, object?value, string name, bool ignoreCase, bool add) { ExpandoData data; object? oldValue; lock (LockObject) { data = _data; if (data.Class != indexClass || ignoreCase) { // The class has changed or we are doing a case-insensitive search, // we need to get the correct index and set the value there. If we // don't have the value then we need to promote the class - that // should only happen when we have multiple concurrent writers. index = data.Class.GetValueIndex(name, ignoreCase, this); if (index == ExpandoObject.AmbiguousMatchFound) { throw System.Linq.Expressions.Error.AmbiguousMatchInExpandoObject(name); } if (index == ExpandoObject.NoMatch) { // Before creating a new class with the new member, need to check // if there is the exact same member but is deleted. We should reuse // the class if there is such a member. int exactMatch = ignoreCase ? data.Class.GetValueIndexCaseSensitive(name) : index; if (exactMatch != ExpandoObject.NoMatch) { Debug.Assert(data[exactMatch] == Uninitialized); index = exactMatch; } else { ExpandoClass newClass = data.Class.FindNewClass(name); data = PromoteClassCore(data.Class, newClass); // After the class promotion, there must be an exact match, // so we can do case-sensitive search here. index = data.Class.GetValueIndexCaseSensitive(name); Debug.Assert(index != ExpandoObject.NoMatch); } } } // Setting an uninitialized member increases the count of available members oldValue = data[index]; if (oldValue == Uninitialized) { _count++; } else if (add) { throw System.Linq.Expressions.Error.SameKeyExistsInExpando(name); } data[index] = value; } // Notify property changed outside the lock PropertyChangedEventHandler?propertyChanged = _propertyChanged; if (propertyChanged != null && value != oldValue) { propertyChanged(this, new PropertyChangedEventArgs(data.Class.Keys[index])); } }
/// <summary> /// Notifies multiple property changed /// </summary> /// <param name="propertyChangedImplementation">The property changed implementation, this is normally a view model</param> /// <param name="propertyChanged">The property changed event handler that the propertyChangedImplementation holds</param> /// <param name="properties"></param> public static void OnMultiplePropertiesChanged(this INotifyPropertyChanged propertyChangedImplementation, PropertyChangedEventHandler?propertyChanged, params string[] properties) { propertyChanged?.RaiseForEach(propertyChangedImplementation, properties); }
public static ExternalPerSaveSettings?CreateFromXmlStream(Stream xmlStream, Func <IPropertyDefinitionBase, IRef> assignRefDelegate, PropertyChangedEventHandler?propertyChanged = null) { using var reader = XmlReader.Create(xmlStream, new XmlReaderSettings { IgnoreComments = true, IgnoreWhitespace = true }); var serializer = new XmlSerializer(typeof(SettingsXmlModel)); if (!serializer.CanDeserialize(reader) || serializer.Deserialize(reader) is not SettingsXmlModel settingsXmlModel) { return(null); } var subGroupDelimiter = settingsXmlModel.SubGroupDelimiter[0]; var props = settingsXmlModel.Groups .SelectMany(g => g.Properties.Select(p => new SettingsPropertyDefinition(SettingsUtils.GetPropertyDefinitionWrappers(p), g, assignRefDelegate(p), subGroupDelimiter))) .Concat(settingsXmlModel.Properties.Select(p => new SettingsPropertyDefinition(SettingsUtils.GetPropertyDefinitionWrappers(p), SettingsPropertyGroupDefinition.DefaultGroup, assignRefDelegate(p), subGroupDelimiter))); var propGroups = SettingsUtils.GetSettingsPropertyGroups(subGroupDelimiter, props); return(new ExternalPerSaveSettings( settingsXmlModel.Id, settingsXmlModel.DisplayName, settingsXmlModel.FolderName, settingsXmlModel.SubFolder, settingsXmlModel.UIVersion, subGroupDelimiter, propertyChanged, propGroups, new Dictionary <string, ISettingsPresetBuilder>())); }
/// <summary> /// Notifies property changed. /// </summary> /// <param name="propertyChangedImplementation">The property changed implementation, this is normally a view model </param> /// <param name="propertyChanged">The property changed event handler that the propertyChangedImplementation holds</param> /// <param name="propertyName">A nullable property name, if left empty it will pick the caller member name</param> public static void OnPropertyChanged(this INotifyPropertyChanged propertyChangedImplementation, PropertyChangedEventHandler?propertyChanged, [CallerMemberName] string propertyName = "") { propertyChanged?.Raise(propertyName, propertyChangedImplementation); }
/// <summary> /// Sets a value to a backing field if it passes a equality check and notifies property changed. /// </summary> /// <typeparam name="S">The type of the property</typeparam> /// <param name="propertyChangedImplementation">The property changed implementation, this is normally a view model</param> /// <param name="backingStore">The backing store that will hold the value of the property</param> /// <param name="value">The new value that should be set</param> /// <param name="propertyChanged">The property changed event handler that the propertyChangedImplementation holds</param> /// <param name="propertyName">A nullable property name, if left empty it will pick the caller member name</param> /// <remarks>This method does a equality check to see if the value has changed, if you need to notify property changed when the value has not changed, please use <see cref="OnPropertyChanged"/></remarks> /// <returns>A boolean value to indicate that the property changed has been invoked</returns> public static bool Set <S>(this INotifyPropertyChanged propertyChangedImplementation, ref S backingStore, S value, PropertyChangedEventHandler?propertyChanged, [CallerMemberName] string propertyName = "") { #pragma warning disable CS8604 // Disabled to be able to test RaiseAfter by calling Set, PropertyChanged should never actually be null in a Xamarin.Forms app and we do a null propagation check in RaiseAfter, so its safe to ignore return(propertyChanged.RaiseWhenSet(ref backingStore, value, propertyChangedImplementation, propertyName)); #pragma warning restore CS8604 }
public static bool RaiseSetAndObserveIfChanged <T, U, V>( this T @this, ref Arr <U> backingField, Arr <U> newValue, PropertyChangedEventHandler?propertyChangedEventHandler, ISubject <(Arr <U> Us, ObservableQualifier ObservableQualifier)> changesSubject,
public static void Raise(this PropertyChangedEventHandler?handler, object?sender, [CallerMemberName] string?memberName = null) { handler?.Invoke(sender, new PropertyChangedEventArgs(memberName)); }
/*注释:如果将更改属性名设为String.Empty, * 可以通知索引器已经更改, * 但如果填入索引器的默认名称Item,则不会发出通知, * 原因可能是索引器能够重载*/ #endregion #region 统事件版本 /// <summary> /// 调用一个<see cref="INotifyPropertyChanged.PropertyChanged"/>事件, /// 自动填入调用属性的名称 /// </summary> /// <param name="obj">要引发事件的<see cref="INotifyPropertyChanged"/>对象</param> /// <param name="delegate"><see cref="INotifyPropertyChanged.PropertyChanged"/>事件的传统委托封装</param> /// <param name="propertyName">调用属性的名称,可自动获取,如果是<see cref="string.Empty"/>,代表所有属性都已更改</param> public static void Changed(this INotifyPropertyChanged obj, PropertyChangedEventHandler? @delegate, [CallerMemberName] string propertyName = "") => @delegate?.Invoke(obj, new PropertyChangedEventArgs(propertyName));
public static void Raise(this PropertyChangedEventHandler?handler, object sender, string propertyName) { handler?.Invoke(sender, new PropertyChangedEventArgs(propertyName)); }
protected BaseFluentGlobalSettingsWrapper(object @object, string id, string displayName, string folderName, string subFolder, string format, int uiVersion, char subGroupDelimiter, PropertyChangedEventHandler?onPropertyChanged, IEnumerable <SettingsPropertyGroupDefinition> settingPropertyGroups, Dictionary <string, ISettingsPresetBuilder> presets) : base(id, displayName, folderName, subFolder, format, uiVersion, subGroupDelimiter, onPropertyChanged, settingPropertyGroups, presets) { Object = @object; }