8 changed files with 477 additions and 8 deletions
@ -0,0 +1,289 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using System.Windows; |
||||
|
using System.Windows.Controls; |
||||
|
using System.Windows.Controls.Primitives; |
||||
|
using System.Collections; |
||||
|
using System.Reflection; |
||||
|
using System.Windows.Input; |
||||
|
|
||||
|
namespace Microsoft.Windows.Controls |
||||
|
{ |
||||
|
public class PrimitiveTypeCollectionEditor : ContentControl |
||||
|
{ |
||||
|
#region Members
|
||||
|
|
||||
|
TextBox _textBox; |
||||
|
Thumb _resizeThumb; |
||||
|
bool _surpressTextChanged; |
||||
|
bool _conversionFailed; |
||||
|
|
||||
|
#endregion //Members
|
||||
|
|
||||
|
#region Properties
|
||||
|
|
||||
|
#region IsOpen
|
||||
|
|
||||
|
public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register("IsOpen", typeof(bool), typeof(PrimitiveTypeCollectionEditor), new UIPropertyMetadata(false, OnIsOpenChanged)); |
||||
|
public bool IsOpen |
||||
|
{ |
||||
|
get { return (bool)GetValue(IsOpenProperty); } |
||||
|
set { SetValue(IsOpenProperty, value); } |
||||
|
} |
||||
|
|
||||
|
private static void OnIsOpenChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
||||
|
{ |
||||
|
PrimitiveTypeCollectionEditor primitiveTypeCollectionEditor = o as PrimitiveTypeCollectionEditor; |
||||
|
if (primitiveTypeCollectionEditor != null) |
||||
|
primitiveTypeCollectionEditor.OnIsOpenChanged((bool)e.OldValue, (bool)e.NewValue); |
||||
|
} |
||||
|
|
||||
|
protected virtual void OnIsOpenChanged(bool oldValue, bool newValue) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#endregion //IsOpen
|
||||
|
|
||||
|
#region ItemsSource
|
||||
|
|
||||
|
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IList), typeof(PrimitiveTypeCollectionEditor), new UIPropertyMetadata(null, OnItemsSourceChanged)); |
||||
|
public IList ItemsSource |
||||
|
{ |
||||
|
get { return (IList)GetValue(ItemsSourceProperty); } |
||||
|
set { SetValue(ItemsSourceProperty, value); } |
||||
|
} |
||||
|
|
||||
|
private static void OnItemsSourceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
||||
|
{ |
||||
|
PrimitiveTypeCollectionEditor primitiveTypeCollectionEditor = o as PrimitiveTypeCollectionEditor; |
||||
|
if (primitiveTypeCollectionEditor != null) |
||||
|
primitiveTypeCollectionEditor.OnItemsSourceChanged((IList)e.OldValue, (IList)e.NewValue); |
||||
|
} |
||||
|
|
||||
|
protected virtual void OnItemsSourceChanged(IList oldValue, IList newValue) |
||||
|
{ |
||||
|
if (newValue == null) |
||||
|
return; |
||||
|
|
||||
|
if (ItemsSourceType == null) |
||||
|
ItemsSourceType = newValue.GetType(); |
||||
|
|
||||
|
if (ItemType == null) |
||||
|
ItemType = newValue.GetType().GetGenericArguments()[0]; |
||||
|
|
||||
|
if (newValue.Count > 0) |
||||
|
SetText(newValue); |
||||
|
} |
||||
|
|
||||
|
#endregion //ItemsSource
|
||||
|
|
||||
|
public static readonly DependencyProperty ItemsSourceTypeProperty = DependencyProperty.Register("ItemsSourceType", typeof(Type), typeof(PrimitiveTypeCollectionEditor), new UIPropertyMetadata(null)); |
||||
|
public Type ItemsSourceType |
||||
|
{ |
||||
|
get { return (Type)GetValue(ItemsSourceTypeProperty); } |
||||
|
set { SetValue(ItemsSourceTypeProperty, value); } |
||||
|
} |
||||
|
|
||||
|
public static readonly DependencyProperty ItemTypeProperty = DependencyProperty.Register("ItemType", typeof(Type), typeof(PrimitiveTypeCollectionEditor), new UIPropertyMetadata(null)); |
||||
|
public Type ItemType |
||||
|
{ |
||||
|
get { return (Type)GetValue(ItemTypeProperty); } |
||||
|
set { SetValue(ItemTypeProperty, value); } |
||||
|
} |
||||
|
|
||||
|
#region Text
|
||||
|
|
||||
|
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(PrimitiveTypeCollectionEditor), new UIPropertyMetadata(null, OnTextChanged)); |
||||
|
public string Text |
||||
|
{ |
||||
|
get { return (string)GetValue(TextProperty); } |
||||
|
set { SetValue(TextProperty, value); } |
||||
|
} |
||||
|
|
||||
|
private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
||||
|
{ |
||||
|
PrimitiveTypeCollectionEditor primitiveTypeCollectionEditor = o as PrimitiveTypeCollectionEditor; |
||||
|
if (primitiveTypeCollectionEditor != null) |
||||
|
primitiveTypeCollectionEditor.OnTextChanged((string)e.OldValue, (string)e.NewValue); |
||||
|
} |
||||
|
|
||||
|
protected virtual void OnTextChanged(string oldValue, string newValue) |
||||
|
{ |
||||
|
if (!_surpressTextChanged) |
||||
|
PersistChanges(); |
||||
|
} |
||||
|
|
||||
|
#endregion //Text
|
||||
|
|
||||
|
#endregion //Properties
|
||||
|
|
||||
|
#region Constructors
|
||||
|
|
||||
|
static PrimitiveTypeCollectionEditor() |
||||
|
{ |
||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(PrimitiveTypeCollectionEditor), new FrameworkPropertyMetadata(typeof(PrimitiveTypeCollectionEditor))); |
||||
|
} |
||||
|
|
||||
|
public PrimitiveTypeCollectionEditor() |
||||
|
{ |
||||
|
Keyboard.AddKeyDownHandler(this, OnKeyDown); |
||||
|
Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnMouseDownOutsideCapturedElement); |
||||
|
} |
||||
|
|
||||
|
#endregion //Constructors
|
||||
|
|
||||
|
#region Bass Class Overrides
|
||||
|
|
||||
|
public override void OnApplyTemplate() |
||||
|
{ |
||||
|
base.OnApplyTemplate(); |
||||
|
|
||||
|
_textBox = (TextBox)GetTemplateChild("PART_TextBox"); |
||||
|
|
||||
|
if (_resizeThumb != null) |
||||
|
_resizeThumb.DragDelta -= ResizeThumb_DragDelta; |
||||
|
|
||||
|
_resizeThumb = (Thumb)GetTemplateChild("PART_ResizeThumb"); |
||||
|
|
||||
|
if (_resizeThumb != null) |
||||
|
_resizeThumb.DragDelta += ResizeThumb_DragDelta; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e) |
||||
|
{ |
||||
|
double yadjust = this._textBox.Height + e.VerticalChange; |
||||
|
double xadjust = this._textBox.Width + e.HorizontalChange; |
||||
|
|
||||
|
if ((xadjust >= 0) && (yadjust >= 0)) |
||||
|
{ |
||||
|
this._textBox.Width = xadjust; |
||||
|
this._textBox.Height = yadjust; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endregion //Bass Class Overrides
|
||||
|
|
||||
|
#region Event Handlers
|
||||
|
|
||||
|
private void OnKeyDown(object sender, KeyEventArgs e) |
||||
|
{ |
||||
|
switch (e.Key) |
||||
|
{ |
||||
|
case Key.Escape: |
||||
|
case Key.Tab: |
||||
|
{ |
||||
|
CloseEditor(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void OnMouseDownOutsideCapturedElement(object sender, MouseButtonEventArgs e) |
||||
|
{ |
||||
|
CloseEditor(); |
||||
|
} |
||||
|
|
||||
|
#endregion //Event Handlers
|
||||
|
|
||||
|
#region Methods
|
||||
|
|
||||
|
private void CloseEditor() |
||||
|
{ |
||||
|
if (IsOpen) |
||||
|
IsOpen = false; |
||||
|
ReleaseMouseCapture(); |
||||
|
} |
||||
|
|
||||
|
private void PersistChanges() |
||||
|
{ |
||||
|
IList list = ResolveItemsSource(); |
||||
|
if (list == null) |
||||
|
return; |
||||
|
|
||||
|
//the easiest way to persist changes to the source is to just clear the source list and then add all items to it.
|
||||
|
list.Clear(); |
||||
|
|
||||
|
IList items = ResolveItems(); |
||||
|
foreach (var item in items) |
||||
|
{ |
||||
|
list.Add(item); |
||||
|
}; |
||||
|
|
||||
|
// if something went wrong during conversion we want to reload the text to show only valid entries
|
||||
|
if (_conversionFailed) |
||||
|
SetText(list); |
||||
|
} |
||||
|
|
||||
|
private IList ResolveItems() |
||||
|
{ |
||||
|
IList items = new List<object>(); |
||||
|
|
||||
|
if (ItemType == null) |
||||
|
return items; |
||||
|
|
||||
|
string[] textArray = Text.Split('\n'); |
||||
|
|
||||
|
foreach (string s in textArray) |
||||
|
{ |
||||
|
string valueString = s.TrimEnd('\r'); |
||||
|
if (!String.IsNullOrEmpty(valueString)) |
||||
|
{ |
||||
|
object value = null; |
||||
|
try |
||||
|
{ |
||||
|
value = Convert.ChangeType(valueString, ItemType); |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
//a conversion failed
|
||||
|
_conversionFailed = true; |
||||
|
} |
||||
|
|
||||
|
if (value != null) |
||||
|
items.Add(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return items; |
||||
|
} |
||||
|
|
||||
|
private IList ResolveItemsSource() |
||||
|
{ |
||||
|
if (ItemsSource == null) |
||||
|
ItemsSource = CreateItemsSource(); |
||||
|
|
||||
|
return ItemsSource; |
||||
|
} |
||||
|
|
||||
|
private IList CreateItemsSource() |
||||
|
{ |
||||
|
IList list = null; |
||||
|
|
||||
|
if (ItemsSourceType != null) |
||||
|
{ |
||||
|
ConstructorInfo constructor = ItemsSourceType.GetConstructor(Type.EmptyTypes); |
||||
|
list = (IList)constructor.Invoke(null); |
||||
|
} |
||||
|
|
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private void SetText(IEnumerable collection) |
||||
|
{ |
||||
|
_surpressTextChanged = true; |
||||
|
StringBuilder builder = new StringBuilder(); |
||||
|
foreach (object obj2 in collection) |
||||
|
{ |
||||
|
builder.Append(obj2.ToString()); |
||||
|
builder.AppendLine(); |
||||
|
} |
||||
|
Text = builder.ToString().Trim(); |
||||
|
_surpressTextChanged = false; |
||||
|
} |
||||
|
|
||||
|
#endregion //Methods
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Microsoft.Windows.Controls.PropertyGrid.Editors |
||||
|
{ |
||||
|
public class PrimitiveTypeCollectionEditor : TypeEditor<Microsoft.Windows.Controls.PrimitiveTypeCollectionEditor> |
||||
|
{ |
||||
|
protected override void SetControlProperties() |
||||
|
{ |
||||
|
Editor.Content = "(Collection)"; |
||||
|
} |
||||
|
|
||||
|
protected override void SetValueDependencyProperty() |
||||
|
{ |
||||
|
ValueProperty = Microsoft.Windows.Controls.PrimitiveTypeCollectionEditor.ItemsSourceProperty; |
||||
|
} |
||||
|
|
||||
|
public override void Attach(PropertyItem propertyItem) |
||||
|
{ |
||||
|
Editor.ItemsSourceType = propertyItem.PropertyType; |
||||
|
Editor.ItemType = propertyItem.PropertyType.GetGenericArguments()[0]; |
||||
|
base.Attach(propertyItem); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue