Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3285 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
25 changed files with 16 additions and 2055 deletions
@ -1,110 +0,0 @@
@@ -1,110 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
using System.Windows.Data; |
||||
|
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
|
||||
namespace ICSharpCode.WpfDesign.AddIn |
||||
{ |
||||
public class ChooseClass : INotifyPropertyChanged |
||||
{ |
||||
public ChooseClass(IProjectContent projectContent) |
||||
{ |
||||
this.projectContent = projectContent; |
||||
|
||||
AddClassesRecursive(""); |
||||
|
||||
projectClasses.Sort((c1, c2) => c1.Name.CompareTo(c2.Name)); |
||||
|
||||
classes = new ListCollectionView(projectClasses); |
||||
classes.Filter = FilterPredicate; |
||||
} |
||||
|
||||
IProjectContent projectContent; |
||||
List<IClass> projectClasses = new List<IClass>(); |
||||
|
||||
void AddClassesRecursive(string ns) |
||||
{ |
||||
foreach (var item in projectContent.GetNamespaceContents(ns)) { |
||||
if (item is string) { |
||||
AddClassesRecursive(ns.Length == 0 ? item.ToString() : ns + "." + item); |
||||
} else if (item is IClass) { |
||||
IClass c = item as IClass; |
||||
if (c.IsPartial) { |
||||
if (projectClasses.Contains(c)) continue; |
||||
} |
||||
if (c.ClassType == ClassType.Class && c.IsPublic) { |
||||
projectClasses.Add(c); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
ListCollectionView classes; |
||||
|
||||
public ICollectionView Classes { |
||||
get { return classes; } |
||||
} |
||||
|
||||
string filter; |
||||
|
||||
public string Filter { |
||||
get { |
||||
return filter; |
||||
} |
||||
set { |
||||
filter = value; |
||||
Classes.Refresh(); |
||||
RaisePropertyChanged("Filter"); |
||||
} |
||||
} |
||||
|
||||
bool showSystemClasses; |
||||
|
||||
public bool ShowSystemClasses { |
||||
get { |
||||
return showSystemClasses; |
||||
} |
||||
set { |
||||
showSystemClasses = value; |
||||
Classes.Refresh(); |
||||
RaisePropertyChanged("ShowSystemClasses"); |
||||
} |
||||
} |
||||
|
||||
public IClass CurrentClass { |
||||
get { return Classes.CurrentItem as IClass; } |
||||
} |
||||
|
||||
bool FilterPredicate(object item) |
||||
{ |
||||
IClass c = item as IClass; |
||||
if (!ShowSystemClasses) { |
||||
if (c.Namespace.StartsWith("System") || c.Namespace.StartsWith("Microsoft")) { |
||||
return false; |
||||
} |
||||
} |
||||
return Match(c.Name, Filter); |
||||
} |
||||
|
||||
static bool Match(string className, string filter) |
||||
{ |
||||
if (string.IsNullOrEmpty(filter)) |
||||
return true; |
||||
else |
||||
return className.StartsWith(filter, StringComparison.InvariantCultureIgnoreCase); |
||||
} |
||||
|
||||
#region INotifyPropertyChanged Members
|
||||
public event PropertyChangedEventHandler PropertyChanged; |
||||
|
||||
void RaisePropertyChanged(string name) |
||||
{ |
||||
if (PropertyChanged != null) { |
||||
PropertyChanged(this, new PropertyChangedEventArgs(name)); |
||||
} |
||||
} |
||||
#endregion
|
||||
} |
||||
} |
@ -1,69 +0,0 @@
@@ -1,69 +0,0 @@
|
||||
<Window x:Class="ICSharpCode.WpfDesign.AddIn.ChooseClassDialog" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:sd="clr-namespace:ICSharpCode.WpfDesign.AddIn" |
||||
Background="{x:Static SystemColors.ControlBrush}" |
||||
SnapsToDevicePixels="True" |
||||
WindowStartupLocation="CenterScreen" |
||||
ResizeMode="CanResizeWithGrip" |
||||
Title="Choose Class" |
||||
Height="438" |
||||
Width="488"> |
||||
|
||||
<Grid> |
||||
<TextBlock Text="Starts with:" |
||||
HorizontalAlignment="Left" |
||||
Margin="12,12,0,0" |
||||
VerticalAlignment="Top" |
||||
Height="13" |
||||
Width="55" /> |
||||
<TextBox x:Name="uxFilter" |
||||
Text="{Binding Filter, UpdateSourceTrigger=PropertyChanged}" |
||||
Height="23" |
||||
Margin="12,31,12,0" |
||||
VerticalAlignment="Top" /> |
||||
|
||||
<sd:ClassListBox x:Name="uxList" |
||||
Margin="12,60,12,78" |
||||
ItemsSource="{Binding Classes}" |
||||
IsSynchronizedWithCurrentItem="True" |
||||
ScrollViewer.HorizontalScrollBarVisibility="Hidden" |
||||
> |
||||
<ListBox.ItemTemplate> |
||||
<DataTemplate> |
||||
<StackPanel Orientation="Horizontal"> |
||||
<Image Source="{sd:GetBitmap Icons.16x16.Class}" |
||||
Stretch="None" /> |
||||
<TextBlock Margin="5 0 0 0" |
||||
Text="{Binding Converter={x:Static sd:ClassNameConverter.Instance}}" |
||||
VerticalAlignment="Center"/> |
||||
</StackPanel> |
||||
</DataTemplate> |
||||
</ListBox.ItemTemplate> |
||||
</sd:ClassListBox> |
||||
|
||||
<CheckBox Content="Show System Classes" |
||||
IsChecked="{Binding ShowSystemClasses}" |
||||
Height="16" |
||||
HorizontalAlignment="Left" |
||||
Margin="12,0,0,56" |
||||
VerticalAlignment="Bottom" |
||||
Width="120" /> |
||||
<Button x:Name="uxOk" |
||||
Content="OK" |
||||
Height="23" |
||||
Margin="0,0,93,12" |
||||
VerticalAlignment="Bottom" |
||||
HorizontalAlignment="Right" |
||||
Width="75" |
||||
IsDefault="True" |
||||
IsEnabled="{Binding SelectedItem, ElementName=uxList, Converter={x:Static sd:NullToBoolConverter.Instance}}"/> |
||||
<Button Content="Cancel" |
||||
Height="23" |
||||
HorizontalAlignment="Right" |
||||
Margin="0,0,12,12" |
||||
VerticalAlignment="Bottom" |
||||
Width="75" |
||||
IsCancel="True" /> |
||||
</Grid> |
||||
</Window> |
@ -1,114 +0,0 @@
@@ -1,114 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Specialized; |
||||
using System.Globalization; |
||||
using System.Reflection; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Controls.Primitives; |
||||
using System.Windows.Data; |
||||
using System.Windows.Input; |
||||
|
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
|
||||
namespace ICSharpCode.WpfDesign.AddIn |
||||
{ |
||||
public partial class ChooseClassDialog |
||||
{ |
||||
public ChooseClassDialog(ChooseClass core) |
||||
{ |
||||
DataContext = core; |
||||
InitializeComponent(); |
||||
|
||||
uxFilter.Focus(); |
||||
uxList.MouseDoubleClick += uxList_MouseDoubleClick; |
||||
uxOk.Click += delegate { Ok(); }; |
||||
|
||||
AddHandler(Keyboard.GotKeyboardFocusEvent, |
||||
new KeyboardFocusChangedEventHandler( |
||||
(sender, e) => uxList.SetValue(IsSelectionActivePropertyKey, true) |
||||
), |
||||
true); |
||||
} |
||||
|
||||
//HACK: listbox is always highlighted
|
||||
public static DependencyPropertyKey IsSelectionActivePropertyKey = |
||||
(DependencyPropertyKey)typeof(Selector).GetField("IsSelectionActivePropertyKey", |
||||
BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); |
||||
|
||||
protected override void OnPreviewKeyDown(KeyEventArgs e) |
||||
{ |
||||
if (e.Key == Key.Enter) { |
||||
Ok(); |
||||
e.Handled = true; |
||||
} else if (e.Key == Key.Up) { |
||||
uxList.SelectedIndex = Math.Max(0, uxList.SelectedIndex - 1); |
||||
e.Handled = true; |
||||
} else if (e.Key == Key.Down) { |
||||
uxList.SelectedIndex++; |
||||
e.Handled = true; |
||||
} |
||||
} |
||||
|
||||
void uxList_MouseDoubleClick(object sender, MouseButtonEventArgs e) |
||||
{ |
||||
var f = e.OriginalSource as FrameworkElement; |
||||
if (f != null && f.DataContext is IClass) { |
||||
Ok(); |
||||
} |
||||
} |
||||
|
||||
void Ok() |
||||
{ |
||||
DialogResult = true; |
||||
Close(); |
||||
} |
||||
} |
||||
|
||||
class ClassListBox : ListBox |
||||
{ |
||||
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
base.OnItemsChanged(e); |
||||
SelectedIndex = 0; |
||||
ScrollIntoView(SelectedItem); |
||||
} |
||||
|
||||
protected override void OnSelectionChanged(SelectionChangedEventArgs e) |
||||
{ |
||||
base.OnSelectionChanged(e); |
||||
ScrollIntoView(SelectedItem); |
||||
} |
||||
} |
||||
|
||||
public class ClassNameConverter : IValueConverter |
||||
{ |
||||
public static ClassNameConverter Instance = new ClassNameConverter(); |
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
var c = value as IClass; |
||||
if (c == null) return value; |
||||
return c.Name + " (" + c.Namespace + ")"; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public class NullToBoolConverter : IValueConverter |
||||
{ |
||||
public static NullToBoolConverter Instance = new NullToBoolConverter(); |
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
return value == null ? false : true; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
@ -1,20 +0,0 @@
@@ -1,20 +0,0 @@
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
|
||||
namespace ICSharpCode.WpfDesign.AddIn |
||||
{ |
||||
public class ChooseClassService |
||||
{ |
||||
public IClass ChooseClass() |
||||
{ |
||||
var core = new ChooseClass(ParserService.CurrentProjectContent); |
||||
var window = new ChooseClassDialog(core); |
||||
|
||||
if (window.ShowDialog().Value) { |
||||
return core.CurrentClass; |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -1,30 +0,0 @@
@@ -1,30 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Windows; |
||||
using System.Windows.Data; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Documents; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Type editor used to edit bool properties.
|
||||
/// </summary>
|
||||
sealed class BooleanEditor : CheckBox |
||||
{ |
||||
/// <summary>
|
||||
/// Creates a new BooleanEditor instance.
|
||||
/// </summary>
|
||||
public BooleanEditor(IPropertyEditorDataProperty property) |
||||
{ |
||||
SetBinding(IsCheckedProperty, PropertyEditorBindingHelper.CreateBinding(this, property)); |
||||
} |
||||
} |
||||
} |
@ -1,49 +0,0 @@
@@ -1,49 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision: 2667$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// wraps a DesignItemDataProperty (with IsEvent=true) for the property editor/grid.
|
||||
/// </summary>
|
||||
sealed class DesignItemDataEvent : DesignItemDataMember, IPropertyEditorDataEvent |
||||
{ |
||||
internal DesignItemDataEvent(DesignItemDataSource ownerDataSource, DesignItemProperty property) |
||||
: base(ownerDataSource, property) |
||||
{ |
||||
Debug.Assert(property.IsEvent); |
||||
} |
||||
|
||||
public event EventHandler HandlerNameChanged { |
||||
add { property.ValueChanged += value; } |
||||
remove { property.ValueChanged -= value; } |
||||
} |
||||
|
||||
public string HandlerName { |
||||
get { |
||||
return (string)property.ValueOnInstance; |
||||
} |
||||
set { |
||||
if (string.IsNullOrEmpty(value)) |
||||
property.Reset(); |
||||
else |
||||
property.SetValue(value); |
||||
} |
||||
} |
||||
|
||||
public void GoToHandler() |
||||
{ |
||||
IEventHandlerService ehs = ownerDataSource.Services.GetService<IEventHandlerService>(); |
||||
if (ehs != null) { |
||||
ehs.CreateEventHandler(ownerDataSource.DesignItem, property); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,61 +0,0 @@
@@ -1,61 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// wraps a DesignItemDataProperty for the property editor/grid.
|
||||
/// </summary>
|
||||
class DesignItemDataMember : IPropertyEditorDataMember |
||||
{ |
||||
protected readonly DesignItemDataSource ownerDataSource; |
||||
protected readonly DesignItemProperty property; |
||||
|
||||
protected DesignItemDataMember(DesignItemDataSource ownerDataSource, DesignItemProperty property) |
||||
{ |
||||
Debug.Assert(ownerDataSource != null); |
||||
Debug.Assert(property != null); |
||||
|
||||
this.ownerDataSource = ownerDataSource; |
||||
this.property = property; |
||||
} |
||||
|
||||
public IPropertyEditorDataSource OwnerDataSource { |
||||
get { return ownerDataSource; } |
||||
} |
||||
|
||||
public string Name { |
||||
get { return property.Name; } |
||||
} |
||||
|
||||
public object GetDescription() |
||||
{ |
||||
IPropertyDescriptionService p = ownerDataSource.DesignItem.Services.GetService<IPropertyDescriptionService>(); |
||||
if (p != null) |
||||
return p.GetDescription(property); |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the type that declares the property.
|
||||
/// </summary>
|
||||
public Type DeclaringType { |
||||
get { return property.DeclaringType; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the property value.
|
||||
/// </summary>
|
||||
public Type ReturnType { |
||||
get { return property.ReturnType; } |
||||
} |
||||
} |
||||
} |
@ -1,96 +0,0 @@
@@ -1,96 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Windows; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// wraps a DesignItemDataProperty (with IsEvent=false) for the property editor/grid.
|
||||
/// </summary>
|
||||
sealed class DesignItemDataProperty : DesignItemDataMember, IPropertyEditorDataProperty |
||||
{ |
||||
internal DesignItemDataProperty(DesignItemDataSource ownerDataSource, DesignItemProperty property) |
||||
: base(ownerDataSource, property) |
||||
{ |
||||
Debug.Assert(!property.IsEvent); |
||||
} |
||||
|
||||
public string Category { |
||||
get { return property.Category; } |
||||
} |
||||
|
||||
public System.ComponentModel.TypeConverter TypeConverter { |
||||
get { return property.TypeConverter; } |
||||
} |
||||
|
||||
public bool IsSet { |
||||
get { |
||||
return property.IsSet; |
||||
} |
||||
set { |
||||
if (value != property.IsSet) { |
||||
if (value) { |
||||
// copy default value to local value
|
||||
property.SetValue(property.ValueOnInstance); |
||||
} else { |
||||
property.Reset(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public event EventHandler IsSetChanged { |
||||
add { property.IsSetChanged += value; } |
||||
remove { property.IsSetChanged -= value; } |
||||
} |
||||
|
||||
public bool IsAmbiguous { |
||||
get { return false; } |
||||
} |
||||
|
||||
public object Value { |
||||
get { |
||||
return property.ValueOnInstance; |
||||
} |
||||
set { |
||||
property.SetValue(value); |
||||
} |
||||
} |
||||
|
||||
public event EventHandler ValueChanged { |
||||
add { property.ValueChanged += value; } |
||||
remove { property.ValueChanged -= value; } |
||||
} |
||||
|
||||
public bool CanUseCustomExpression { |
||||
get { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
public void SetCustomExpression(string expression) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates a UIElement that can edit the property value.
|
||||
/// </summary>
|
||||
public UIElement CreateEditor() |
||||
{ |
||||
EditorManager manager = ownerDataSource.Services.GetService<EditorManager>(); |
||||
if (manager != null) { |
||||
return manager.CreateEditor(this); |
||||
} else { |
||||
return new FallbackEditor(this); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,206 +0,0 @@
@@ -1,206 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
using System.Diagnostics; |
||||
using System.Windows; |
||||
using System.Windows.Media; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Implements IPropertyEditorDataSource accessing the properties on a DesignItem.
|
||||
/// </summary>
|
||||
public sealed class DesignItemDataSource : IPropertyEditorDataSource |
||||
{ |
||||
readonly DesignItem item; |
||||
readonly List<IPropertyEditorDataProperty> properties = new List<IPropertyEditorDataProperty>(); |
||||
readonly List<IPropertyEditorDataEvent> events = new List<IPropertyEditorDataEvent>(); |
||||
|
||||
#region Available properties
|
||||
// cache properties available for a type - retrieving this list takes ~100ms on my machine, so
|
||||
// we cannot do this for every selected component, but must reuse the list
|
||||
static readonly Dictionary<Type, string[]> availableProperties = new Dictionary<Type, string[]>(); |
||||
|
||||
static string[] GetAvailableProperties(Type forType) |
||||
{ |
||||
Debug.Assert(forType != null); |
||||
string[] result; |
||||
lock (availableProperties) { |
||||
if (availableProperties.TryGetValue(forType, out result)) |
||||
return result; |
||||
} |
||||
List<string> names = new List<string>(); |
||||
foreach (PropertyDescriptor p in TypeDescriptor.GetProperties(forType)) { |
||||
if (!p.IsBrowsable) continue; |
||||
if (p.IsReadOnly) continue; |
||||
if (p.Name.Contains(".")) continue; |
||||
names.Add(p.Name); |
||||
} |
||||
result = names.ToArray(); |
||||
lock (availableProperties) { |
||||
availableProperties[forType] = result; |
||||
} |
||||
return result; |
||||
} |
||||
#endregion
|
||||
|
||||
#region Available events
|
||||
// cache events available for a type
|
||||
static readonly Dictionary<Type, string[]> availableEvents = new Dictionary<Type, string[]>(); |
||||
|
||||
static string[] GetAvailableEvents(Type forType) |
||||
{ |
||||
Debug.Assert(forType != null); |
||||
string[] result; |
||||
lock (availableEvents) { |
||||
if (availableEvents.TryGetValue(forType, out result)) |
||||
return result; |
||||
} |
||||
List<string> names = new List<string>(); |
||||
foreach (EventDescriptor p in TypeDescriptor.GetEvents(forType)) { |
||||
if (!p.IsBrowsable) continue; |
||||
if (p.Name.Contains(".")) continue; |
||||
names.Add(p.Name); |
||||
} |
||||
result = names.ToArray(); |
||||
lock (availableEvents) { |
||||
availableEvents[forType] = result; |
||||
} |
||||
return result; |
||||
} |
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new DesignItemDataSource for the specified design item.
|
||||
/// </summary>
|
||||
public DesignItemDataSource(DesignItem item) |
||||
{ |
||||
if (item == null) |
||||
throw new ArgumentNullException("item"); |
||||
this.item = item; |
||||
|
||||
List<DesignItemProperty> designItemProperties = new List<DesignItemProperty>(); |
||||
foreach (string name in GetAvailableProperties(item.ComponentType)) { |
||||
designItemProperties.Add(item.Properties[name]); |
||||
} |
||||
foreach (string name in GetAvailableEvents(item.ComponentType)) { |
||||
designItemProperties.Add(item.Properties[name]); |
||||
} |
||||
designItemProperties.AddRange(item.Properties); |
||||
|
||||
foreach (DesignItemProperty p in designItemProperties.Distinct()) { |
||||
if (p.IsEvent) { |
||||
events.Add(new DesignItemDataEvent(this, p)); |
||||
} else { |
||||
properties.Add(new DesignItemDataProperty(this, p)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets a data source for the specified design item.
|
||||
/// This tries to get an existing data source instance (as behavior), or constructs a new
|
||||
/// DesignItemDataSource instance if that fails.
|
||||
/// </summary>
|
||||
public static IPropertyEditorDataSource GetDataSourceForDesignItem(DesignItem item) |
||||
{ |
||||
return item.GetBehavior<IPropertyEditorDataSource>() ?? new DesignItemDataSource(item); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets a data source for the specified design item.
|
||||
/// This tries to get an existing data source instance (as behavior), or constructs a new
|
||||
/// DesignItemDataSource instance if that fails.
|
||||
/// </summary>
|
||||
public static IPropertyEditorDataSource GetDataSourceForDesignItems(ICollection<DesignItem> items) |
||||
{ |
||||
IPropertyEditorDataSource[] sources = new IPropertyEditorDataSource[items.Count]; |
||||
DesignContext context = null; |
||||
int i = 0; |
||||
foreach (DesignItem item in items) { |
||||
if (context == null) |
||||
context = item.Context; |
||||
else if (context != item.Context) |
||||
throw new DesignerException("All specified items must use the same design context!"); |
||||
|
||||
sources[i++] = GetDataSourceForDesignItem(item); |
||||
} |
||||
return MultipleSelectionDataSource.CreateDataSource(context != null ? context.Services : null, sources); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the design item for which this DesignItemDataSource was created.
|
||||
/// </summary>
|
||||
public DesignItem DesignItem { |
||||
get { return item; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public string Name { |
||||
get { return item.Name ?? ""; } |
||||
set { item.Name = value; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Is raised when the name of the design item changes.
|
||||
/// </summary>
|
||||
public event EventHandler NameChanged { |
||||
add { item.NameChanged += value; } |
||||
remove { item.NameChanged -= value; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public string Type { |
||||
get { |
||||
return item.ComponentType.Name; |
||||
} |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public ImageSource Icon { |
||||
get { return null; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public ICollection<IPropertyEditorDataProperty> Properties { |
||||
get { return properties.AsReadOnly(); } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public ICollection<IPropertyEditorDataEvent> Events { |
||||
get { return events.AsReadOnly(); } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public bool CanAddAttachedProperties { |
||||
get { |
||||
return item.Component is DependencyObject; |
||||
} |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public ServiceContainer Services { |
||||
get { return item.Services; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public Brush CreateThumbnailBrush() |
||||
{ |
||||
if (item.View != null) { |
||||
VisualBrush b = new VisualBrush(item.View); |
||||
b.AutoLayoutContent = false; |
||||
return b; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,120 +0,0 @@
@@ -1,120 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.ComponentModel; |
||||
using System.Diagnostics; |
||||
using System.Collections.Generic; |
||||
using System.Reflection; |
||||
using System.Windows; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Manages registered type and property editors.
|
||||
/// </summary>
|
||||
public sealed class EditorManager |
||||
{ |
||||
// property return type => editor type
|
||||
Dictionary<Type, Type> _typeEditors = new Dictionary<Type, Type>(); |
||||
// property full name => editor type
|
||||
Dictionary<string, Type> _propertyEditors = new Dictionary<string, Type>(); |
||||
|
||||
/// <summary>
|
||||
/// Creates an editor for the specified property.
|
||||
/// </summary>
|
||||
public UIElement CreateEditor(IPropertyEditorDataProperty property) |
||||
{ |
||||
try { |
||||
return (UIElement)Activator.CreateInstance(GetEditorType(property), property); |
||||
} catch (Exception ex) { |
||||
Debug.WriteLine(ex.ToString()); |
||||
throw; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates the fallback editor for the specified property.
|
||||
/// </summary>
|
||||
public static UIElement CreateFallbackEditor(IPropertyEditorDataProperty property) |
||||
{ |
||||
return (UIElement)Activator.CreateInstance(GetFallbackEditorType(property), property); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the editor that can edit the specified property.
|
||||
/// </summary>
|
||||
public Type GetEditorType(IPropertyEditorDataProperty property) |
||||
{ |
||||
if (property == null) |
||||
throw new ArgumentNullException("property"); |
||||
|
||||
Type editorType; |
||||
if (_propertyEditors.TryGetValue(property.DeclaringType.FullName + "." + property.Name, out editorType)) |
||||
return editorType; |
||||
else if (_typeEditors.TryGetValue(property.ReturnType, out editorType)) |
||||
return editorType; |
||||
else |
||||
return GetFallbackEditorType(property); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the fallback editor used for the specified property.
|
||||
/// </summary>
|
||||
public static Type GetFallbackEditorType(IPropertyEditorDataProperty property) |
||||
{ |
||||
if (property == null) |
||||
throw new ArgumentNullException("property"); |
||||
|
||||
Type returnType = property.ReturnType; |
||||
if (returnType.IsEnum) { |
||||
return typeof(StandardValuesComboBoxEditor); |
||||
} else if (returnType == typeof(bool)) { |
||||
return typeof(BooleanEditor); |
||||
} else { |
||||
TypeConverter c = property.TypeConverter; |
||||
if (c != null && c.CanConvertFrom(typeof(string)) && c.CanConvertTo(typeof(string))) |
||||
return typeof(TextBoxEditor); |
||||
else |
||||
return typeof(FallbackEditor); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Registers property editors defined in the specified assembly.
|
||||
/// </summary>
|
||||
public void RegisterAssembly(Assembly assembly) |
||||
{ |
||||
if (assembly == null) |
||||
throw new ArgumentNullException("assembly"); |
||||
|
||||
foreach (Type type in assembly.GetExportedTypes()) { |
||||
foreach (TypeEditorAttribute editorAttribute in type.GetCustomAttributes(typeof(TypeEditorAttribute), false)) { |
||||
CheckValidEditor(type); |
||||
_typeEditors[editorAttribute.SupportedPropertyType] = type; |
||||
} |
||||
foreach (PropertyEditorAttribute editorAttribute in type.GetCustomAttributes(typeof(PropertyEditorAttribute), false)) { |
||||
CheckValidEditor(type); |
||||
string propertyName = editorAttribute.PropertyDeclaringType.FullName + "." + editorAttribute.PropertyName; |
||||
_propertyEditors[propertyName] = type; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static readonly Type[] typeArrayWithPropertyEditorDataProperty = { typeof(IPropertyEditorDataProperty) }; |
||||
|
||||
static void CheckValidEditor(Type type) |
||||
{ |
||||
if (!typeof(UIElement).IsAssignableFrom(type)) { |
||||
throw new DesignerException("Editor types must derive from UIElement!"); |
||||
} |
||||
if (type.GetConstructor(typeArrayWithPropertyEditorDataProperty) == null) { |
||||
throw new DesignerException("Editor types must have a constructor that takes a IPropertyEditorDataProperty as argument!"); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,69 +0,0 @@
@@ -1,69 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Documents; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// The type editor used when no other type editor could be found.
|
||||
/// </summary>
|
||||
[TypeEditor(typeof(object))] |
||||
public sealed class FallbackEditor : TextBlock |
||||
{ |
||||
readonly IPropertyEditorDataProperty property; |
||||
|
||||
/// <summary>
|
||||
/// Creates a new FallbackEditor instance for the specified property.
|
||||
/// </summary>
|
||||
public FallbackEditor(IPropertyEditorDataProperty property) |
||||
{ |
||||
if (property == null) |
||||
throw new ArgumentNullException("property"); |
||||
|
||||
this.property = property; |
||||
|
||||
this.TextTrimming = TextTrimming.CharacterEllipsis; |
||||
PropertyEditorBindingHelper.AddValueChangedEventHandler(this, property, OnValueChanged); |
||||
OnValueChanged(null, null); |
||||
} |
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] |
||||
void OnValueChanged(object sender, EventArgs e) |
||||
{ |
||||
if (property.IsSet) { |
||||
this.FontWeight = FontWeights.Bold; |
||||
} else { |
||||
this.FontWeight = FontWeights.Regular; |
||||
} |
||||
if (property.IsAmbiguous) { |
||||
this.Text = ""; |
||||
} else { |
||||
object val = property.Value; |
||||
if (val == null) { |
||||
this.Text = "null"; |
||||
this.FontStyle = FontStyles.Italic; |
||||
} else { |
||||
this.FontStyle = FontStyles.Normal; |
||||
try { |
||||
this.Text = val.ToString(); |
||||
} catch (Exception ex) { |
||||
this.FontWeight = FontWeights.Regular; |
||||
Inlines.Clear(); |
||||
Inlines.Add(new Italic(new Run(ex.GetType().Name))); |
||||
Inlines.Add(" "); |
||||
Inlines.Add(ex.Message); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,178 +0,0 @@
@@ -1,178 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
using System.Windows.Media; |
||||
using System.Windows; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Interface for data sources used by the property editor to display the list of properties.
|
||||
/// </summary>
|
||||
public interface IPropertyEditorDataSource |
||||
{ |
||||
/// <summary>
|
||||
/// Gets/Sets the name of the item. Returns null when the item does not support having a name.
|
||||
/// </summary>
|
||||
string Name { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Is raised whenever the Name property changes value.
|
||||
/// </summary>
|
||||
event EventHandler NameChanged; |
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the item (for display only).
|
||||
/// </summary>
|
||||
string Type { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the icon of the item (for display only)
|
||||
/// </summary>
|
||||
ImageSource Icon { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of properties.
|
||||
/// </summary>
|
||||
ICollection<IPropertyEditorDataProperty> Properties { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of events.
|
||||
/// </summary>
|
||||
ICollection<IPropertyEditorDataEvent> Events { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets if adding attached properties is supported.
|
||||
/// </summary>
|
||||
bool CanAddAttachedProperties { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the service container attached to this data source.
|
||||
/// </summary>
|
||||
ServiceContainer Services { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets a brush used as a preview for the data source.
|
||||
/// </summary>
|
||||
Brush CreateThumbnailBrush(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a property or event inside a <see cref="IPropertyEditorDataSource"/>.
|
||||
/// </summary>
|
||||
public interface IPropertyEditorDataMember |
||||
{ |
||||
/// <summary>
|
||||
/// Gets the data source that own this property.
|
||||
/// </summary>
|
||||
IPropertyEditorDataSource OwnerDataSource { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the property.
|
||||
/// </summary>
|
||||
string Name { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the type that declares the property.
|
||||
/// </summary>
|
||||
Type DeclaringType { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the property value / the type of the event delegate.
|
||||
/// </summary>
|
||||
Type ReturnType { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the property. The returned object should be something that
|
||||
/// can be used as Content for a WPF tooltip.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] |
||||
object GetDescription(); // is not a property because it can create a new instance on every call
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a property inside a <see cref="IPropertyEditorDataSource"/>.
|
||||
/// </summary>
|
||||
public interface IPropertyEditorDataProperty : IPropertyEditorDataMember |
||||
{ |
||||
/// <summary>
|
||||
/// Gets the category this property uses.
|
||||
/// </summary>
|
||||
string Category { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the type converter used to convert property values to/from string.
|
||||
/// </summary>
|
||||
TypeConverter TypeConverter { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets if the property has been assigned a local value.
|
||||
/// Setting this property to false has the effect of resetting the value, setting it to true
|
||||
/// copies the default value to a local value.
|
||||
/// </summary>
|
||||
bool IsSet { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Is raised when the IsSet property has changed.
|
||||
/// </summary>
|
||||
event EventHandler IsSetChanged; |
||||
|
||||
/// <summary>
|
||||
/// Gets if the property value is ambiguous.
|
||||
/// </summary>
|
||||
bool IsAmbiguous { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the value of the property.
|
||||
/// </summary>
|
||||
object Value { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Is raised when the Value property has changed.
|
||||
/// </summary>
|
||||
event EventHandler ValueChanged; |
||||
|
||||
/// <summary>
|
||||
/// Gets if using a custom expression is supported.
|
||||
/// </summary>
|
||||
bool CanUseCustomExpression { get; } |
||||
|
||||
/// <summary>
|
||||
/// Sets a custom expression.
|
||||
/// </summary>
|
||||
void SetCustomExpression(string expression); |
||||
|
||||
/// <summary>
|
||||
/// Creates a UIElement that can edit the property value.
|
||||
/// </summary>
|
||||
UIElement CreateEditor(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents an event inside a <see cref="IPropertyEditorDataSource"/>.
|
||||
/// </summary>
|
||||
public interface IPropertyEditorDataEvent : IPropertyEditorDataMember |
||||
{ |
||||
/// <summary>
|
||||
/// Gets/Sets the name of the event handler.
|
||||
/// </summary>
|
||||
string HandlerName { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Is raised when the HandlerName property has changed.
|
||||
/// </summary>
|
||||
event EventHandler HandlerNameChanged; |
||||
|
||||
/// <summary>
|
||||
/// Goes to the event handler, creating it when necessary.
|
||||
/// </summary>
|
||||
void GoToHandler(); |
||||
} |
||||
} |
@ -1,230 +0,0 @@
@@ -1,230 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
sealed class MultipleSelectionDataProperty : IPropertyEditorDataProperty |
||||
{ |
||||
readonly MultipleSelectionDataSource ownerDataSource; |
||||
readonly IPropertyEditorDataProperty[] data; |
||||
|
||||
public MultipleSelectionDataProperty(MultipleSelectionDataSource ownerDataSource, IPropertyEditorDataProperty[] data) |
||||
{ |
||||
Debug.Assert(ownerDataSource != null); |
||||
Debug.Assert(data != null); |
||||
Debug.Assert(data.Length >= 2); |
||||
|
||||
this.ownerDataSource = ownerDataSource; |
||||
this.data = data; |
||||
} |
||||
|
||||
#region IsSet + IsSetChanged
|
||||
EventHandler isSetChangedHandlers; |
||||
bool cachedIsSet; |
||||
|
||||
public event EventHandler IsSetChanged { |
||||
add { |
||||
if (isSetChangedHandlers == null) { |
||||
cachedIsSet = GetIsSetInternal(); |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
p.IsSetChanged += OnIsSetChanged; |
||||
} |
||||
} |
||||
isSetChangedHandlers += value; |
||||
} |
||||
remove { |
||||
isSetChangedHandlers -= value; |
||||
if (isSetChangedHandlers == null) { |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
p.IsSetChanged -= OnIsSetChanged; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void OnIsSetChanged(object sender, EventArgs e) |
||||
{ |
||||
bool newIsSet = GetIsSetInternal(); |
||||
if (newIsSet != cachedIsSet) { |
||||
cachedIsSet = newIsSet; |
||||
isSetChangedHandlers(this, e); |
||||
} |
||||
} |
||||
|
||||
bool GetIsSetInternal() |
||||
{ |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
if (p.IsSet) |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public bool IsSet { |
||||
get { |
||||
if (isSetChangedHandlers != null) |
||||
return cachedIsSet; |
||||
else |
||||
return GetIsSetInternal(); |
||||
} |
||||
set { |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
p.IsSet = value; |
||||
} |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region Value
|
||||
EventHandler valueChangedHandlers; |
||||
object cachedValue; |
||||
bool cachedIsAmbiguous; |
||||
/// <summary>0 = don't prevent, 1 = prevent, 2 = prevented</summary>
|
||||
byte preventOnValueChanged; |
||||
|
||||
public event EventHandler ValueChanged { |
||||
add { |
||||
if (valueChangedHandlers == null) { |
||||
cachedValue = GetValueInternal(); |
||||
cachedIsAmbiguous = GetIsAmbiguousInternal(); |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
p.ValueChanged += OnValueChanged; |
||||
} |
||||
} |
||||
valueChangedHandlers += value; |
||||
} |
||||
remove { |
||||
valueChangedHandlers -= value; |
||||
if (valueChangedHandlers == null) { |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
p.ValueChanged -= OnValueChanged; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void OnValueChanged(object sender, EventArgs e) |
||||
{ |
||||
if (preventOnValueChanged > 0) { |
||||
preventOnValueChanged = 2; |
||||
return; |
||||
} |
||||
cachedValue = GetValueInternal(); |
||||
cachedIsAmbiguous = GetIsAmbiguousInternal(); |
||||
valueChangedHandlers(this, e); |
||||
} |
||||
|
||||
object GetValueInternal() |
||||
{ |
||||
object val = data[0].Value; |
||||
for (int i = 1; i < data.Length; i++) { |
||||
if (!object.Equals(data[i].Value, val)) |
||||
return null; |
||||
} |
||||
return val; |
||||
} |
||||
|
||||
bool GetIsAmbiguousInternal() |
||||
{ |
||||
object val = data[0].Value; |
||||
for (int i = 1; i < data.Length; i++) { |
||||
if (!object.Equals(data[i].Value, val)) |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public object Value { |
||||
get { |
||||
if (valueChangedHandlers != null) |
||||
return cachedValue; |
||||
else |
||||
return GetValueInternal(); |
||||
} |
||||
set { |
||||
preventOnValueChanged = 1; |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
p.Value = value; |
||||
} |
||||
if (preventOnValueChanged == 2) { |
||||
preventOnValueChanged = 0; |
||||
OnValueChanged(null, EventArgs.Empty); |
||||
} |
||||
preventOnValueChanged = 0; |
||||
} |
||||
} |
||||
|
||||
public bool IsAmbiguous { |
||||
get { |
||||
if (valueChangedHandlers != null) |
||||
return cachedIsAmbiguous; |
||||
else |
||||
return GetIsAmbiguousInternal(); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
public IPropertyEditorDataSource OwnerDataSource { |
||||
get { return ownerDataSource; } |
||||
} |
||||
|
||||
public string Category { |
||||
get { return data[0].Category; } |
||||
} |
||||
|
||||
public string Name { |
||||
get { return data[0].Name; } |
||||
} |
||||
|
||||
public Type ReturnType { |
||||
get { return data[0].ReturnType; } |
||||
} |
||||
|
||||
public Type DeclaringType { |
||||
get { return data[0].DeclaringType; } |
||||
} |
||||
|
||||
public System.ComponentModel.TypeConverter TypeConverter { |
||||
get { return data[0].TypeConverter; } |
||||
} |
||||
|
||||
public object GetDescription() |
||||
{ |
||||
return data[0].GetDescription(); |
||||
} |
||||
|
||||
public bool CanUseCustomExpression { |
||||
get { |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
if (!p.CanUseCustomExpression) |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
public void SetCustomExpression(string expression) |
||||
{ |
||||
foreach (IPropertyEditorDataProperty p in data) { |
||||
p.SetCustomExpression(expression); |
||||
} |
||||
} |
||||
|
||||
public System.Windows.UIElement CreateEditor() |
||||
{ |
||||
EditorManager manager = ownerDataSource.Services.GetService<EditorManager>(); |
||||
if (manager != null) { |
||||
return manager.CreateEditor(this); |
||||
} else { |
||||
return new FallbackEditor(this); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,144 +0,0 @@
@@ -1,144 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Windows.Media; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Implements IPropertyEditorDataSource by combining the information from multiple data sources.
|
||||
/// </summary>
|
||||
public sealed class MultipleSelectionDataSource : IPropertyEditorDataSource |
||||
{ |
||||
/// <summary>
|
||||
/// Creates a data source for a collection of data sources.
|
||||
/// </summary>
|
||||
/// <param name="services">The service container to use.</param>
|
||||
/// <param name="sources">The collection of data sources.</param>
|
||||
/// <returns>
|
||||
/// <c>null</c>, if sources is <c>null</c> or empty.
|
||||
/// <c>sources[0]</c>, if sources.Count == 1.
|
||||
/// A new MultiSelectionDataSource, if sources.Count >= 2.
|
||||
/// </returns>
|
||||
public static IPropertyEditorDataSource CreateDataSource(ServiceContainer services, ICollection<IPropertyEditorDataSource> sources) |
||||
{ |
||||
if (sources == null || sources.Count == 0) { |
||||
return null; |
||||
} else if (sources.Count == 1) { |
||||
foreach (IPropertyEditorDataSource s in sources) { |
||||
return s; |
||||
} |
||||
throw new InvalidOperationException(); |
||||
} else { |
||||
return new MultipleSelectionDataSource(services, sources); |
||||
} |
||||
} |
||||
|
||||
|
||||
readonly ServiceContainer services; |
||||
readonly IPropertyEditorDataSource[] data; |
||||
readonly List<IPropertyEditorDataProperty> properties = new List<IPropertyEditorDataProperty>(); |
||||
|
||||
/// <summary>
|
||||
/// Creates a new MultiSelectionDataSource instance.
|
||||
/// </summary>
|
||||
public MultipleSelectionDataSource(ServiceContainer services, ICollection<IPropertyEditorDataSource> sources) |
||||
{ |
||||
this.services = services; |
||||
if (sources == null) |
||||
throw new ArgumentNullException("sources"); |
||||
data = sources.ToArray(); |
||||
if (data.Length < 2) |
||||
throw new ArgumentException("The collection must have at least 2 items!"); |
||||
|
||||
foreach (IPropertyEditorDataProperty property in data[0].Properties) { |
||||
IPropertyEditorDataProperty[] properties = new IPropertyEditorDataProperty[data.Length]; |
||||
properties[0] = property; |
||||
for (int i = 1; i < data.Length; i++) { |
||||
foreach (IPropertyEditorDataProperty p in data[i].Properties) { |
||||
if (p.Name == property.Name && p.ReturnType == property.ReturnType) { |
||||
properties[i] = p; |
||||
break; |
||||
} |
||||
} |
||||
if (properties[i] == null) { |
||||
properties = null; // could not find the property for all data sources
|
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (properties != null) { |
||||
this.properties.Add(new MultipleSelectionDataProperty(this, properties)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Is never raised because Name cannot change.
|
||||
/// </summary>
|
||||
public event EventHandler NameChanged { |
||||
add { } remove { } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Always returns null. The setter throws an exception.
|
||||
/// </summary>
|
||||
public string Name { |
||||
get { return null; } |
||||
set { throw new NotSupportedException(); } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the selected objects.
|
||||
/// </summary>
|
||||
public string Type { |
||||
get { return "multiple selection"; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the icon of the selected objects.
|
||||
/// </summary>
|
||||
public System.Windows.Media.ImageSource Icon { |
||||
get { return null; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of properties.
|
||||
/// </summary>
|
||||
public ICollection<IPropertyEditorDataProperty> Properties { |
||||
get { return properties.AsReadOnly(); } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets if adding attached properties is supported.
|
||||
/// </summary>
|
||||
public bool CanAddAttachedProperties { |
||||
get { return false; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the service container used by this data source.
|
||||
/// </summary>
|
||||
public ServiceContainer Services { |
||||
get { return services; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public Brush CreateThumbnailBrush() |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
|
||||
public ICollection<IPropertyEditorDataEvent> Events { |
||||
get { return new IPropertyEditorDataEvent[0]; } |
||||
} |
||||
} |
||||
} |
@ -1,50 +0,0 @@
@@ -1,50 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Attribute to specify that the decorated class is a editor for the specified property.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false)] |
||||
public sealed class PropertyEditorAttribute : Attribute |
||||
{ |
||||
readonly Type propertyDeclaringType; |
||||
readonly string propertyName; |
||||
|
||||
/// <summary>
|
||||
/// Creates a new PropertyEditorAttribute that specifies that the decorated class is a editor
|
||||
/// for the "<paramref name="propertyDeclaringType"/>.<paramref name="propertyName"/>".
|
||||
/// </summary>
|
||||
public PropertyEditorAttribute(Type propertyDeclaringType, string propertyName) |
||||
{ |
||||
if (propertyDeclaringType == null) |
||||
throw new ArgumentNullException("propertyDeclaringType"); |
||||
if (propertyName == null) |
||||
throw new ArgumentNullException("propertyName"); |
||||
this.propertyDeclaringType = propertyDeclaringType; |
||||
this.propertyName = propertyName; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the type that declares the property that the decorated editor supports.
|
||||
/// </summary>
|
||||
public Type PropertyDeclaringType { |
||||
get { return propertyDeclaringType; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the property that the decorated editor supports.
|
||||
/// </summary>
|
||||
public string PropertyName { |
||||
get { return propertyName; } |
||||
} |
||||
} |
||||
} |
||||
|
@ -1,137 +0,0 @@
@@ -1,137 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
// Enable additional Debug.WriteLines for Loading/Unloading event handlers
|
||||
//#define PropertyEditorBindingHelperDebugging
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Globalization; |
||||
using System.Windows; |
||||
using System.Windows.Data; |
||||
using System.ComponentModel; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Provides a static method to create a binding between a dependency property
|
||||
/// and a data property.
|
||||
/// </summary>
|
||||
public static class PropertyEditorBindingHelper |
||||
{ |
||||
/// <summary>
|
||||
/// Registers a value changed event handler for the data property that gets unregistered when the
|
||||
/// editor FrameworkElement is unloaded.
|
||||
/// </summary>
|
||||
public static void AddValueChangedEventHandler(FrameworkElement editor, IPropertyEditorDataProperty dataProperty, EventHandler handler) |
||||
{ |
||||
if (editor == null) |
||||
throw new ArgumentNullException("editor"); |
||||
if (dataProperty == null) |
||||
throw new ArgumentNullException("dataProperty"); |
||||
if (handler == null) |
||||
throw new ArgumentNullException("handler"); |
||||
|
||||
bool isAttached = false; |
||||
|
||||
editor.Loaded += delegate { |
||||
if (!isAttached) { |
||||
isAttached = true; |
||||
dataProperty.ValueChanged += handler; |
||||
} |
||||
}; |
||||
editor.Unloaded += delegate { |
||||
if (isAttached) { |
||||
isAttached = false; |
||||
dataProperty.ValueChanged -= handler; |
||||
} |
||||
}; |
||||
if (editor.IsLoaded) { |
||||
isAttached = true; |
||||
dataProperty.ValueChanged += handler; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Binds editor.property to dataProperty.Value.
|
||||
/// </summary>
|
||||
public static Binding CreateBinding(FrameworkElement editor, IPropertyEditorDataProperty dataProperty) |
||||
{ |
||||
if (editor == null) |
||||
throw new ArgumentNullException("editor"); |
||||
if (dataProperty == null) |
||||
throw new ArgumentNullException("dataProperty"); |
||||
|
||||
#if PropertyEditorBindingHelperDebugging
|
||||
Debug.WriteLine("Create CustomBinding"); |
||||
#endif
|
||||
|
||||
CustomBinding customBinding = new CustomBinding(dataProperty); |
||||
editor.Loaded += customBinding.OnLoaded; |
||||
editor.Unloaded += customBinding.OnUnloaded; |
||||
if (editor.IsLoaded) { |
||||
customBinding.OnLoaded(editor, null); |
||||
} |
||||
|
||||
Binding b = new Binding("BoundValue"); |
||||
b.Source = customBinding; |
||||
b.ConverterCulture = CultureInfo.InvariantCulture; |
||||
return b; |
||||
} |
||||
|
||||
sealed class CustomBinding : INotifyPropertyChanged |
||||
{ |
||||
readonly IPropertyEditorDataProperty dataProperty; |
||||
bool isLoaded; |
||||
|
||||
public CustomBinding(IPropertyEditorDataProperty dataProperty) |
||||
{ |
||||
this.dataProperty = dataProperty; |
||||
} |
||||
|
||||
internal void OnLoaded(object sender, RoutedEventArgs e) |
||||
{ |
||||
#if PropertyEditorBindingHelperDebugging
|
||||
Debug.WriteLine("CustomBinding.OnLoaded (isLoaded=" + isLoaded + ")"); |
||||
#endif
|
||||
|
||||
if (!isLoaded) { |
||||
isLoaded = true; |
||||
dataProperty.ValueChanged += OnValueChanged; |
||||
} |
||||
} |
||||
|
||||
internal void OnUnloaded(object sender, RoutedEventArgs e) |
||||
{ |
||||
#if PropertyEditorBindingHelperDebugging
|
||||
Debug.WriteLine("CustomBinding.OnUnloaded (isLoaded=" + isLoaded + ")"); |
||||
#endif
|
||||
|
||||
if (isLoaded) { |
||||
isLoaded = false; |
||||
dataProperty.ValueChanged -= OnValueChanged; |
||||
} |
||||
} |
||||
|
||||
// Used by the Binding using Reflection.
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] |
||||
public object BoundValue { |
||||
get { return dataProperty.Value; } |
||||
set { dataProperty.Value = value; } |
||||
} |
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged; |
||||
|
||||
void OnValueChanged(object sender, EventArgs e) |
||||
{ |
||||
if (PropertyChanged != null) { |
||||
PropertyChanged(this, new PropertyChangedEventArgs("BoundValue")); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,109 +0,0 @@
@@ -1,109 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Implements IPropertyEditorDataProperty by forwarding all calls to another IPropertyEditorDataProperty.
|
||||
/// </summary>
|
||||
public abstract class ProxyPropertyEditorDataProperty : IPropertyEditorDataProperty |
||||
{ |
||||
readonly IPropertyEditorDataProperty data; |
||||
|
||||
/// <summary></summary>
|
||||
protected ProxyPropertyEditorDataProperty(IPropertyEditorDataProperty data) |
||||
{ |
||||
if (data == null) |
||||
throw new ArgumentNullException("data"); |
||||
this.data = data; |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual event EventHandler IsSetChanged { |
||||
add { data.IsSetChanged += value; } |
||||
remove { data.IsSetChanged -= value; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual event EventHandler ValueChanged { |
||||
add { data.ValueChanged += value; } |
||||
remove { data.ValueChanged -= value; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual IPropertyEditorDataSource OwnerDataSource { |
||||
get { return data.OwnerDataSource; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual string Category { |
||||
get { return data.Category; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual string Name { |
||||
get { return data.Name; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual Type ReturnType { |
||||
get { return data.ReturnType; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual Type DeclaringType { |
||||
get { return data.DeclaringType; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual System.ComponentModel.TypeConverter TypeConverter { |
||||
get { return data.TypeConverter; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual bool IsSet { |
||||
get { return data.IsSet; } |
||||
set { data.IsSet = value; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual bool IsAmbiguous { |
||||
get { return data.IsAmbiguous; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual object Value { |
||||
get { return data.Value; } |
||||
set { data.Value = value; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual bool CanUseCustomExpression { |
||||
get { return data.CanUseCustomExpression; } |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual object GetDescription() |
||||
{ |
||||
return data.GetDescription(); |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual void SetCustomExpression(string expression) |
||||
{ |
||||
data.SetCustomExpression(expression); |
||||
} |
||||
|
||||
/// <summary>See <see cref="IPropertyEditorDataProperty"/></summary>
|
||||
public virtual System.Windows.UIElement CreateEditor() |
||||
{ |
||||
return data.CreateEditor(); |
||||
} |
||||
} |
||||
} |
@ -1,34 +0,0 @@
@@ -1,34 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Windows; |
||||
using System.Windows.Data; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Documents; |
||||
using System.Windows.Media; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Type editor used to edit enum properties.
|
||||
/// </summary>
|
||||
sealed class StandardValuesComboBoxEditor : ComboBox |
||||
{ |
||||
/// <summary>
|
||||
/// Creates a new EnumEditor instance.
|
||||
/// </summary>
|
||||
public StandardValuesComboBoxEditor(IPropertyEditorDataProperty property) |
||||
{ |
||||
foreach (object o in property.TypeConverter.GetStandardValues()) { |
||||
this.Items.Add(o); |
||||
} |
||||
SetBinding(ComboBox.SelectedItemProperty, PropertyEditorBindingHelper.CreateBinding(this, property)); |
||||
} |
||||
} |
||||
} |
@ -1,163 +0,0 @@
@@ -1,163 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.ComponentModel; |
||||
using System.Diagnostics; |
||||
using System.Windows; |
||||
using System.Windows.Data; |
||||
using System.Windows.Media; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Controls.Primitives; |
||||
using System.Windows.Documents; |
||||
using System.Windows.Threading; |
||||
using System.Windows.Input; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Type editor used to edit properties using a text box and the type's default type converter.
|
||||
/// </summary>
|
||||
public sealed class TextBoxEditor : TextBox |
||||
{ |
||||
readonly IPropertyEditorDataProperty property; |
||||
bool isDirty; |
||||
bool hasError; |
||||
|
||||
/// <summary>
|
||||
/// The property edited by the TextBoxEditor.
|
||||
/// </summary>
|
||||
public IPropertyEditorDataProperty Property { |
||||
get { return property; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates a new TextBoxEditor instance.
|
||||
/// </summary>
|
||||
public TextBoxEditor(IPropertyEditorDataProperty property) |
||||
{ |
||||
if (property == null) |
||||
throw new ArgumentNullException("property"); |
||||
|
||||
this.property = property; |
||||
UpdateFromSource(); |
||||
PropertyEditorBindingHelper.AddValueChangedEventHandler( |
||||
this, property, delegate { UpdateFromSource(); } |
||||
); |
||||
} |
||||
|
||||
void UpdateFromSource() |
||||
{ |
||||
if (property.IsAmbiguous) { |
||||
this.Text = ""; |
||||
this.Background = SystemColors.ControlBrush; |
||||
} else { |
||||
this.Text = property.TypeConverter.ConvertToInvariantString(property.Value); |
||||
} |
||||
hasError = false; |
||||
isDirty = false; |
||||
if (property.IsSet) { |
||||
this.Foreground = SystemColors.WindowTextBrush; |
||||
} else { |
||||
this.Foreground = SystemColors.GrayTextBrush; |
||||
} |
||||
} |
||||
|
||||
void SaveValueToSource() |
||||
{ |
||||
isDirty = false; |
||||
hasError = false; |
||||
try { |
||||
property.Value = property.TypeConverter.ConvertFromInvariantString(this.Text); |
||||
} catch (Exception) { |
||||
hasError = true; |
||||
throw; |
||||
} |
||||
if (ValueSaved != null) |
||||
ValueSaved(this, EventArgs.Empty); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Raised when the user changes the property value using this text box.
|
||||
/// </summary>
|
||||
public event EventHandler ValueSaved; |
||||
|
||||
static UIElement DescribeError(Exception ex) |
||||
{ |
||||
return new TextBlock(new Run(ex.Message)); |
||||
} |
||||
|
||||
static void ShowError(ServiceContainer serviceContainer, FrameworkElement control, UIElement errorDescription) |
||||
{ |
||||
IErrorService errorService = null; |
||||
if (serviceContainer != null) |
||||
errorService = serviceContainer.GetService<IErrorService>(); |
||||
|
||||
if (errorService != null) { |
||||
errorService.ShowErrorTooltip(control, errorDescription); |
||||
} |
||||
} |
||||
|
||||
/// <summary/>
|
||||
protected override void OnTextChanged(TextChangedEventArgs e) |
||||
{ |
||||
isDirty = true; |
||||
this.Background = SystemColors.WindowBrush; |
||||
this.Foreground = SystemColors.WindowTextBrush; |
||||
base.OnTextChanged(e); |
||||
} |
||||
|
||||
/// <summary/>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] |
||||
protected override void OnLostFocus(RoutedEventArgs e) |
||||
{ |
||||
if (isDirty) { |
||||
try { |
||||
SaveValueToSource(); |
||||
} catch (Exception ex) { |
||||
Dispatcher.BeginInvoke( |
||||
DispatcherPriority.Normal, new Action<Exception>( |
||||
delegate (Exception exception) { |
||||
if (Focus()) { |
||||
ShowError(property.OwnerDataSource.Services, this, DescribeError(exception)); |
||||
} |
||||
}), ex); |
||||
} |
||||
} else if (hasError) { |
||||
UpdateFromSource(); |
||||
} |
||||
base.OnLostFocus(e); |
||||
} |
||||
|
||||
/// <summary/>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] |
||||
protected override void OnKeyDown(KeyEventArgs e) |
||||
{ |
||||
base.OnKeyDown(e); |
||||
if (e.Handled) return; |
||||
if (e.Key == Key.Enter) { |
||||
string oldText = this.Text; |
||||
try { |
||||
SaveValueToSource(); |
||||
} catch (Exception ex) { |
||||
ShowError(property.OwnerDataSource.Services, this, DescribeError(ex)); |
||||
} |
||||
if (this.Text != oldText) { |
||||
this.SelectAll(); |
||||
} |
||||
e.Handled = true; |
||||
} else if (e.Key == Key.Escape) { |
||||
string oldText = this.Text; |
||||
UpdateFromSource(); |
||||
if (this.Text != oldText) { |
||||
this.SelectAll(); |
||||
} |
||||
e.Handled = true; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,39 +0,0 @@
@@ -1,39 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.WpfDesign.PropertyEditor |
||||
{ |
||||
/// <summary>
|
||||
/// Attribute to specify that the decorated class is a editor for properties with the specified
|
||||
/// return type.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false)] |
||||
public sealed class TypeEditorAttribute : Attribute |
||||
{ |
||||
readonly Type supportedPropertyType; |
||||
|
||||
/// <summary>
|
||||
/// Creates a new TypeEditorAttribute that specifies that the decorated class is a editor
|
||||
/// for properties with the return type "<paramref name="supportedPropertyType"/>".
|
||||
/// </summary>
|
||||
public TypeEditorAttribute(Type supportedPropertyType) |
||||
{ |
||||
if (supportedPropertyType == null) |
||||
throw new ArgumentNullException("supportedPropertyType"); |
||||
this.supportedPropertyType = supportedPropertyType; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the supported property type.
|
||||
/// </summary>
|
||||
public Type SupportedPropertyType { |
||||
get { return supportedPropertyType; } |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue