From 6f01d44edf1ef83b288c07b1b9acc4b742617ae1 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Sat, 19 Apr 2014 11:57:24 +0100 Subject: [PATCH 01/11] First stab at a proper README --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6b129ff..2ddf678 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,57 @@ StyletIoC ========= -This project is still in development. +Introduction +------------ -[The wiki](https://github.com/canton7/Stylet/wiki/_pages) is the official (incomplete) documentation source. +Blah blah + + +Installation +------------ + +You can either grab Stylet through NuGet, or build it from source yourself. +Stylet does rely on .NET 4.5 (Visual Studio 2012 or higher). + +### NuGet + +[Stylet is available on NuGet](https://www.nuget.org/packages/Stylet). + +Either open the package console and type: + +``` +PM> Install-Package Stylet +``` + +Or right-click your project -> Manage NuGet Packages... -> Online -> search for Stylet in the top right. + +Don't forget to right-click your solution, and click "Enable NuGet package restore"! + +I also publish symbols on [SymbolSource](http://www.symbolsource.org/Public), so you can use the NuGet package but still have access to Stylet's source when debugging. If you haven't yet set up Visual Studio to use SymbolSource, do that now: + +In Visual Studio, go to Debug -> Options and Settings, and make the following changes: + + - Under General, turn **off** "Enable Just My Code" + - Under General, turn **on** "Enable source server support". You may have to Ok a security warning. + - Under Symbols, add "http://srv.symbolsource.org/pdb/Public" to the list. + +### Source + +I maintain a subtree split of just the Stylet project, [called Stylet-Core](https://github.com/canton7/Stylet-Core). +Head over there, clone/download the repo, and add the .csproj to your solution. + + +Documentation +------------- + +[The wiki is the official documentation source](https://github.com/canton7/Stylet/wiki). +There's a lot of documentation there (it was longer than my dissertation last time I checked), and it's being added to all the time. +Go check it out! + + +Contributing +------------ + +Contributions are always welcome. +If you've got a problem or a question, [raise an issue](https://github.com/canton7/Stylet/issues). +If you've got code you want to contribute, create a feature branch off the `develop` branch, add your changes there, and submit it as a pull request. \ No newline at end of file From ec3cf5e44067f553f5a6b3268bc882b540d40de2 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 14:06:40 +0100 Subject: [PATCH 02/11] PropertyChangeBase: Don't try to serialize the PropertyChangedDispatcher --- Stylet/PropertyChangedBase.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Stylet/PropertyChangedBase.cs b/Stylet/PropertyChangedBase.cs index 637ad6a..9384935 100644 --- a/Stylet/PropertyChangedBase.cs +++ b/Stylet/PropertyChangedBase.cs @@ -18,6 +18,7 @@ namespace Stylet /// /// Dispatcher to use to dispatch PropertyChanged events. Defaults to Execute.DefaultPropertyChangedDispatcher /// + [System.Xml.Serialization.XmlIgnore] public virtual Action PropertyChangedDispatcher { get { return this._propertyChangedDispatcher; } From b6fd8754fe566ca7001d566dd55a0b12adc327b2 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 14:59:25 +0100 Subject: [PATCH 03/11] Add options to ActionExtension to control the behaviour if target/action are null --- Stylet/Xaml/ActionExtension.cs | 23 +++++++++++++-- Stylet/Xaml/CommandAction.cs | 51 ++++++++++++++++++++++++++-------- Stylet/Xaml/EventAction.cs | 37 ++++++++++++++++++------ 3 files changed, 90 insertions(+), 21 deletions(-) diff --git a/Stylet/Xaml/ActionExtension.cs b/Stylet/Xaml/ActionExtension.cs index b5062cd..f6ff774 100644 --- a/Stylet/Xaml/ActionExtension.cs +++ b/Stylet/Xaml/ActionExtension.cs @@ -10,6 +10,13 @@ using System.Windows.Markup; namespace Stylet { + public enum ActionUnavailableBehaviour + { + Enable, + Disable, + Throw + }; + /// /// MarkupExtension used for binding Commands and Events to methods on the View.ActionTarget /// @@ -20,6 +27,16 @@ namespace Stylet /// public string Method { get; set; } + /// + /// Behaviour if the View.ActionTarget is nulil + /// + public ActionUnavailableBehaviour NullTarget { get; set; } + + /// + /// Behaviour if the action itself isn't found on the View.ActionTarget + /// + public ActionUnavailableBehaviour ActionNotFound { get; set; } + /// /// Create a new ActionExtension /// @@ -27,6 +44,8 @@ namespace Stylet public ActionExtension(string method) { this.Method = method; + this.NullTarget = ActionUnavailableBehaviour.Disable; + this.ActionNotFound = ActionUnavailableBehaviour.Throw; } public override object ProvideValue(IServiceProvider serviceProvider) @@ -41,13 +60,13 @@ namespace Stylet var propertyAsDependencyProperty = valueService.TargetProperty as DependencyProperty; if (propertyAsDependencyProperty != null && propertyAsDependencyProperty.PropertyType == typeof(ICommand)) { - return new CommandAction((FrameworkElement)valueService.TargetObject, this.Method); + return new CommandAction((FrameworkElement)valueService.TargetObject, this.Method, this.NullTarget, this.ActionNotFound); } var propertyAsEventInfo = valueService.TargetProperty as EventInfo; if (propertyAsEventInfo != null) { - var ec = new EventAction((FrameworkElement)valueService.TargetObject, propertyAsEventInfo, this.Method); + var ec = new EventAction((FrameworkElement)valueService.TargetObject, propertyAsEventInfo, this.Method, this.NullTarget, this.ActionNotFound); return ec.GetDelegate(); } diff --git a/Stylet/Xaml/CommandAction.cs b/Stylet/Xaml/CommandAction.cs index 4b5c885..7d1cd10 100644 --- a/Stylet/Xaml/CommandAction.cs +++ b/Stylet/Xaml/CommandAction.cs @@ -45,15 +45,20 @@ namespace Stylet private object target; + private ActionUnavailableBehaviour targetNullBehaviour; + private ActionUnavailableBehaviour actionNonExistentBehaviour; + /// /// Create a new ActionCommand /// /// View to grab the View.ActionTarget from /// Method name. the MyMethod in Buttom Command="{s:Action MyMethod}". - public CommandAction(FrameworkElement subject, string methodName) + public CommandAction(FrameworkElement subject, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour) { this.Subject = subject; this.MethodName = methodName; + this.targetNullBehaviour = targetNullBehaviour; + this.actionNonExistentBehaviour = actionNonExistentBehaviour; this.UpdateGuardAndMethod(); @@ -72,7 +77,13 @@ namespace Stylet MethodInfo targetMethodInfo = null; this.guardPropertyGetter = null; - if (newTarget != null) + if (newTarget == null) + { + // If it's Enable or Disable we don't do anything - CanExecute will handle this + if (this.targetNullBehaviour == ActionUnavailableBehaviour.Throw) + throw new Exception(String.Format("Method {0} has a target set which is null", this.MethodName)); + } + else { var newTargetType = newTarget.GetType(); @@ -86,11 +97,16 @@ namespace Stylet targetMethodInfo = newTargetType.GetMethod(this.MethodName); if (targetMethodInfo == null) - throw new ArgumentException(String.Format("Unable to find method {0} on {1}", this.MethodName, newTargetType.Name)); - - var methodParameters = targetMethodInfo.GetParameters(); - if (methodParameters.Length > 1) - throw new ArgumentException(String.Format("Method {0} on {1} must have zero or one parameters", this.MethodName, newTargetType.Name)); + { + if (this.actionNonExistentBehaviour == ActionUnavailableBehaviour.Throw) + throw new ArgumentException(String.Format("Unable to find method {0} on {1}", this.MethodName, newTargetType.Name)); + } + else + { + var methodParameters = targetMethodInfo.GetParameters(); + if (methodParameters.Length > 1) + throw new ArgumentException(String.Format("Method {0} on {1} must have zero or one parameters", this.MethodName, newTargetType.Name)); + } } var oldTarget = this.target as INotifyPropertyChanged; @@ -125,9 +141,21 @@ namespace Stylet public bool CanExecute(object parameter) { - if (this.target == null) + // It's enabled only if both the targetNull and actionNonExistent tests pass + + // Throw is handled when the target is set + if (this.target == null && this.targetNullBehaviour == ActionUnavailableBehaviour.Disable) return false; + // Throw is handled when the target is set + if (this.targetMethodInfo == null) + { + if (this.actionNonExistentBehaviour == ActionUnavailableBehaviour.Disable) + return false; + else + return true; + } + if (this.guardPropertyGetter == null) return true; @@ -138,10 +166,11 @@ namespace Stylet public void Execute(object parameter) { - // This is not going to be called very often, so don't bother to generate a delegate, in the way that we do for the method guard - if (this.target == null) - throw new ArgumentException("Target not set"); + // Any throwing would have been handled prior to this + if (this.target == null || this.targetMethodInfo == null) + return; + // This is not going to be called very often, so don't bother to generate a delegate, in the way that we do for the method guard var parameters = this.targetMethodInfo.GetParameters().Length == 1 ? new[] { parameter } : null; this.targetMethodInfo.Invoke(this.target, parameters); } diff --git a/Stylet/Xaml/EventAction.cs b/Stylet/Xaml/EventAction.cs index ddb80e4..137aa1e 100644 --- a/Stylet/Xaml/EventAction.cs +++ b/Stylet/Xaml/EventAction.cs @@ -36,17 +36,27 @@ namespace Stylet private object target; + private ActionUnavailableBehaviour nullTargetBehaviour; + private ActionUnavailableBehaviour actionNonExistentBehaviour; + /// /// Create a new EventAction /// /// View whose View.ActionTarget we watch /// Property on the WPF element we're returning a delegate for /// The MyMethod in {s:Action MyMethod}, this is what we call when the event's fired - public EventAction(FrameworkElement subject, EventInfo targetProperty, string methodName) + public EventAction(FrameworkElement subject, EventInfo targetProperty, string methodName, ActionUnavailableBehaviour nullTargetBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour) { + if (nullTargetBehaviour == ActionUnavailableBehaviour.Disable) + throw new ArgumentException("Setting NullTarget = Disable is unsupported when used on an Event"); + if (actionNonExistentBehaviour == ActionUnavailableBehaviour.Disable) + throw new ArgumentException("Setting ActionNotFound = Disable is unsupported when used on an Event"); + this.subject = subject; this.targetProperty = targetProperty; this.methodName = methodName; + this.nullTargetBehaviour = nullTargetBehaviour; + this.actionNonExistentBehaviour = actionNonExistentBehaviour; // Observe the View.ActionTarget for changes, and re-bind the guard property and MethodInfo if it changes DependencyPropertyDescriptor.FromProperty(View.ActionTargetProperty, typeof(View)).AddValueChanged(this.subject, (o, e) => this.UpdateMethod()); @@ -57,16 +67,26 @@ namespace Stylet var newTarget = View.GetActionTarget(this.subject); MethodInfo targetMethodInfo = null; - if (newTarget != null) + if (newTarget == null) + { + if (this.nullTargetBehaviour == ActionUnavailableBehaviour.Throw) + throw new Exception(String.Format("Method {0} has a target set which is null", this.methodName)); + } + else { var newTargetType = newTarget.GetType(); targetMethodInfo = newTargetType.GetMethod(this.methodName); if (targetMethodInfo == null) - throw new ArgumentException(String.Format("Unable to find method {0} on {1}", this.methodName, newTargetType.Name)); - - var methodParameters = targetMethodInfo.GetParameters(); - if (methodParameters.Length > 1 || (methodParameters.Length == 1 && !methodParameters[0].ParameterType.IsAssignableFrom(typeof(RoutedEventArgs)))) - throw new ArgumentException(String.Format("Method {0} on {1} must have zero parameters, or a single parameter accepting a RoutedEventArgs", this.methodName, newTargetType.Name)); + { + if (this.actionNonExistentBehaviour == ActionUnavailableBehaviour.Throw) + throw new ArgumentException(String.Format("Unable to find method {0} on {1}", this.methodName, newTargetType.Name)); + } + else + { + var methodParameters = targetMethodInfo.GetParameters(); + if (methodParameters.Length > 1 || (methodParameters.Length == 1 && !methodParameters[0].ParameterType.IsAssignableFrom(typeof(RoutedEventArgs)))) + throw new ArgumentException(String.Format("Method {0} on {1} must have zero parameters, or a single parameter accepting a RoutedEventArgs", this.methodName, newTargetType.Name)); + } } this.target = newTarget; @@ -86,7 +106,8 @@ namespace Stylet private void InvokeCommand(object sender, RoutedEventArgs e) { - if (this.target == null) + // Any throwing will have been handled above + if (this.target == null || this.targetMethodInfo == null) return; var parameters = this.targetMethodInfo.GetParameters().Length == 1 ? new object[] { e } : null; From 1512ea56a625167103a3a4d4342d18b8035cc4da Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 15:34:02 +0100 Subject: [PATCH 04/11] Update Actions to support things like Hyperlinks --- Stylet/Xaml/ActionExtension.cs | 12 +++++------- Stylet/Xaml/CommandAction.cs | 4 ++-- Stylet/Xaml/EventAction.cs | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Stylet/Xaml/ActionExtension.cs b/Stylet/Xaml/ActionExtension.cs index f6ff774..87bfdd6 100644 --- a/Stylet/Xaml/ActionExtension.cs +++ b/Stylet/Xaml/ActionExtension.cs @@ -30,12 +30,12 @@ namespace Stylet /// /// Behaviour if the View.ActionTarget is nulil /// - public ActionUnavailableBehaviour NullTarget { get; set; } + public ActionUnavailableBehaviour? NullTarget { get; set; } /// /// Behaviour if the action itself isn't found on the View.ActionTarget /// - public ActionUnavailableBehaviour ActionNotFound { get; set; } + public ActionUnavailableBehaviour? ActionNotFound { get; set; } /// /// Create a new ActionExtension @@ -44,8 +44,6 @@ namespace Stylet public ActionExtension(string method) { this.Method = method; - this.NullTarget = ActionUnavailableBehaviour.Disable; - this.ActionNotFound = ActionUnavailableBehaviour.Throw; } public override object ProvideValue(IServiceProvider serviceProvider) @@ -54,19 +52,19 @@ namespace Stylet // Seems this is the case when we're in a template. We'll get called again properly in a second. // http://social.msdn.microsoft.com/Forums/vstudio/en-US/a9ead3d5-a4e4-4f9c-b507-b7a7d530c6a9/gaining-access-to-target-object-instead-of-shareddp-in-custom-markupextensions-providevalue-method?forum=wpf - if (!(valueService.TargetObject is FrameworkElement)) + if (!(valueService.TargetObject is DependencyObject)) return this; var propertyAsDependencyProperty = valueService.TargetProperty as DependencyProperty; if (propertyAsDependencyProperty != null && propertyAsDependencyProperty.PropertyType == typeof(ICommand)) { - return new CommandAction((FrameworkElement)valueService.TargetObject, this.Method, this.NullTarget, this.ActionNotFound); + return new CommandAction((DependencyObject)valueService.TargetObject, this.Method, this.NullTarget.GetValueOrDefault(ActionUnavailableBehaviour.Disable), this.ActionNotFound.GetValueOrDefault(ActionUnavailableBehaviour.Throw)); } var propertyAsEventInfo = valueService.TargetProperty as EventInfo; if (propertyAsEventInfo != null) { - var ec = new EventAction((FrameworkElement)valueService.TargetObject, propertyAsEventInfo, this.Method, this.NullTarget, this.ActionNotFound); + var ec = new EventAction((DependencyObject)valueService.TargetObject, propertyAsEventInfo, this.Method, this.NullTarget.GetValueOrDefault(ActionUnavailableBehaviour.Throw), this.ActionNotFound.GetValueOrDefault(ActionUnavailableBehaviour.Throw)); return ec.GetDelegate(); } diff --git a/Stylet/Xaml/CommandAction.cs b/Stylet/Xaml/CommandAction.cs index 7d1cd10..b9153a5 100644 --- a/Stylet/Xaml/CommandAction.cs +++ b/Stylet/Xaml/CommandAction.cs @@ -26,7 +26,7 @@ namespace Stylet /// /// View to grab the View.ActionTarget from /// - public FrameworkElement Subject { get; private set; } + public DependencyObject Subject { get; private set; } /// /// Method name. E.g. if someone's gone Buttom Command="{s:Action MyMethod}", this is MyMethod. @@ -53,7 +53,7 @@ namespace Stylet /// /// View to grab the View.ActionTarget from /// Method name. the MyMethod in Buttom Command="{s:Action MyMethod}". - public CommandAction(FrameworkElement subject, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour) + public CommandAction(DependencyObject subject, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour) { this.Subject = subject; this.MethodName = methodName; diff --git a/Stylet/Xaml/EventAction.cs b/Stylet/Xaml/EventAction.cs index 137aa1e..7a28de3 100644 --- a/Stylet/Xaml/EventAction.cs +++ b/Stylet/Xaml/EventAction.cs @@ -17,7 +17,7 @@ namespace Stylet /// /// View whose View.ActionTarget we watch /// - private FrameworkElement subject; + private DependencyObject subject; /// /// Property on the WPF element we're returning a delegate for @@ -45,7 +45,7 @@ namespace Stylet /// View whose View.ActionTarget we watch /// Property on the WPF element we're returning a delegate for /// The MyMethod in {s:Action MyMethod}, this is what we call when the event's fired - public EventAction(FrameworkElement subject, EventInfo targetProperty, string methodName, ActionUnavailableBehaviour nullTargetBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour) + public EventAction(DependencyObject subject, EventInfo targetProperty, string methodName, ActionUnavailableBehaviour nullTargetBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour) { if (nullTargetBehaviour == ActionUnavailableBehaviour.Disable) throw new ArgumentException("Setting NullTarget = Disable is unsupported when used on an Event"); From c8e5ef37155bbcaca6077d4ae82caceb48112e9a Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 17:32:57 +0100 Subject: [PATCH 05/11] We can't use NotifyCollectionChangedAction.Add or Remove with a list of items, apparently --- Stylet/BindableCollection.cs | 6 ++++-- StyletUnitTests/BindableCollectionTests.cs | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Stylet/BindableCollection.cs b/Stylet/BindableCollection.cs index 72f4295..4ba09ea 100644 --- a/Stylet/BindableCollection.cs +++ b/Stylet/BindableCollection.cs @@ -82,7 +82,8 @@ namespace Stylet this.isNotifying = previousNotificationSetting; this.OnPropertyChanged(new PropertyChangedEventArgs("Count")); this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); - this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items.ToList())); + // Can't add with a range, or it throws an exception + this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } /// @@ -104,7 +105,8 @@ namespace Stylet this.isNotifying = previousNotificationSetting; this.OnPropertyChanged(new PropertyChangedEventArgs("Count")); this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); - this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, items.ToList())); + // Can't remove with a range, or it throws an exception + this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } /// diff --git a/StyletUnitTests/BindableCollectionTests.cs b/StyletUnitTests/BindableCollectionTests.cs index f3b0ca7..b603c91 100644 --- a/StyletUnitTests/BindableCollectionTests.cs +++ b/StyletUnitTests/BindableCollectionTests.cs @@ -66,8 +66,7 @@ namespace StyletUnitTests Assert.AreEqual(1, changedEvents.Count); var changedEvent = changedEvents[0]; - Assert.AreEqual(NotifyCollectionChangedAction.Add, changedEvent.Action); - Assert.AreEqual(elementsToAdd, changedEvent.NewItems); + Assert.AreEqual(NotifyCollectionChangedAction.Reset, changedEvent.Action); } [Test] @@ -97,8 +96,7 @@ namespace StyletUnitTests Assert.AreEqual(1, changedEvents.Count); var changedEvent = changedEvents[0]; - Assert.AreEqual(NotifyCollectionChangedAction.Add, changedEvent.Action); - Assert.AreEqual(itemsToRemove, changedEvent.NewItems); + Assert.AreEqual(NotifyCollectionChangedAction.Reset, changedEvent.Action); } [Test] From afe8b9c20fa475ee776eb61db8b69c19102c85ab Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 17:44:52 +0100 Subject: [PATCH 06/11] Remove tests which were no longer relevant, since Bind/BindWeak refactor --- .../PropertyChangedExtensionsTests.cs | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/StyletUnitTests/PropertyChangedExtensionsTests.cs b/StyletUnitTests/PropertyChangedExtensionsTests.cs index a0f629f..865a258 100644 --- a/StyletUnitTests/PropertyChangedExtensionsTests.cs +++ b/StyletUnitTests/PropertyChangedExtensionsTests.cs @@ -84,22 +84,6 @@ namespace StyletUnitTests Assert.AreEqual("bar", newVal); } - [Test] - public void StrongBindingRetainsBindingClass() - { - var binding = new BindingClass(); - - // Means of determining whether the class has been disposed - var weakBinding = new WeakReference(binding); - - var notifying = new NotifyingClass(); - binding.BindStrong(notifying); - - binding = null; - GC.Collect(); - Assert.IsTrue(weakBinding.TryGetTarget(out binding)); - } - [Test] public void StrongBindingDoesNotRetainNotifier() { @@ -180,23 +164,6 @@ namespace StyletUnitTests Assert.IsFalse(weakBinding.TryGetTarget(out binding)); } - [Test] - public void WeakBindingRetainsClassIfIPropertyChangedBindingRetained() - { - var binding = new BindingClass(); - - // Means of determining whether the class has been disposed - var weakBinding = new WeakReference(binding); - - var notifying = new NotifyingClass(); - // Retain this - var binder = binding.BindWeak(notifying); - - binding = null; - GC.Collect(); - Assert.IsTrue(weakBinding.TryGetTarget(out binding)); - } - [Test] public void WeakBindingDoesNotRetainNotifier() { From f7210b8aa9f95baf14fc6f3f1f247246faa40226 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 17:45:26 +0100 Subject: [PATCH 07/11] Rename IPropertyChangedBinding -> IEventBinding --- Stylet/PropertyChangedExtensions.cs | 6 +++--- Stylet/Screen.cs | 2 +- Stylet/WeakEventManager.cs | 14 +++++++------- StyletUnitTests/PropertyChangedExtensionsTests.cs | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Stylet/PropertyChangedExtensions.cs b/Stylet/PropertyChangedExtensions.cs index 9f7a0c2..56c9f17 100644 --- a/Stylet/PropertyChangedExtensions.cs +++ b/Stylet/PropertyChangedExtensions.cs @@ -12,14 +12,14 @@ namespace Stylet /// /// A binding to a PropertyChanged event, which can be used to unbind the binding /// - public interface IPropertyChangedBinding + public interface IEventBinding { void Unbind(); } public static class PropertyChangedExtensions { - internal class StrongPropertyChangedBinding : IPropertyChangedBinding + internal class StrongPropertyChangedBinding : IEventBinding { private WeakReference inpc; private PropertyChangedEventHandler handler; @@ -48,7 +48,7 @@ namespace Stylet /// MemberExpression selecting the property to observe for changes (e.g x => x.PropertyName) /// Handler called whenever that property changed /// Something which can be used to undo the binding. You can discard it if you want - public static IPropertyChangedBinding Bind(this TBindTo target, Expression> targetSelector, Action handler) where TBindTo : class, INotifyPropertyChanged + public static IEventBinding Bind(this TBindTo target, Expression> targetSelector, Action handler) where TBindTo : class, INotifyPropertyChanged { var propertyName = targetSelector.NameForProperty(); var propertyAccess = targetSelector.Compile(); diff --git a/Stylet/Screen.cs b/Stylet/Screen.cs index 52febf7..f7605c7 100644 --- a/Stylet/Screen.cs +++ b/Stylet/Screen.cs @@ -32,7 +32,7 @@ namespace Stylet /// Expression for selecting the property to observe, e.g. x => x.PropertyName /// Handler to be called when that property changes /// A resource which can be used to undo the binding - protected IPropertyChangedBinding BindWeak(TSource source, Expression> selector, Action handler) + protected IEventBinding BindWeak(TSource source, Expression> selector, Action handler) where TSource : class, INotifyPropertyChanged { return this.weakEventManager.BindWeak(source, selector, handler); diff --git a/Stylet/WeakEventManager.cs b/Stylet/WeakEventManager.cs index 0fb3293..dd6c390 100644 --- a/Stylet/WeakEventManager.cs +++ b/Stylet/WeakEventManager.cs @@ -10,20 +10,20 @@ namespace Stylet { public interface IWeakEventManager { - IPropertyChangedBinding BindWeak(TSource source, Expression> selector, Action handler) + IEventBinding BindWeak(TSource source, Expression> selector, Action handler) where TSource : class, INotifyPropertyChanged; } - internal class WeakPropertyBinding : IPropertyChangedBinding where TSource : class, INotifyPropertyChanged + internal class WeakPropertyBinding : IEventBinding where TSource : class, INotifyPropertyChanged { // Make sure we don't end up retaining the source private readonly WeakReference source; private readonly string propertyName; private readonly Func valueSelector; private readonly Action handler; - private readonly Action remover; + private readonly Action remover; - public WeakPropertyBinding(TSource source, Expression> selector, Action handler, Action remover) + public WeakPropertyBinding(TSource source, Expression> selector, Action handler, Action remover) { this.source = new WeakReference(source); this.propertyName = selector.NameForProperty(); @@ -55,9 +55,9 @@ namespace Stylet public class WeakEventManager : IWeakEventManager { private object bindingsLock = new object(); - private List bindings = new List(); + private List bindings = new List(); - public IPropertyChangedBinding BindWeak(TSource source, Expression> selector, Action handler) + public IEventBinding BindWeak(TSource source, Expression> selector, Action handler) where TSource : class, INotifyPropertyChanged { // So, the handler's target might point to the class that owns us, or it might point to a compiler-generated class @@ -82,7 +82,7 @@ namespace Stylet return binding; } - internal void Remove(IPropertyChangedBinding binding) + internal void Remove(IEventBinding binding) { lock (this.bindingsLock) { diff --git a/StyletUnitTests/PropertyChangedExtensionsTests.cs b/StyletUnitTests/PropertyChangedExtensionsTests.cs index 865a258..85413cb 100644 --- a/StyletUnitTests/PropertyChangedExtensionsTests.cs +++ b/StyletUnitTests/PropertyChangedExtensionsTests.cs @@ -38,13 +38,13 @@ namespace StyletUnitTests public string LastFoo; private WeakEventManager weakEventManager = new WeakEventManager(); - public IPropertyChangedBinding BindStrong(NotifyingClass notifying) + public IEventBinding BindStrong(NotifyingClass notifying) { // Must make sure the compiler doesn't generate an inner class for this, otherwise we're not testing the right thing return notifying.Bind(x => x.Foo, x => this.LastFoo = x); } - public IPropertyChangedBinding BindWeak(NotifyingClass notifying) + public IEventBinding BindWeak(NotifyingClass notifying) { return this.weakEventManager.BindWeak(notifying, x => x.Foo, x => this.LastFoo = x); } From 580ba7f865ae09eeaf32d2aff6ab661e1072d971 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 17:47:42 +0100 Subject: [PATCH 08/11] Change stylet namespace to https://github.com/canton7/Stylet --- Samples/Stylet.Samples.Hello/ShellView.xaml | 2 +- Samples/Stylet.Samples.HelloDialog/Dialog1View.xaml | 2 +- Samples/Stylet.Samples.HelloDialog/ShellView.xaml | 2 +- Samples/Stylet.Samples.MasterDetail/ShellView.xaml | 2 +- .../Stylet.Samples.RedditBrowser/Pages/PostCommentsView.xaml | 2 +- Samples/Stylet.Samples.RedditBrowser/Pages/PostsView.xaml | 2 +- Samples/Stylet.Samples.RedditBrowser/Pages/ShellView.xaml | 2 +- Samples/Stylet.Samples.RedditBrowser/Pages/SubredditView.xaml | 2 +- Samples/Stylet.Samples.RedditBrowser/Pages/TaskbarView.xaml | 2 +- Samples/Stylet.Samples.TabNavigation/ShellView.xaml | 2 +- Stylet/Properties/AssemblyInfo.cs | 2 +- StyletIntegrationTests/Actions/ActionsView.xaml | 2 +- StyletIntegrationTests/ShellView.xaml | 2 +- .../ShowDialogAndDialogResult/DialogView.xaml | 2 +- StyletIntegrationTests/WindowDisplayNameBound/WindowView.xaml | 2 +- StyletIntegrationTests/WindowGuardClose/WindowView.xaml | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Samples/Stylet.Samples.Hello/ShellView.xaml b/Samples/Stylet.Samples.Hello/ShellView.xaml index e944ad2..5823506 100644 --- a/Samples/Stylet.Samples.Hello/ShellView.xaml +++ b/Samples/Stylet.Samples.Hello/ShellView.xaml @@ -1,7 +1,7 @@  diff --git a/Samples/Stylet.Samples.HelloDialog/Dialog1View.xaml b/Samples/Stylet.Samples.HelloDialog/Dialog1View.xaml index 713f4d2..0db8334 100644 --- a/Samples/Stylet.Samples.HelloDialog/Dialog1View.xaml +++ b/Samples/Stylet.Samples.HelloDialog/Dialog1View.xaml @@ -1,7 +1,7 @@  diff --git a/Samples/Stylet.Samples.HelloDialog/ShellView.xaml b/Samples/Stylet.Samples.HelloDialog/ShellView.xaml index 8adad9f..78e6434 100644 --- a/Samples/Stylet.Samples.HelloDialog/ShellView.xaml +++ b/Samples/Stylet.Samples.HelloDialog/ShellView.xaml @@ -1,7 +1,7 @@  diff --git a/Samples/Stylet.Samples.MasterDetail/ShellView.xaml b/Samples/Stylet.Samples.MasterDetail/ShellView.xaml index c4f1075..a584448 100644 --- a/Samples/Stylet.Samples.MasterDetail/ShellView.xaml +++ b/Samples/Stylet.Samples.MasterDetail/ShellView.xaml @@ -1,7 +1,7 @@  diff --git a/Samples/Stylet.Samples.RedditBrowser/Pages/PostCommentsView.xaml b/Samples/Stylet.Samples.RedditBrowser/Pages/PostCommentsView.xaml index 5f99960..1d64272 100644 --- a/Samples/Stylet.Samples.RedditBrowser/Pages/PostCommentsView.xaml +++ b/Samples/Stylet.Samples.RedditBrowser/Pages/PostCommentsView.xaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:redditapi="clr-namespace:Stylet.Samples.RedditBrowser.RedditApi" - xmlns:s="http://github.com/canton7/Stylet" + xmlns:s="https://github.com/canton7/Stylet" xmlns:uc="clr-namespace:Stylet.Samples.RedditBrowser.UserControls" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> diff --git a/Samples/Stylet.Samples.RedditBrowser/Pages/PostsView.xaml b/Samples/Stylet.Samples.RedditBrowser/Pages/PostsView.xaml index 9b49bad..7e45eef 100644 --- a/Samples/Stylet.Samples.RedditBrowser/Pages/PostsView.xaml +++ b/Samples/Stylet.Samples.RedditBrowser/Pages/PostsView.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:s="http://github.com/canton7/Stylet" + xmlns:s="https://github.com/canton7/Stylet" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> diff --git a/Samples/Stylet.Samples.RedditBrowser/Pages/ShellView.xaml b/Samples/Stylet.Samples.RedditBrowser/Pages/ShellView.xaml index 996c9fe..278a753 100644 --- a/Samples/Stylet.Samples.RedditBrowser/Pages/ShellView.xaml +++ b/Samples/Stylet.Samples.RedditBrowser/Pages/ShellView.xaml @@ -1,7 +1,7 @@  diff --git a/Samples/Stylet.Samples.RedditBrowser/Pages/SubredditView.xaml b/Samples/Stylet.Samples.RedditBrowser/Pages/SubredditView.xaml index da432ac..fdd611d 100644 --- a/Samples/Stylet.Samples.RedditBrowser/Pages/SubredditView.xaml +++ b/Samples/Stylet.Samples.RedditBrowser/Pages/SubredditView.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:s="http://github.com/canton7/Stylet" + xmlns:s="https://github.com/canton7/Stylet" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> diff --git a/Samples/Stylet.Samples.RedditBrowser/Pages/TaskbarView.xaml b/Samples/Stylet.Samples.RedditBrowser/Pages/TaskbarView.xaml index d2b5cf9..53c78ed 100644 --- a/Samples/Stylet.Samples.RedditBrowser/Pages/TaskbarView.xaml +++ b/Samples/Stylet.Samples.RedditBrowser/Pages/TaskbarView.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:s="http://github.com/canton7/Stylet" + xmlns:s="https://github.com/canton7/Stylet" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> diff --git a/Samples/Stylet.Samples.TabNavigation/ShellView.xaml b/Samples/Stylet.Samples.TabNavigation/ShellView.xaml index 63cf5af..748926b 100644 --- a/Samples/Stylet.Samples.TabNavigation/ShellView.xaml +++ b/Samples/Stylet.Samples.TabNavigation/ShellView.xaml @@ -1,7 +1,7 @@  diff --git a/Stylet/Properties/AssemblyInfo.cs b/Stylet/Properties/AssemblyInfo.cs index 1890254..0bf90fb 100644 --- a/Stylet/Properties/AssemblyInfo.cs +++ b/Stylet/Properties/AssemblyInfo.cs @@ -23,7 +23,7 @@ using System.Windows.Markup; // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("a557a739-6b61-44d2-a431-889bc11aac9e")] -[assembly: XmlnsDefinition("http://github.com/canton7/Stylet", "Stylet")] +[assembly: XmlnsDefinition("https://github.com/canton7/Stylet", "Stylet")] // Version information for an assembly consists of the following four values: // diff --git a/StyletIntegrationTests/Actions/ActionsView.xaml b/StyletIntegrationTests/Actions/ActionsView.xaml index 611bb28..e52ef56 100644 --- a/StyletIntegrationTests/Actions/ActionsView.xaml +++ b/StyletIntegrationTests/Actions/ActionsView.xaml @@ -1,7 +1,7 @@  diff --git a/StyletIntegrationTests/ShellView.xaml b/StyletIntegrationTests/ShellView.xaml index 77ba1ea..c26a78b 100644 --- a/StyletIntegrationTests/ShellView.xaml +++ b/StyletIntegrationTests/ShellView.xaml @@ -1,7 +1,7 @@  diff --git a/StyletIntegrationTests/ShowDialogAndDialogResult/DialogView.xaml b/StyletIntegrationTests/ShowDialogAndDialogResult/DialogView.xaml index d71f2c6..2e167af 100644 --- a/StyletIntegrationTests/ShowDialogAndDialogResult/DialogView.xaml +++ b/StyletIntegrationTests/ShowDialogAndDialogResult/DialogView.xaml @@ -1,7 +1,7 @@  Choose the desired DialogResult, then close the dialog. diff --git a/StyletIntegrationTests/WindowDisplayNameBound/WindowView.xaml b/StyletIntegrationTests/WindowDisplayNameBound/WindowView.xaml index a8adc7b..f0836f8 100644 --- a/StyletIntegrationTests/WindowDisplayNameBound/WindowView.xaml +++ b/StyletIntegrationTests/WindowDisplayNameBound/WindowView.xaml @@ -1,7 +1,7 @@  Press the button, and verify that the count in the window title increases. When you are done, close the window. diff --git a/StyletIntegrationTests/WindowGuardClose/WindowView.xaml b/StyletIntegrationTests/WindowGuardClose/WindowView.xaml index 3305fe5..6496f2e 100644 --- a/StyletIntegrationTests/WindowGuardClose/WindowView.xaml +++ b/StyletIntegrationTests/WindowGuardClose/WindowView.xaml @@ -1,7 +1,7 @@  Leave the checkbox unchecked, then close the window using the red X at the top. It should not close. From 242690e95bfa9ab0e5c540ba196e8161cebba874 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 20:25:37 +0100 Subject: [PATCH 09/11] Re-instate AssemblyVersion and AssemblyFileVersion --- Stylet/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Stylet/Properties/AssemblyInfo.cs b/Stylet/Properties/AssemblyInfo.cs index 0bf90fb..b9bf99d 100644 --- a/Stylet/Properties/AssemblyInfo.cs +++ b/Stylet/Properties/AssemblyInfo.cs @@ -35,5 +35,5 @@ using System.Windows.Markup; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -//[assembly: AssemblyVersion("1.0.0.0")] -//[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.3.0")] +[assembly: AssemblyFileVersion("0.9.3.0")] From dcd90f87da31f53927ea3e8fc4abcb36c1e5cdf9 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 20:29:04 +0100 Subject: [PATCH 10/11] Update changelog --- CHANGELOG.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8b22a6e..bf7ad5d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,14 @@ Stylet Changelog ================ +v0.9.4 +------ + + - Fix BindableCollection issues + - ActionExtension has configurable behaviour if target/action are null/not found + - ActionExtension works with things like Hyperlinks + - Misc tweaks and fixes + v0.9.3 ------ From 6f7e2d4b5f927b925ad959140f4a9c3f6cfd87a0 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Wed, 23 Apr 2014 20:29:33 +0100 Subject: [PATCH 11/11] Bump version --- NuGet/Stylet.nuspec | 2 +- Stylet/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGet/Stylet.nuspec b/NuGet/Stylet.nuspec index 03cd843..cc3ecc7 100644 --- a/NuGet/Stylet.nuspec +++ b/NuGet/Stylet.nuspec @@ -2,7 +2,7 @@ Stylet - 0.9.3 + 0.9.4 Stylet Antony Male Antony Male diff --git a/Stylet/Properties/AssemblyInfo.cs b/Stylet/Properties/AssemblyInfo.cs index b9bf99d..e00489c 100644 --- a/Stylet/Properties/AssemblyInfo.cs +++ b/Stylet/Properties/AssemblyInfo.cs @@ -35,5 +35,5 @@ using System.Windows.Markup; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.3.0")] -[assembly: AssemblyFileVersion("0.9.3.0")] +[assembly: AssemblyVersion("0.9.4.0")] +[assembly: AssemblyFileVersion("0.9.4.0")]