Add a load of missing XML documentation

This commit is contained in:
Antony Male 2014-05-26 18:48:44 +01:00
parent a914d58668
commit 7203b02cdf
31 changed files with 527 additions and 44 deletions

View File

@ -58,15 +58,31 @@ namespace Stylet
/// </summary> /// </summary>
private bool isNotifying = true; private bool isNotifying = true;
/// <summary>
/// Create a new empty BindableCollection
/// </summary>
public BindableCollection() : base() { } public BindableCollection() : base() { }
/// <summary>
/// Create a new BindableCollection with the given members
/// </summary>
/// <param name="collection">The collection from which the elements are copied</param>
public BindableCollection(IEnumerable<T> collection) : base(collection) { } public BindableCollection(IEnumerable<T> collection) : base(collection) { }
/// <summary>
/// Raises the System.Collections.ObjectModel.ObservableCollection{T}.PropertyChanged event with the provided arguments.
/// </summary>
/// <param name="e">Arguments of the event being raised.</param>
protected override void OnPropertyChanged(PropertyChangedEventArgs e) protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{ {
if (this.isNotifying) if (this.isNotifying)
this.PropertyChangedDispatcher(() => base.OnPropertyChanged(e)); this.PropertyChangedDispatcher(() => base.OnPropertyChanged(e));
} }
/// <summary>
/// Raises the System.Collections.ObjectModel.ObservableCollection{T}.CollectionChanged event with the provided arguments.
/// </summary>
/// <param name="e">Arguments of the event being raised.</param>
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{ {
if (this.isNotifying) if (this.isNotifying)

View File

@ -87,6 +87,9 @@ namespace Stylet
IoC.Get<IWindowManager>().ShowWindow(IoC.Get<TRootViewModel>()); IoC.Get<IWindowManager>().ShowWindow(IoC.Get<TRootViewModel>());
} }
/// <summary>
/// Add any application resources to the application. Override to add your own, or to avoid Stylet's default resources from being added
/// </summary>
protected virtual void ConfigureResources() protected virtual void ConfigureResources()
{ {
if (this.Application == null) if (this.Application == null)

View File

@ -10,6 +10,9 @@ namespace Stylet
{ {
public partial class Conductor<T> public partial class Conductor<T>
{ {
/// <summary>
/// Contains specific Conductor{T} collection types
/// </summary>
public partial class Collection public partial class Collection
{ {
/// <summary> /// <summary>
@ -18,11 +21,18 @@ namespace Stylet
public class AllActive : ConductorBase<T> public class AllActive : ConductorBase<T>
{ {
private BindableCollection<T> items = new BindableCollection<T>(); private BindableCollection<T> items = new BindableCollection<T>();
/// <summary>
/// All items associated with this conductor
/// </summary>
public IObservableCollection<T> Items public IObservableCollection<T> Items
{ {
get { return this.items; } get { return this.items; }
} }
/// <summary>
/// Creates a new Conductor{T}.Collection.AllActive
/// </summary>
public AllActive() public AllActive()
{ {
this.items.CollectionChanged += (o, e) => this.items.CollectionChanged += (o, e) =>
@ -49,6 +59,10 @@ namespace Stylet
}; };
} }
/// <summary>
/// Active all items in a given collection if appropriate, and set the parent of all items to this
/// </summary>
/// <param name="items">Items to manipulate</param>
protected virtual void ActivateAndSetParent(IEnumerable items) protected virtual void ActivateAndSetParent(IEnumerable items)
{ {
this.SetParent(items); this.SetParent(items);
@ -61,6 +75,9 @@ namespace Stylet
} }
} }
/// <summary>
/// Activates all items whenever this conductor is activated
/// </summary>
protected override void OnActivate() protected override void OnActivate()
{ {
foreach (var item in this.items.OfType<IActivate>()) foreach (var item in this.items.OfType<IActivate>())
@ -69,6 +86,9 @@ namespace Stylet
} }
} }
/// <summary>
/// Deactivates all items whenever this conductor is deactivated
/// </summary>
protected override void OnDeactivate() protected override void OnDeactivate()
{ {
foreach (var item in this.items.OfType<IDeactivate>()) foreach (var item in this.items.OfType<IDeactivate>())
@ -77,6 +97,9 @@ namespace Stylet
} }
} }
/// <summary>
/// Close, and clean up, all items when this conductor is closed
/// </summary>
protected override void OnClose() protected override void OnClose()
{ {
// We've already been deactivated by this point // We've already been deactivated by this point
@ -142,6 +165,10 @@ namespace Stylet
return this.items; return this.items;
} }
/// <summary>
/// Ensure an item is ready to be activated, by adding it to the items collection, as well as setting it up
/// </summary>
/// <param name="newItem">Item to ensure</param>
protected override void EnsureItem(T newItem) protected override void EnsureItem(T newItem)
{ {
if (!this.items.Contains(newItem)) if (!this.items.Contains(newItem))

View File

@ -12,6 +12,10 @@ namespace Stylet
/// <typeparam name="T">Type of item to be conducted</typeparam> /// <typeparam name="T">Type of item to be conducted</typeparam>
public abstract class ConductorBase<T> : Screen, IConductor<T>, IParent<T>, IChildDelegate where T : class public abstract class ConductorBase<T> : Screen, IConductor<T>, IParent<T>, IChildDelegate where T : class
{ {
/// <summary>
/// Retrieves the Item or Items associated with this Conductor
/// </summary>
/// <returns>Item or Items associated with this Conductor</returns>
public abstract IEnumerable<T> GetChildren(); public abstract IEnumerable<T> GetChildren();
/// <summary> /// <summary>
@ -27,7 +31,7 @@ namespace Stylet
public abstract void DeactivateItem(T item); public abstract void DeactivateItem(T item);
/// <summary> /// <summary>
/// Deactivate the given item /// Close the given item
/// </summary> /// </summary>
/// <param name="item">Item to deactivate</param> /// <param name="item">Item to deactivate</param>
public abstract void CloseItem(T item); public abstract void CloseItem(T item);

View File

@ -97,6 +97,9 @@ namespace Stylet
return this.CanAllItemsCloseAsync(this.history.Concat(new[] { this.ActiveItem })); return this.CanAllItemsCloseAsync(this.history.Concat(new[] { this.ActiveItem }));
} }
/// <summary>
/// Ensures that all children are closed when this conductor is closed
/// </summary>
protected override void OnClose() protected override void OnClose()
{ {
// We've already been deactivated by this point // We've already been deactivated by this point

View File

@ -18,11 +18,18 @@ namespace Stylet
public class OneActive : ConductorBaseWithActiveItem<T> public class OneActive : ConductorBaseWithActiveItem<T>
{ {
private BindableCollection<T> items = new BindableCollection<T>(); private BindableCollection<T> items = new BindableCollection<T>();
/// <summary>
/// Items owned by this Conductor, one of which is active
/// </summary>
public IObservableCollection<T> Items public IObservableCollection<T> Items
{ {
get { return this.items; } get { return this.items; }
} }
/// <summary>
/// Create a new Conductor{T}.Collections.OneActive instance
/// </summary>
public OneActive() public OneActive()
{ {
this.items.CollectionChanged += (o, e) => this.items.CollectionChanged += (o, e) =>
@ -52,6 +59,9 @@ namespace Stylet
}; };
} }
/// <summary>
/// Called when the ActiveItem may have been removed from the Items collection. If it has, will change the ActiveItem to something sensible
/// </summary>
protected virtual void ActiveItemMayHaveBeenRemovedFromItems() protected virtual void ActiveItemMayHaveBeenRemovedFromItems()
{ {
if (this.items.Contains(this.ActiveItem)) if (this.items.Contains(this.ActiveItem))
@ -60,6 +70,10 @@ namespace Stylet
this.ChangeActiveItem(this.items.FirstOrDefault(), true); this.ChangeActiveItem(this.items.FirstOrDefault(), true);
} }
/// <summary>
/// Return all items associated with this conductor
/// </summary>
/// <returns></returns>
public override IEnumerable<T> GetChildren() public override IEnumerable<T> GetChildren()
{ {
return this.items; return this.items;
@ -102,6 +116,10 @@ namespace Stylet
} }
} }
/// <summary>
/// Close the given item (if and when possible, depending on IGuardClose.CanCloseAsync). This will deactive if it is the active item
/// </summary>
/// <param name="item">Item to close</param>
public override async void CloseItem(T item) public override async void CloseItem(T item)
{ {
if (item == null || !await this.CanCloseItem(item)) if (item == null || !await this.CanCloseItem(item))
@ -120,6 +138,10 @@ namespace Stylet
this.items.Remove(item); this.items.Remove(item);
} }
/// <summary>
/// Given a list of items, and and item which is going to be removed, choose a new item to be the next ActiveItem
/// </summary>
/// <returns>The next item to activate, or default(T) if no such item exists</returns>
protected virtual T DetermineNextItemToActivate(T itemToRemove) protected virtual T DetermineNextItemToActivate(T itemToRemove)
{ {
if (itemToRemove == null) if (itemToRemove == null)
@ -153,6 +175,9 @@ namespace Stylet
return this.CanAllItemsCloseAsync(this.items); return this.CanAllItemsCloseAsync(this.items);
} }
/// <summary>
/// Ensures that all items are closed when this conductor is closed
/// </summary>
protected override void OnClose() protected override void OnClose()
{ {
// We've already been deactivated by this point // We've already been deactivated by this point
@ -161,6 +186,10 @@ namespace Stylet
this.items.Clear(); this.items.Clear();
} }
/// <summary>
/// Ensure an item is ready to be activated
/// </summary>
/// <param name="newItem"></param>
protected override void EnsureItem(T newItem) protected override void EnsureItem(T newItem)
{ {
if (!this.items.Contains(newItem)) if (!this.items.Contains(newItem))

View File

@ -21,6 +21,10 @@ namespace Stylet
/// <typeparam name="TMessageType">Message type to handle. Can be a base class of the messsage type(s) to handle</typeparam> /// <typeparam name="TMessageType">Message type to handle. Can be a base class of the messsage type(s) to handle</typeparam>
public interface IHandle<TMessageType> : IHandle public interface IHandle<TMessageType> : IHandle
{ {
/// <summary>
/// Called whenever a message of type TMessageType is posted
/// </summary>
/// <param name="message">Message which was posted</param>
void Handle(TMessageType message); void Handle(TMessageType message);
} }
@ -49,11 +53,18 @@ namespace Stylet
void PublishWithDispatcher(object message, Action<Action> dispatcher); void PublishWithDispatcher(object message, Action<Action> dispatcher);
} }
/// <summary>
/// Default implementation of IEventAggregator
/// </summary>
public class EventAggregator : IEventAggregator public class EventAggregator : IEventAggregator
{ {
private readonly List<Handler> handlers = new List<Handler>(); private readonly List<Handler> handlers = new List<Handler>();
private readonly object handlersLock = new object(); private readonly object handlersLock = new object();
/// <summary>
/// Register an instance as wanting to receive events. Implement IHandle{T} for each event type you want to receive.
/// </summary>
/// <param name="handler">Instance that will be registered with the EventAggregator</param>
public void Subscribe(IHandle handler) public void Subscribe(IHandle handler)
{ {
lock (this.handlersLock) lock (this.handlersLock)
@ -66,6 +77,10 @@ namespace Stylet
} }
} }
/// <summary>
/// Unregister as wanting to receive events. The instance will no longer receive events after this is called.
/// </summary>
/// <param name="handler">Instance to unregister</param>
public void Unsubscribe(IHandle handler) public void Unsubscribe(IHandle handler)
{ {
lock (this.handlersLock) lock (this.handlersLock)
@ -76,6 +91,11 @@ namespace Stylet
} }
} }
/// <summary>
/// Publish an event to all subscribers, using the specified dispatcher
/// </summary>
/// <param name="message">Event to publish</param>
/// <param name="dispatcher">Dispatcher to use to call each subscriber's handle method(s)</param>
public void PublishWithDispatcher(object message, Action<Action> dispatcher) public void PublishWithDispatcher(object message, Action<Action> dispatcher)
{ {
lock (this.handlersLock) lock (this.handlersLock)

View File

@ -58,6 +58,9 @@ namespace Stylet
} }
} }
/// <summary>
/// Static class providing methods to easily run an action on the UI thread in various ways, and some other things
/// </summary>
public static class Execute public static class Execute
{ {
/// <summary> /// <summary>
@ -167,6 +170,9 @@ namespace Stylet
} }
} }
/// <summary>
/// Determing if we're currently running in design mode
/// </summary>
public static bool InDesignMode public static bool InDesignMode
{ {
get get

View File

@ -25,6 +25,9 @@ namespace Stylet
/// <typeparam name="T">Type of the active item</typeparam> /// <typeparam name="T">Type of the active item</typeparam>
public interface IHaveActiveItem<T> public interface IHaveActiveItem<T>
{ {
/// <summary>
/// Only item which is currently active. This normally corresponds to the item being displayed
/// </summary>
T ActiveItem { get; set; } T ActiveItem { get; set; }
} }
@ -33,6 +36,11 @@ namespace Stylet
/// </summary> /// </summary>
public interface IChildDelegate public interface IChildDelegate
{ {
/// <summary>
/// Called by the child to request that is be closed
/// </summary>
/// <param name="item">Child object, which is passed by the child itself</param>
/// <param name="dialogResult">DialogResult to use to close, if any</param>
void CloseItem(object item, bool? dialogResult = null); void CloseItem(object item, bool? dialogResult = null);
} }

View File

@ -114,15 +114,23 @@ namespace Stylet
{ {
} }
/// <summary>
/// EventArgs associated with the IActivate.Activated event
/// </summary>
public class ActivationEventArgs : EventArgs public class ActivationEventArgs : EventArgs
{ {
} }
/// <summary>
/// EventArgs associated with the IDeactivate.Deactivated event
/// </summary>
public class DeactivationEventArgs : EventArgs public class DeactivationEventArgs : EventArgs
{ {
} }
/// <summary>
/// EventArgs associated with the IClose.Closed event
/// </summary>
public class CloseEventArgs : EventArgs public class CloseEventArgs : EventArgs
{ {
} }

View File

@ -32,31 +32,57 @@ namespace Stylet
set { SetAndNotify(ref this._value, value); } set { SetAndNotify(ref this._value, value); }
} }
/// <summary>
/// Create a new LabelledValue, without setting Label or Value
/// </summary>
public LabelledValue() public LabelledValue()
{ {
} }
/// <summary>
/// Create a new LabelledValue, with the given label and value
/// </summary>
/// <param name="label">Label to use. This value is displayed in your view</param>
/// <param name="value">Value to use. This is used by your ViewModel</param>
public LabelledValue(string label, T value) public LabelledValue(string label, T value)
{ {
this._label = label; this._label = label;
this._value = value; this._value = value;
} }
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">An object to compare with this object</param>
/// <returns>true if the current object is equal to the other parameter; otherwise, false.</returns>
public bool Equals(LabelledValue<T> other) public bool Equals(LabelledValue<T> other)
{ {
return other == null ? false : this.Label == other.Label && EqualityComparer<T>.Default.Equals(this.Value, other.Value); return other == null ? false : this.Label == other.Label && EqualityComparer<T>.Default.Equals(this.Value, other.Value);
} }
/// <summary>
/// Indicates whether the current object is equal to another object of any type
/// </summary>
/// <param name="obj">An object to compare with this object</param>
/// <returns>true if the current object is of the same type as the other object, and equal to the other parameter; otherwise, false.</returns>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return this.Equals(obj as LabelledValue<T>); return this.Equals(obj as LabelledValue<T>);
} }
/// <summary>
/// Returns a hash code for the this object
/// </summary>
/// <returns>A hash code for this object.</returns>
public override int GetHashCode() public override int GetHashCode()
{ {
return new { this.Label, this.Value }.GetHashCode(); return new { this.Label, this.Value }.GetHashCode();
} }
/// <summary>
/// Return the Label associated with this object
/// </summary>
/// <returns>The Label associated with this object</returns>
public override string ToString() public override string ToString()
{ {
return this.Label; return this.Label;

View File

@ -17,7 +17,7 @@ namespace Stylet
/// <summary> /// <summary>
/// Create a new LambdaComparer{T} /// Create a new LambdaComparer{T}
/// </summary> /// </summary>
/// <param name="comparer">Comparer, which takes two {T} instances and returns true if they are equal</param> /// <param name="comparer">Comparer, which takes two T instances and returns true if they are equal</param>
public LambdaComparer(Func<T, T, bool> comparer) public LambdaComparer(Func<T, T, bool> comparer)
{ {
if (comparer == null) if (comparer == null)
@ -25,11 +25,22 @@ namespace Stylet
this.comparer = comparer; this.comparer = comparer;
} }
/// <summary>
/// Determines whether the specified objects are equal
/// </summary>
/// <param name="x">The first object of type T to compare.</param>
/// <param name="y">The second object of type T to compare.</param>
/// <returns>true if the specified objects are equal; otherwise, false.</returns>
public bool Equals(T x, T y) public bool Equals(T x, T y)
{ {
return this.comparer(x, y); return this.comparer(x, y);
} }
/// <summary>
/// Returns a hash code for the specified object
/// </summary>
/// <param name="obj">The System.Object for which a hash code is to be returned.</param>
/// <returns>A hash code for the specified object.</returns>
public int GetHashCode(T obj) public int GetHashCode(T obj)
{ {
return obj.GetHashCode(); return obj.GetHashCode();

View File

@ -13,6 +13,9 @@ using System.Windows.Media.Imaging;
namespace Stylet namespace Stylet
{ {
/// <summary>
/// Class holding extension method(s) on IWindowManager, used to show a MessageBox
/// </summary>
public static class MessageBoxWindowManagerExtensions public static class MessageBoxWindowManagerExtensions
{ {
/// <summary> /// <summary>
@ -77,6 +80,9 @@ namespace Stylet
/// </summary> /// </summary>
public static IDictionary<MessageBoxResult, string> ButtonLabels { get; set; } public static IDictionary<MessageBoxResult, string> ButtonLabels { get; set; }
/// <summary>
/// Mapping of MessageBoxButton values to the buttons which should be displayed
/// </summary>
public static IDictionary<MessageBoxButton, MessageBoxResult[]> ButtonToResults { get; set; } public static IDictionary<MessageBoxButton, MessageBoxResult[]> ButtonToResults { get; set; }
/// <summary> /// <summary>
@ -229,6 +235,9 @@ namespace Stylet
/// </summary> /// </summary>
public virtual MessageBoxResult ClickedButton { get; protected set; } public virtual MessageBoxResult ClickedButton { get; protected set; }
/// <summary>
/// When the View loads, play a sound if appropriate
/// </summary>
protected override void OnViewLoaded() protected override void OnViewLoaded()
{ {
// There might not be a sound, or it might be null // There might not be a sound, or it might be null
@ -238,6 +247,10 @@ namespace Stylet
sound.Play(); sound.Play();
} }
/// <summary>
/// Called when MessageBoxView when the user clicks a button
/// </summary>
/// <param name="button">Button which was clicked</param>
public void ButtonClicked(MessageBoxResult button) public void ButtonClicked(MessageBoxResult button)
{ {
this.ClickedButton = button; this.ClickedButton = button;

View File

@ -40,7 +40,7 @@ namespace Stylet
/// <summary> /// <summary>
/// Raise a PropertyChanged notification from the property in the given expression, e.g. NotifyOfPropertyChange(() => this.Property) /// Raise a PropertyChanged notification from the property in the given expression, e.g. NotifyOfPropertyChange(() => this.Property)
/// </summary /// </summary>
/// <param name="property">Expression describing the property to raise a PropertyChanged notification for</param> /// <param name="property">Expression describing the property to raise a PropertyChanged notification for</param>
protected virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) protected virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property)
{ {

View File

@ -14,9 +14,15 @@ namespace Stylet
/// </summary> /// </summary>
public interface IEventBinding public interface IEventBinding
{ {
/// <summary>
/// Unbind this event binding, so that it will no longer receive events
/// </summary>
void Unbind(); void Unbind();
} }
/// <summary>
/// Class holding extension methods on INotifyPropertyChanged, to allow strong/weak binding
/// </summary>
public static class PropertyChangedExtensions public static class PropertyChangedExtensions
{ {
internal class StrongPropertyChangedBinding : IEventBinding internal class StrongPropertyChangedBinding : IEventBinding

View File

@ -16,7 +16,15 @@ namespace Stylet
/// </summary> /// </summary>
public class Screen : ValidatingModelBase, IScreen public class Screen : ValidatingModelBase, IScreen
{ {
/// <summary>
/// Create a new Screen instance (without setting up a validator)
/// </summary>
public Screen() : this(null) { } public Screen() : this(null) { }
/// <summary>
/// Create a new screen instance, which can validate properties using the given validator
/// </summary>
/// <param name="validator">Validator to use</param>
public Screen(IModelValidator validator) : base(validator) public Screen(IModelValidator validator) : base(validator)
{ {
this.DisplayName = this.GetType().FullName; this.DisplayName = this.GetType().FullName;
@ -57,6 +65,10 @@ namespace Stylet
#region IHaveDisplayName #region IHaveDisplayName
private string _displayName; private string _displayName;
/// <summary>
/// Name associated with this ViewModel. Shown e.g. in a window's title bar, or as a tab's displayName
/// </summary>
public virtual string DisplayName public virtual string DisplayName
{ {
get { return this._displayName; } get { return this._displayName; }
@ -67,6 +79,9 @@ namespace Stylet
#region IActivate #region IActivate
/// <summary>
/// Fired whenever the Screen is activated
/// </summary>
public event EventHandler<ActivationEventArgs> Activated; public event EventHandler<ActivationEventArgs> Activated;
private bool hasBeenActivatedEver; private bool hasBeenActivatedEver;
@ -114,6 +129,9 @@ namespace Stylet
#region IDeactivate #region IDeactivate
/// <summary>
/// Fired whenever the Screen is deactivated
/// </summary>
public event EventHandler<DeactivationEventArgs> Deactivated; public event EventHandler<DeactivationEventArgs> Deactivated;
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "Stylet.Screen.#Stylet.IDeactivate.Deactivate()", Justification = "As this is a framework type, don't want to make it too easy for users to call this method")] [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "Stylet.Screen.#Stylet.IDeactivate.Deactivate()", Justification = "As this is a framework type, don't want to make it too easy for users to call this method")]
@ -140,6 +158,9 @@ namespace Stylet
#region IClose #region IClose
/// <summary>
/// Called whenever this Screen is closed
/// </summary>
public event EventHandler<CloseEventArgs> Closed; public event EventHandler<CloseEventArgs> Closed;
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "As this is a framework type, don't want to make it too easy for users to call this method")] [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "As this is a framework type, don't want to make it too easy for users to call this method")]
@ -166,6 +187,9 @@ namespace Stylet
#region IViewAware #region IViewAware
/// <summary>
/// View attached to this ViewModel, if any. Using this should be a last resort
/// </summary>
public UIElement View { get; private set; } public UIElement View { get; private set; }
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "As this is a framework type, don't want to make it too easy for users to call this method")] [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "As this is a framework type, don't want to make it too easy for users to call this method")]

View File

@ -8,8 +8,17 @@ using System.Threading.Tasks;
namespace Stylet namespace Stylet
{ {
// Don't name ConductorExtensions, otherwise it's too obvious when someone types 'Conductor' // Don't name ConductorExtensions, otherwise it's too obvious when someone types 'Conductor'
/// <summary>
/// Extension methods used by the Conductor classes
/// </summary>
public static class StyletConductorExtensions public static class StyletConductorExtensions
{ {
/// <summary>
/// For each item in a list, set the parent to the current conductor
/// </summary>
/// <typeparam name="T">Type of conductor</typeparam>
/// <param name="parent">Parent to set the items' parent to</param>
/// <param name="items">Items to manipulate</param>
public static void SetParent<T>(this IConductor<T> parent, IEnumerable items) public static void SetParent<T>(this IConductor<T> parent, IEnumerable items)
{ {
foreach (var child in items.OfType<IChild>()) foreach (var child in items.OfType<IChild>())
@ -19,8 +28,11 @@ namespace Stylet
} }
/// <summary> /// <summary>
/// Close an item, and clean it up a bit /// Close an item, and clear its parent if it's set to the current parent
/// </summary> /// </summary>
/// <typeparam name="T">Type of conductor</typeparam>
/// <param name="parent">Parent</param>
/// <param name="item">Item to close and clean up</param>
public static void CloseAndCleanUp<T>(this IConductor<T> parent, T item) public static void CloseAndCleanUp<T>(this IConductor<T> parent, T item)
{ {
ScreenExtensions.TryClose(item); ScreenExtensions.TryClose(item);
@ -30,6 +42,12 @@ namespace Stylet
itemAsChild.Parent = null; itemAsChild.Parent = null;
} }
/// <summary>
/// For each item in a list, close it, and if its parent is set to the given parent, clear that parent
/// </summary>
/// <typeparam name="T">Type of conductor</typeparam>
/// <param name="parent">Parent</param>
/// <param name="items">List of items to close and clean up</param>
public static void CloseAndCleanUp<T>(this IConductor<T> parent, IEnumerable items) public static void CloseAndCleanUp<T>(this IConductor<T> parent, IEnumerable items)
{ {
foreach (var item in items.OfType<T>()) foreach (var item in items.OfType<T>())

View File

@ -16,6 +16,7 @@ namespace StyletIoC
{ {
/// <summary> /// <summary>
/// Bind the specified service to itself - if you self-bind MyClass, and request an instance of MyClass, you'll get an instance of MyClass. /// Bind the specified service to itself - if you self-bind MyClass, and request an instance of MyClass, you'll get an instance of MyClass.
/// </summary>
/// <returns></returns> /// <returns></returns>
IInScopeOrWithKey ToSelf(); IInScopeOrWithKey ToSelf();
@ -50,14 +51,9 @@ namespace StyletIoC
IInScopeOrWithKey ToAllImplementations(params Assembly[] assemblies); IInScopeOrWithKey ToAllImplementations(params Assembly[] assemblies);
} }
public interface IInScopeOrWithKey : IInScope
{
/// <summary> /// <summary>
/// Associate a key with this binding. Requests for the service will have to specify this key to retrieve the result of this binding /// Fluent interface on which WithKey can be called
/// </summary> /// </summary>
/// <param name="key">Key to associate with this binding</param>
IInScope WithKey(string key);
}
public interface IWithKey public interface IWithKey
{ {
/// <summary> /// <summary>
@ -66,6 +62,10 @@ namespace StyletIoC
/// <param name="key">Key to associate with this binding</param> /// <param name="key">Key to associate with this binding</param>
void WithKey(string key); void WithKey(string key);
} }
/// <summary>
/// Fluent interface on which InSingletonScope can be called
/// </summary>
public interface IInScope public interface IInScope
{ {
/// <summary> /// <summary>
@ -74,6 +74,18 @@ namespace StyletIoC
void InSingletonScope(); void InSingletonScope();
} }
/// <summary>
/// Fluent interface on which InSingletonScope or WithKey can be called
/// </summary>
public interface IInScopeOrWithKey : IInScope
{
/// <summary>
/// Associate a key with this binding. Requests for the service will have to specify this key to retrieve the result of this binding
/// </summary>
/// <param name="key">Key to associate with this binding</param>
IInScope WithKey(string key);
}
internal class BuilderBindTo : IBindTo internal class BuilderBindTo : IBindTo
{ {
public Type ServiceType { get; private set; } public Type ServiceType { get; private set; }

View File

@ -12,6 +12,9 @@ using System.Threading.Tasks;
namespace StyletIoC namespace StyletIoC
{ {
/// <summary>
/// Describes an IoC container, specifically StyletIoC
/// </summary>
public interface IContainer public interface IContainer
{ {
/// <summary> /// <summary>
@ -165,7 +168,7 @@ namespace StyletIoC
/// <summary> /// <summary>
/// Fetch instances of all types which implement the specified service /// Fetch instances of all types which implement the specified service
/// </summary> /// </summary>
/// <typeparam name="T">Type of the service to fetch implementations for</typeparam> /// <param name="type">Type of the service to fetch implementations for</param>
/// <param name="key">Key that implementations of the service to fetch were registered with, defaults to null</param> /// <param name="key">Key that implementations of the service to fetch were registered with, defaults to null</param>
/// <returns>All implementations of the requested service, with the requested key</returns> /// <returns>All implementations of the requested service, with the requested key</returns>
public IEnumerable<object> GetAll(Type type, string key = null) public IEnumerable<object> GetAll(Type type, string key = null)
@ -605,47 +608,77 @@ namespace StyletIoC
} }
} }
/// <summary>
/// Interface to be implemented by objects if they want to be notified when property injection has occurred
/// </summary>
public interface IInjectionAware public interface IInjectionAware
{ {
/// <summary>
/// Called by StyletIoC when property injection has occurred
/// </summary>
void ParametersInjected(); void ParametersInjected();
} }
public class StyletIoCException : Exception /// <summary>
/// Base class for all exceptions describing StyletIoC-specific problems?
/// </summary>
public abstract class StyletIoCException : Exception
{ {
public StyletIoCException(string message) : base(message) { } internal StyletIoCException(string message) : base(message) { }
public StyletIoCException(string message, Exception innerException) : base(message, innerException) { } internal StyletIoCException(string message, Exception innerException) : base(message, innerException) { }
} }
/// <summary>
/// A problem occured with a registration process (failed to register, failed to find a registration, etc)
/// </summary>
public class StyletIoCRegistrationException : StyletIoCException public class StyletIoCRegistrationException : StyletIoCException
{ {
public StyletIoCRegistrationException(string message) : base(message) { } internal StyletIoCRegistrationException(string message) : base(message) { }
public StyletIoCRegistrationException(string message, Exception innerException) : base(message, innerException) { } internal StyletIoCRegistrationException(string message, Exception innerException) : base(message, innerException) { }
} }
/// <summary>
/// StyletIoC was unable to find a callable constructor for a type
/// </summary>
public class StyletIoCFindConstructorException : StyletIoCException public class StyletIoCFindConstructorException : StyletIoCException
{ {
public StyletIoCFindConstructorException(string message) : base(message) { } internal StyletIoCFindConstructorException(string message) : base(message) { }
} }
/// <summary>
/// StyletIoC was unable to create an abstract factory
/// </summary>
public class StyletIoCCreateFactoryException : StyletIoCException public class StyletIoCCreateFactoryException : StyletIoCException
{ {
public StyletIoCCreateFactoryException(string message) : base(message) { } internal StyletIoCCreateFactoryException(string message) : base(message) { }
public StyletIoCCreateFactoryException(string message, Exception innerException) : base(message, innerException) { } internal StyletIoCCreateFactoryException(string message, Exception innerException) : base(message, innerException) { }
} }
/// <summary>
/// Attribute which can be used to mark the constructor to use, properties to inject, which key to use to resolve an injected property, and others. See the docs
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class InjectAttribute : Attribute public sealed class InjectAttribute : Attribute
{ {
/// <summary>
/// Create a new InjectAttribute
/// </summary>
public InjectAttribute() public InjectAttribute()
{ {
} }
/// <summary>
/// Create a new InjectAttribute, which has the specified key
/// </summary>
/// <param name="key"></param>
public InjectAttribute(string key) public InjectAttribute(string key)
{ {
this.Key = key; this.Key = key;
} }
// This is a named argument /// <summary>
/// Key to use to resolve the relevant dependency
/// </summary>
public string Key { get; set; } public string Key { get; set; }
} }
} }

View File

@ -213,6 +213,10 @@ namespace Stylet
return newErrors == null || newErrors.Length == 0; return newErrors == null || newErrors.Length == 0;
} }
/// <summary>
/// Raise a PropertyChanged notification for the named property, and validate that property if this.validation is set and this.autoValidate is true
/// </summary>
/// <param name="propertyName"></param>
protected override async void OnPropertyChanged(string propertyName) protected override async void OnPropertyChanged(string propertyName)
{ {
base.OnPropertyChanged(propertyName); base.OnPropertyChanged(propertyName);

View File

@ -17,14 +17,18 @@ namespace Stylet
public interface IViewManager public interface IViewManager
{ {
/// <summary> /// <summary>
/// Called by the View.Model attached property when the ViewModel its bound to changes /// Called by View whenever its current View.Model changes. Will locate and instantiate the correct view, and set it as the target's Content
/// </summary>
/// <param name="targetLocation">Thing which View.Model was changed on. Will have its Content set</param>
/// <param name="oldValue">Previous value of View.Model</param>
/// <param name="newValue">New value of View.Model</param>
void OnModelChanged(DependencyObject targetLocation, object oldValue, object newValue); void OnModelChanged(DependencyObject targetLocation, object oldValue, object newValue);
/// <summary> /// <summary>
/// Given an instance of a ViewModel, locate the correct view for it, and instantiate it /// Given a ViewModel instance, locate its View type (using LocateViewForModel), instantiates and initializes it
/// </summary> /// </summary>
/// <param name="model">ViewModel to locate the view for</param> /// <param name="model">ViewModel to locate and instantiate the View for</param>
/// <returns>An instance of the correct view</returns> /// <returns>Instantiated and setup view</returns>
UIElement CreateAndSetupViewForModel(object model); UIElement CreateAndSetupViewForModel(object model);
/// <summary> /// <summary>
@ -35,8 +39,17 @@ namespace Stylet
void BindViewToModel(UIElement view, object viewModel); void BindViewToModel(UIElement view, object viewModel);
} }
/// <summary>
/// Default implementation of ViewManager. Responsible for locating, creating, and settings up Views. Also owns the View.Model and View.ActionTarget attached properties
/// </summary>
public class ViewManager : IViewManager public class ViewManager : IViewManager
{ {
/// <summary>
/// Called by View whenever its current View.Model changes. Will locate and instantiate the correct view, and set it as the target's Content
/// </summary>
/// <param name="targetLocation">Thing which View.Model was changed on. Will have its Content set</param>
/// <param name="oldValue">Previous value of View.Model</param>
/// <param name="newValue">New value of View.Model</param>
public virtual void OnModelChanged(DependencyObject targetLocation, object oldValue, object newValue) public virtual void OnModelChanged(DependencyObject targetLocation, object oldValue, object newValue)
{ {
if (oldValue == newValue) if (oldValue == newValue)
@ -64,6 +77,11 @@ namespace Stylet
} }
} }
/// <summary>
/// Given the expected name for a view, locate its type (or throw an exception if a suitable type couldn't be found)
/// </summary>
/// <param name="viewName">View name to locate the type for</param>
/// <returns>Type for that view name</returns>
public virtual Type ViewTypeForViewName(string viewName) public virtual Type ViewTypeForViewName(string viewName)
{ {
// TODO: This might need some more thinking // TODO: This might need some more thinking
@ -74,6 +92,11 @@ namespace Stylet
return viewType; return viewType;
} }
/// <summary>
/// Given the type of a model, locate the type of its View (or throw an exception)
/// </summary>
/// <param name="modelType">Model to find the view for</param>
/// <returns>Type of the ViewModel's View</returns>
public virtual Type LocateViewForModel(Type modelType) public virtual Type LocateViewForModel(Type modelType)
{ {
var viewName = Regex.Replace(modelType.FullName, @"ViewModel", "View"); var viewName = Regex.Replace(modelType.FullName, @"ViewModel", "View");
@ -82,6 +105,11 @@ namespace Stylet
return viewType; return viewType;
} }
/// <summary>
/// Given an instance of a ViewModel and an instance of its View, bind the two together
/// </summary>
/// <param name="view">View to bind to the ViewModel</param>
/// <param name="viewModel">ViewModel to bind the View to</param>
public virtual void BindViewToModel(UIElement view, object viewModel) public virtual void BindViewToModel(UIElement view, object viewModel)
{ {
View.SetActionTarget(view, viewModel); View.SetActionTarget(view, viewModel);
@ -94,6 +122,12 @@ namespace Stylet
if (viewModelAsViewAware != null) if (viewModelAsViewAware != null)
viewModelAsViewAware.AttachView(view); viewModelAsViewAware.AttachView(view);
} }
/// <summary>
/// Given a ViewModel instance, locate its View type (using LocateViewForModel), instantiates and initializes it, and binds it to the ViewModel (using BindViewToModel)
/// </summary>
/// <param name="model">ViewModel to locate and instantiate the View for</param>
/// <returns>Instantiated and setup view</returns>
public virtual UIElement CreateAndSetupViewForModel(object model) public virtual UIElement CreateAndSetupViewForModel(object model)
{ {
var viewType = this.LocateViewForModel(model.GetType()); var viewType = this.LocateViewForModel(model.GetType());

View File

@ -9,8 +9,20 @@ using System.Threading.Tasks;
namespace Stylet namespace Stylet
{ {
/// <summary>
/// A manager capable of creating a weak event subscription for INotifyPropertyChanged events from a source to a subscriber. Manager MUST be owned by the subscriber.
/// </summary>
public interface IWeakEventManager public interface IWeakEventManager
{ {
/// <summary>
/// Create a weak event subscription from the source, to the given handler
/// </summary>
/// <typeparam name="TSource">Type of the source</typeparam>
/// <typeparam name="TProperty">Type of the property to subscribe to on the source</typeparam>
/// <param name="source">Source object, whic implements INotifyPropertyChanged, to subscribe to</param>
/// <param name="selector">Describes which property to observe, e.g. (x => x.SomeProperty)</param>
/// <param name="handler">Callback to be called whenever the property changes. Is passed the new value of the property</param>
/// <returns>An event binding, which can be used to unregister the subscription</returns>
IEventBinding BindWeak<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> selector, Action<TProperty> handler) IEventBinding BindWeak<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> selector, Action<TProperty> handler)
where TSource : class, INotifyPropertyChanged; where TSource : class, INotifyPropertyChanged;
} }
@ -54,11 +66,23 @@ namespace Stylet
} }
} }
/// <summary>
/// Default implementation of IWeakEventManager: a manager capable of creating a weak event subscription for INotifyPropertyChanged events from a source to a subscriber. Manager MUST be owned by the subscriber.
/// </summary>
public class WeakEventManager : IWeakEventManager public class WeakEventManager : IWeakEventManager
{ {
private object bindingsLock = new object(); private object bindingsLock = new object();
private List<IEventBinding> bindings = new List<IEventBinding>(); private List<IEventBinding> bindings = new List<IEventBinding>();
/// <summary>
/// Create a weak event subscription from the source, to the given handler
/// </summary>
/// <typeparam name="TSource">Type of the source</typeparam>
/// <typeparam name="TProperty">Type of the property to subscribe to on the source</typeparam>
/// <param name="source">Source object, whic implements INotifyPropertyChanged, to subscribe to</param>
/// <param name="selector">Describes which property to observe, e.g. (x => x.SomeProperty)</param>
/// <param name="handler">Callback to be called whenever the property changes. Is passed the new value of the property</param>
/// <returns>An event binding, which can be used to unregister the subscription</returns>
public IEventBinding BindWeak<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> selector, Action<TProperty> handler) public IEventBinding BindWeak<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> selector, Action<TProperty> handler)
where TSource : class, INotifyPropertyChanged where TSource : class, INotifyPropertyChanged
{ {

View File

@ -10,34 +10,69 @@ using System.Windows.Navigation;
namespace Stylet namespace Stylet
{ {
/// <summary>
/// Manager capable of taking a ViewModel instance, instantiating its View and showing it as a dialog or window
/// </summary>
public interface IWindowManager public interface IWindowManager
{ {
/// <summary>
/// Given a ViewModel, show its corresponding View as a window
/// </summary>
/// <param name="viewModel">ViewModel to show the View for</param>
void ShowWindow(object viewModel); void ShowWindow(object viewModel);
/// <summary>
/// Given a ViewModel, show its corresponding View as a Dialog
/// </summary>
/// <param name="viewModel">ViewModel to show the View for</param>
/// <returns>DialogResult of the View</returns>
bool? ShowDialog(object viewModel); bool? ShowDialog(object viewModel);
} }
/// <summary>
/// Default implementation of IWindowManager, is capable of showing a ViewModel's View as a dialog or a window
/// </summary>
public class WindowManager : IWindowManager public class WindowManager : IWindowManager
{ {
private IViewManager viewManager; private IViewManager viewManager;
/// <summary>
/// Create a new WindowManager instance, using the given IViewManager
/// </summary>
/// <param name="viewManager">IViewManager to use when creating views</param>
public WindowManager(IViewManager viewManager) public WindowManager(IViewManager viewManager)
{ {
this.viewManager = viewManager; this.viewManager = viewManager;
} }
/// <summary>
/// Given a ViewModel, show its corresponding View as a window
/// </summary>
/// <param name="viewModel">ViewModel to show the View for</param>
public void ShowWindow(object viewModel) public void ShowWindow(object viewModel)
{ {
this.CreateWindow(viewModel, false).Show(); this.CreateWindow(viewModel, false).Show();
} }
/// <summary>
/// Given a ViewModel, show its corresponding View as a Dialog
/// </summary>
/// <param name="viewModel">ViewModel to show the View for</param>
/// <returns>DialogResult of the View</returns>
public bool? ShowDialog(object viewModel) public bool? ShowDialog(object viewModel)
{ {
return this.CreateWindow(viewModel, true).ShowDialog(); return this.CreateWindow(viewModel, true).ShowDialog();
} }
/// <summary>
/// Given a ViewModel, create its View, ensure that it's a Window, and set it up
/// </summary>
/// <param name="viewModel">ViewModel to create the window for</param>
/// <param name="isDialog">True if the window will be used as a dialog</param>
/// <returns>Window which was created and set up</returns>
protected virtual Window CreateWindow(object viewModel, bool isDialog) protected virtual Window CreateWindow(object viewModel, bool isDialog)
{ {
var view = this.viewManager.CreateViewForModel(viewModel); var view = this.viewManager.CreateAndSetupViewForModel(viewModel);
var window = view as Window; var window = view as Window;
if (window == null) if (window == null)
throw new ArgumentException(String.Format("Tried to show {0} as a window, but it isn't a Window", view == null ? "(null)" : view.GetType().Name)); throw new ArgumentException(String.Format("Tried to show {0} as a window, but it isn't a Window", view == null ? "(null)" : view.GetType().Name));

View File

@ -10,10 +10,24 @@ using System.Windows.Markup;
namespace Stylet.Xaml namespace Stylet.Xaml
{ {
/// <summary>
/// What to do if the given target is null, or if the given action doesn't exist on the target
/// </summary>
public enum ActionUnavailableBehaviour public enum ActionUnavailableBehaviour
{ {
/// <summary>
/// Enable the control anyway. Clicking/etc the control won't do anything
/// </summary>
Enable, Enable,
/// <summary>
/// Disable the control. This is only valid for commands, not events
/// </summary>
Disable, Disable,
/// <summary>
/// Throw an exception
/// </summary>
Throw Throw
}; };
@ -46,6 +60,11 @@ namespace Stylet.Xaml
this.Method = method; this.Method = method;
} }
/// <summary>
/// When implemented in a derived class, returns an object that is provided as the value of the target property for this markup extension.
/// </summary>
/// <param name="serviceProvider">A service provider helper that can provide services for the markup extension.</param>
/// <returns>The object value to set on the property where the extension is applied.</returns>
public override object ProvideValue(IServiceProvider serviceProvider) public override object ProvideValue(IServiceProvider serviceProvider)
{ {
var valueService = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)); var valueService = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));

View File

@ -14,6 +14,9 @@ namespace Stylet.Xaml
/// </summary> /// </summary>
public class BoolToVisibilityConverter : DependencyObject, IValueConverter public class BoolToVisibilityConverter : DependencyObject, IValueConverter
{ {
/// <summary>
/// Singleton instance of this converter. Usage e.g. Converter="{x:Static s:BoolToVisibilityConverter.Instance}"
/// </summary>
public static readonly BoolToVisibilityConverter Instance = new BoolToVisibilityConverter(); public static readonly BoolToVisibilityConverter Instance = new BoolToVisibilityConverter();
/// <summary> /// <summary>
@ -25,7 +28,9 @@ namespace Stylet.Xaml
set { SetValue(TrueVisibilityProperty, value); } set { SetValue(TrueVisibilityProperty, value); }
} }
// Using a DependencyProperty as the backing store for TrueVisibility. This enables animation, styling, binding, etc... /// <summary>
/// Property specifying the visibility to return when the parameter is true
/// </summary>
public static readonly DependencyProperty TrueVisibilityProperty = public static readonly DependencyProperty TrueVisibilityProperty =
DependencyProperty.Register("TrueVisibility", typeof(Visibility), typeof(BoolToVisibilityConverter), new PropertyMetadata(Visibility.Visible)); DependencyProperty.Register("TrueVisibility", typeof(Visibility), typeof(BoolToVisibilityConverter), new PropertyMetadata(Visibility.Visible));
@ -38,11 +43,16 @@ namespace Stylet.Xaml
set { SetValue(FalseVisibilityProperty, value); } set { SetValue(FalseVisibilityProperty, value); }
} }
// Using a DependencyProperty as the backing store for FalseVisibility. This enables animation, styling, binding, etc... /// <summary>
/// Property specifying the visibility to return when the parameter is false
/// </summary>
public static readonly DependencyProperty FalseVisibilityProperty = public static readonly DependencyProperty FalseVisibilityProperty =
DependencyProperty.Register("FalseVisibility", typeof(Visibility), typeof(BoolToVisibilityConverter), new PropertyMetadata(Visibility.Collapsed)); DependencyProperty.Register("FalseVisibility", typeof(Visibility), typeof(BoolToVisibilityConverter), new PropertyMetadata(Visibility.Collapsed));
/// <summary>
/// Perform the conversion
/// </summary>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ {
bool result; bool result;
@ -61,6 +71,9 @@ namespace Stylet.Xaml
return result ? this.TrueVisibility : this.FalseVisibility; return result ? this.TrueVisibility : this.FalseVisibility;
} }
/// <summary>
/// Perform the inverse conversion. Only valid if the value is bool
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ {
if (targetType != typeof(bool)) if (targetType != typeof(bool))

View File

@ -53,6 +53,8 @@ namespace Stylet.Xaml
/// </summary> /// </summary>
/// <param name="subject">View to grab the View.ActionTarget from</param> /// <param name="subject">View to grab the View.ActionTarget from</param>
/// <param name="methodName">Method name. the MyMethod in Buttom Command="{s:Action MyMethod}".</param> /// <param name="methodName">Method name. the MyMethod in Buttom Command="{s:Action MyMethod}".</param>
/// <param name="targetNullBehaviour">Behaviour for it the relevant View.ActionTarget is null</param>
/// <param name="actionNonExistentBehaviour">Behaviour for if the action doesn't exist on the View.ActionTarget</param>
public CommandAction(DependencyObject subject, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour) public CommandAction(DependencyObject subject, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour)
{ {
this.Subject = subject; this.Subject = subject;
@ -139,6 +141,11 @@ namespace Stylet.Xaml
handler(this, EventArgs.Empty); handler(this, EventArgs.Empty);
} }
/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
/// <returns>true if this command can be executed; otherwise, false.</returns>
public bool CanExecute(object parameter) public bool CanExecute(object parameter)
{ {
// It's enabled only if both the targetNull and actionNonExistent tests pass // It's enabled only if both the targetNull and actionNonExistent tests pass
@ -162,8 +169,15 @@ namespace Stylet.Xaml
return this.guardPropertyGetter(); return this.guardPropertyGetter();
} }
/// <summary>
/// Occurs when changes occur that affect whether or not the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged; public event EventHandler CanExecuteChanged;
/// <summary>
/// The method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public void Execute(object parameter) public void Execute(object parameter)
{ {
// Any throwing would have been handled prior to this // Any throwing would have been handled prior to this

View File

@ -14,6 +14,9 @@ namespace Stylet.Xaml
/// </summary> /// </summary>
public class DebugConverter : DependencyObject, IValueConverter public class DebugConverter : DependencyObject, IValueConverter
{ {
/// <summary>
/// Singleton instance of this DebugConverter. Usage e.g. Converter={x:Static s:DebugConverter.Instance}"
/// </summary>
public static readonly DebugConverter Instance; public static readonly DebugConverter Instance;
/// <summary> /// <summary>
@ -25,7 +28,9 @@ namespace Stylet.Xaml
set { SetValue(NameProperty, value); } set { SetValue(NameProperty, value); }
} }
// Using a DependencyProperty as the backing store for Name. This enables animation, styling, binding, etc... /// <summary>
/// Property specifying the category to use with Debug.WriteLine
/// </summary>
public static readonly DependencyProperty NameProperty = public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(DebugConverter), new PropertyMetadata("DebugConverter")); DependencyProperty.Register("Name", typeof(string), typeof(DebugConverter), new PropertyMetadata("DebugConverter"));
@ -39,7 +44,9 @@ namespace Stylet.Xaml
set { SetValue(LoggerProperty, value); } set { SetValue(LoggerProperty, value); }
} }
// Using a DependencyProperty as the backing store for Logger. This enables animation, styling, binding, etc... /// <summary>
/// Property specifying an action, which when called will log an entry.
/// </summary>
public static readonly DependencyProperty LoggerProperty = public static readonly DependencyProperty LoggerProperty =
DependencyProperty.Register("Logger", typeof(Action<string, string>), typeof(DebugConverter), new PropertyMetadata(null)); DependencyProperty.Register("Logger", typeof(Action<string, string>), typeof(DebugConverter), new PropertyMetadata(null));
@ -51,13 +58,18 @@ namespace Stylet.Xaml
Instance = new DebugConverter(); Instance = new DebugConverter();
} }
/// <summary>
/// Create a new DebugConverter instance
/// </summary>
public DebugConverter() public DebugConverter()
{ {
if (this.Logger == null) if (this.Logger == null)
this.Logger = (msg, name) => Debug.WriteLine(msg, name); this.Logger = (msg, name) => Debug.WriteLine(msg, name);
} }
/// <summary>
/// Perform the conversion
/// </summary>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ {
if (parameter == null) if (parameter == null)
@ -68,6 +80,9 @@ namespace Stylet.Xaml
return value; return value;
} }
/// <summary>
/// Perform the reverse conversion
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ {
if (parameter == null) if (parameter == null)

View File

@ -13,10 +13,13 @@ namespace Stylet.Xaml
/// </summary> /// </summary>
public class EqualityConverter : DependencyObject, IMultiValueConverter public class EqualityConverter : DependencyObject, IMultiValueConverter
{ {
/// <summary>
/// Singleton instance of this converter. Usage: Converter="{x:Static s:EqualityConverter.Instance}"
/// </summary>
public static readonly EqualityConverter Instance = new EqualityConverter(); public static readonly EqualityConverter Instance = new EqualityConverter();
/// <summary> /// <summary>
/// True false, instead of true, if call values are equal /// Return false, instead of true, if call values are equal
/// </summary> /// </summary>
public bool Invert public bool Invert
{ {
@ -24,9 +27,15 @@ namespace Stylet.Xaml
set { SetValue(InvertProperty, value); } set { SetValue(InvertProperty, value); }
} }
/// <summary>
/// Property specifying whether the output should be inverted
/// </summary>
public static readonly DependencyProperty InvertProperty = public static readonly DependencyProperty InvertProperty =
DependencyProperty.Register("Invert", typeof(bool), typeof(EqualityConverter), new PropertyMetadata(false)); DependencyProperty.Register("Invert", typeof(bool), typeof(EqualityConverter), new PropertyMetadata(false));
/// <summary>
/// Perform the conversion
/// </summary>
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ {
if (values == null || values.Length == 0) if (values == null || values.Length == 0)
@ -36,6 +45,9 @@ namespace Stylet.Xaml
return this.Invert ? !result : result; return this.Invert ? !result : result;
} }
/// <summary>
/// Perform the reverse convesion. Not implemented.
/// </summary>
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@ -36,7 +36,7 @@ namespace Stylet.Xaml
private object target; private object target;
private ActionUnavailableBehaviour nullTargetBehaviour; private ActionUnavailableBehaviour targetNullBehaviour;
private ActionUnavailableBehaviour actionNonExistentBehaviour; private ActionUnavailableBehaviour actionNonExistentBehaviour;
/// <summary> /// <summary>
@ -45,9 +45,11 @@ namespace Stylet.Xaml
/// <param name="subject">View whose View.ActionTarget we watch</param> /// <param name="subject">View whose View.ActionTarget we watch</param>
/// <param name="targetProperty">Property on the WPF element we're returning a delegate for</param> /// <param name="targetProperty">Property on the WPF element we're returning a delegate for</param>
/// <param name="methodName">The MyMethod in {s:Action MyMethod}, this is what we call when the event's fired</param> /// <param name="methodName">The MyMethod in {s:Action MyMethod}, this is what we call when the event's fired</param>
public EventAction(DependencyObject subject, EventInfo targetProperty, string methodName, ActionUnavailableBehaviour nullTargetBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour) /// <param name="targetNullBehaviour">Behaviour for it the relevant View.ActionTarget is null</param>
/// <param name="actionNonExistentBehaviour">Behaviour for if the action doesn't exist on the View.ActionTarget</param>
public EventAction(DependencyObject subject, EventInfo targetProperty, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour)
{ {
if (nullTargetBehaviour == ActionUnavailableBehaviour.Disable) if (targetNullBehaviour == ActionUnavailableBehaviour.Disable)
throw new ArgumentException("Setting NullTarget = Disable is unsupported when used on an Event"); throw new ArgumentException("Setting NullTarget = Disable is unsupported when used on an Event");
if (actionNonExistentBehaviour == ActionUnavailableBehaviour.Disable) if (actionNonExistentBehaviour == ActionUnavailableBehaviour.Disable)
throw new ArgumentException("Setting ActionNotFound = Disable is unsupported when used on an Event"); throw new ArgumentException("Setting ActionNotFound = Disable is unsupported when used on an Event");
@ -55,7 +57,7 @@ namespace Stylet.Xaml
this.subject = subject; this.subject = subject;
this.targetProperty = targetProperty; this.targetProperty = targetProperty;
this.methodName = methodName; this.methodName = methodName;
this.nullTargetBehaviour = nullTargetBehaviour; this.targetNullBehaviour = targetNullBehaviour;
this.actionNonExistentBehaviour = actionNonExistentBehaviour; this.actionNonExistentBehaviour = actionNonExistentBehaviour;
this.UpdateMethod(); this.UpdateMethod();
@ -71,7 +73,7 @@ namespace Stylet.Xaml
if (newTarget == null) if (newTarget == null)
{ {
if (this.nullTargetBehaviour == ActionUnavailableBehaviour.Throw) if (this.targetNullBehaviour == ActionUnavailableBehaviour.Throw)
throw new ArgumentException(String.Format("Method {0} has a target set which is null", this.methodName)); throw new ArgumentException(String.Format("Method {0} has a target set which is null", this.methodName));
} }
else else
@ -98,12 +100,9 @@ namespace Stylet.Xaml
/// <summary> /// <summary>
/// Return a delegate which can be added to the targetProperty /// Return a delegate which can be added to the targetProperty
/// </summary> /// </summary>
public Delegate GetDelegate() public RoutedEventHandler GetDelegate()
{ {
var methodInfo = this.GetType().GetMethod("InvokeCommand", BindingFlags.NonPublic | BindingFlags.Instance); return new RoutedEventHandler(this.InvokeCommand);
var parameterType = this.targetProperty.EventHandlerType;
return Delegate.CreateDelegate(parameterType, this, methodInfo);
} }
private void InvokeCommand(object sender, RoutedEventArgs e) private void InvokeCommand(object sender, RoutedEventArgs e)

View File

@ -16,8 +16,14 @@ namespace Stylet.Xaml
/// </summary> /// </summary>
public class IconToBitmapSourceConverter : IValueConverter public class IconToBitmapSourceConverter : IValueConverter
{ {
/// <summary>
/// Singleton instance of this converter. Usage e.g. Converter="{x:Static s:IconToBitmapSourceConverter.Instance}"
/// </summary>
public static IconToBitmapSourceConverter Instance = new IconToBitmapSourceConverter(); public static IconToBitmapSourceConverter Instance = new IconToBitmapSourceConverter();
/// <summary>
/// Converts a value
/// </summary>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ {
var icon = value as Icon; var icon = value as Icon;
@ -27,6 +33,9 @@ namespace Stylet.Xaml
return bs; return bs;
} }
/// <summary>
/// Converts a value back. Not implemented.
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@ -9,38 +9,76 @@ using System.Windows.Markup;
namespace Stylet.Xaml namespace Stylet.Xaml
{ {
/// <summary>
/// Holds attached properties relating to various bits of the View which are used by Stylet
/// </summary>
public class View : DependencyObject public class View : DependencyObject
{ {
private static readonly ContentPropertyAttribute defaultContentProperty = new ContentPropertyAttribute("Content"); private static readonly ContentPropertyAttribute defaultContentProperty = new ContentPropertyAttribute("Content");
/// <summary>
/// IViewManager to be used. This should be set by the Bootstrapper.
/// </summary>
public static IViewManager ViewManager; public static IViewManager ViewManager;
/// <summary>
/// Get the ActionTarget associated with the given object
/// </summary>
/// <param name="obj">Object to fetch the ActionTarget for</param>
/// <returns>ActionTarget associated with the given object</returns>
public static object GetActionTarget(DependencyObject obj) public static object GetActionTarget(DependencyObject obj)
{ {
return (object)obj.GetValue(ActionTargetProperty); return (object)obj.GetValue(ActionTargetProperty);
} }
/// <summary>
/// Set the ActionTarget associated with the given object
/// </summary>
/// <param name="obj">Object to set the ActionTarget for</param>
/// <param name="value">Value to set the ActionTarget to</param>
public static void SetActionTarget(DependencyObject obj, object value) public static void SetActionTarget(DependencyObject obj, object value)
{ {
obj.SetValue(ActionTargetProperty, value); obj.SetValue(ActionTargetProperty, value);
} }
/// <summary>
/// The object's ActionTarget. This is used to determine what object to call Actions on by the ActionExtension markup extension.
/// </summary>
public static readonly DependencyProperty ActionTargetProperty = public static readonly DependencyProperty ActionTargetProperty =
DependencyProperty.RegisterAttached("ActionTarget", typeof(object), typeof(View), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); DependencyProperty.RegisterAttached("ActionTarget", typeof(object), typeof(View), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
/// <summary>
/// Fetch the ViewModel currently associated with a given object
/// </summary>
/// <param name="obj">Object to fetch the ViewModel for</param>
/// <returns>ViewModel currently associated with the given object</returns>
public static object GetModel(DependencyObject obj) public static object GetModel(DependencyObject obj)
{ {
return (object)obj.GetValue(ModelProperty); return (object)obj.GetValue(ModelProperty);
} }
/// <summary>
/// Set the ViewModel currently associated with a given object
/// </summary>
/// <param name="obj">Object to set the ViewModel for</param>
/// <param name="value">ViewModel to set</param>
public static void SetModel(DependencyObject obj, object value) public static void SetModel(DependencyObject obj, object value)
{ {
obj.SetValue(ModelProperty, value); obj.SetValue(ModelProperty, value);
} }
/// <summary>
/// Property specifying the ViewModel currently associated with a given object
/// </summary>
public static readonly DependencyProperty ModelProperty = public static readonly DependencyProperty ModelProperty =
DependencyProperty.RegisterAttached("Model", typeof(object), typeof(View), new PropertyMetadata(null, (d, e) => ViewManager.OnModelChanged(d, e.OldValue, e.NewValue) )); DependencyProperty.RegisterAttached("Model", typeof(object), typeof(View), new PropertyMetadata(null, (d, e) => ViewManager.OnModelChanged(d, e.OldValue, e.NewValue) ));
/// <summary>
/// Helper to set the Content property of a given object to a particular View
/// </summary>
/// <param name="targetLocation">Object to set the Content property on</param>
/// <param name="view">View to set as the object's Content</param>
public static void SetContentProperty(DependencyObject targetLocation, UIElement view) public static void SetContentProperty(DependencyObject targetLocation, UIElement view)
{ {
var type = targetLocation.GetType(); var type = targetLocation.GetType();