Browse Source

New PrimitiveTypeCollectionEditor added. It is used for editing IList<PrimitiveType> such as Int and String. PropertyGrid now uses this editor for editing primitive colleciton types.

pull/1645/head
brianlagunas_cp 15 years ago
parent
commit
cfcb570f14
  1. 7
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/HomeView.xaml
  2. 11
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/HomeView.xaml.cs
  3. 289
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CollectionEditors/Implementation/PrimitiveTypeCollectionEditor.cs
  4. 133
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CollectionEditors/Themes/Generic.xaml
  5. 4
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/ColorEditor.cs
  6. 24
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/PrimitiveTypeCollectionEditor.cs
  7. 15
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs
  8. 2
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

7
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/HomeView.xaml

@ -17,5 +17,12 @@
<!--<extToolkit:PropertyGrid Grid.Column="1" Name="propertyGrid1" SelectedObject="{Binding ElementName=_button}" />-->
<extToolkit:PropertyGrid Grid.Column="1" Name="propertyGrid1" SelectedObject="{Binding ElementName=_listBox, Path=SelectedItem}" />
<!--<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<extToolkit:PrimitiveTypeCollectionEditor x:Name="_editor" Width="150" Content="(Collection)" />
<Button Click="Button_Click">
<Path Stroke="Black" SnapsToDevicePixels="true" StrokeThickness="1" Data="F0 M 0,0 L 6,6 M 0,3 L 3,6 " />
</Button>
</StackPanel>-->
</Grid>
</UserControl>

11
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/HomeView.xaml.cs

@ -24,7 +24,16 @@ namespace Samples.Modules.PropertyGrid.Views
InitializeComponent();
_listBox.Items.Add(new Data() { Name = "Item One" });
_listBox.Items.Add(new Data() { Name = "Item Two" });
//_editor.ItemsSourceType = typeof(List<double>);
//_editor.ItemType = typeof(double);
//_editor.ItemsSource = new List<String>() { "A", "B", "C" };
//_editor.ItemsSource = new List<double>() { 1.0, 2.0, 3.0 };
}
//private void Button_Click(object sender, RoutedEventArgs e)
//{
// MessageBox.Show(_editor.ItemsSource.Count.ToString());
//}
}
public class Data
@ -88,7 +97,7 @@ namespace Samples.Modules.PropertyGrid.Views
_color = value;
}
}
public Data()
{

289
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CollectionEditors/Implementation/PrimitiveTypeCollectionEditor.cs

@ -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
}
}

133
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CollectionEditors/Themes/Generic.xaml

@ -2,8 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Microsoft.Windows.Controls"
xmlns:coreConverters="clr-namespace:Microsoft.Windows.Controls.Core.Converters"
xmlns:chrome="clr-namespace:Microsoft.Windows.Controls.Chromes"
xmlns:propertyGrid="clr-namespace:Microsoft.Windows.Controls.PropertyGrid">
<coreConverters:InverseBoolConverter x:Key="InverseBoolConverter" />
<coreConverters:ObjectTypeToNameConverter x:Key="ObjectTypeToNameConverter" />
<Style x:Key="CollectionEditorButtonStyle" TargetType="{x:Type Button}">
@ -87,4 +89,135 @@
</Setter>
</Style>
<LinearGradientBrush x:Key="PopupDarkBorderBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0"/>
<GradientStop Color="#FF8399A9" Offset="0.375"/>
<GradientStop Color="#FF718597" Offset="0.375"/>
<GradientStop Color="#FF617584" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="PopupBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0" Color="#FFffffff"/>
<GradientStop Offset="1" Color="#FFE8EBED"/>
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<!--Thumb Style-->
<Style x:Key="ThumbStyle1" TargetType="{x:Type Thumb}">
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Ellipse Fill="{TemplateBinding Background}" Height="5" Width="5" Grid.Row="1" Grid.Column="1"/>
<Ellipse Fill="{TemplateBinding Background}" Height="5" Width="5" Grid.Row="0" Grid.Column="1"/>
<Ellipse Fill="{TemplateBinding Background}" Height="5" Width="5" Grid.Row="1" Grid.Column="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid SnapsToDevicePixels="True">
<chrome:ButtonChrome x:Name="ToggleButtonChrome"
CornerRadius="0,2.75,2.75,0"
RenderChecked="{Binding IsOpen, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:PrimitiveTypeCollectionEditor}}"
RenderEnabled="{Binding IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:PrimitiveTypeCollectionEditor}}"
RenderMouseOver="{TemplateBinding IsMouseOver}"
RenderPressed="{TemplateBinding IsPressed}" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Grid x:Name="arrowGlyph" IsHitTestVisible="False" Grid.Column="1" Margin="5">
<Path Width="7" Height="4" Data="M 0,1 C0,1 0,0 0,0 0,0 3,0 3,0 3,0 3,1 3,1 3,1 4,1 4,1 4,1 4,0 4,0 4,0 7,0 7,0 7,0 7,1 7,1 7,1 6,1 6,1 6,1 6,2 6,2 6,2 5,2 5,2 5,2 5,3 5,3 5,3 4,3 4,3 4,3 4,4 4,4 4,4 3,4 3,4 3,4 3,3 3,3 3,3 2,3 2,3 2,3 2,2 2,2 2,2 1,2 1,2 1,2 1,1 1,1 1,1 0,1 0,1 z" Fill="#FF000000"/>
</Grid>
</Grid>
</chrome:ButtonChrome>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:PrimitiveTypeCollectionEditor}">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0" />
<GradientStop Color="#FF8399A9" Offset="0.375" />
<GradientStop Color="#FF718597" Offset="0.375" />
<GradientStop Color="#FF617584" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1,1,0,1" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Padding" Value="2,0,0,0" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PrimitiveTypeCollectionEditor}">
<Grid x:Name="Root">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*"/>
<ColumnDefinition Width="Auto" MinWidth="13"/>
</Grid.ColumnDefinitions>
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
<ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
<ToggleButton x:Name="PART_DropDownButton" Grid.Column="1" IsTabStop="True" MinHeight="22"
IsChecked="{Binding IsOpen, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ToggleButtonStyle}"
IsHitTestVisible="{Binding IsOpen, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource InverseBoolConverter}}"/>
</Grid>
<Popup IsOpen="{Binding IsChecked, ElementName=PART_DropDownButton}" StaysOpen="False"
Placement="Bottom" SnapsToDevicePixels="True" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
<Border BorderThickness="1" Background="{StaticResource PopupBackgroundBrush}" BorderBrush="{StaticResource PopupDarkBorderBrush}">
<Grid>
<TextBox x:Name="PART_TextBox" AcceptsReturn="true" TextWrapping="NoWrap" Padding="{TemplateBinding Padding}" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
Width="{Binding Path=ActualWidth, ElementName=Root}" Height="150"
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}"
Margin="3">
</TextBox>
<Thumb x:Name="PART_ResizeThumb" HorizontalAlignment="Right" VerticalAlignment="Bottom" Cursor="SizeNWSE">
<Thumb.Template>
<ControlTemplate TargetType="{x:Type Thumb}">
<Grid Background="Transparent">
<Path Data="M0.5,6.5 L6.5,0.5 M6.5,3.5 L3.5,6.5" Stroke="Black" StrokeThickness="1" />
</Grid>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

4
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/ColorEditor.cs

@ -5,6 +5,10 @@ namespace Microsoft.Windows.Controls.PropertyGrid.Editors
{
public class ColorEditor : TypeEditor<ColorPicker>
{
protected override void SetControlProperties()
{
Editor.DisplayColorAndName = true;
}
protected override void SetValueDependencyProperty()
{
ValueProperty = ColorPicker.SelectedColorProperty;

24
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/PrimitiveTypeCollectionEditor.cs

@ -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);
}
}
}

15
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs

@ -275,8 +275,11 @@ namespace Microsoft.Windows.Controls.PropertyGrid
//hitting enter on textbox will update value of underlying source
if (this.SelectedProperty != null && e.Key == Key.Enter && e.OriginalSource is TextBox)
{
BindingExpression be = ((TextBox)e.OriginalSource).GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
if (!(e.OriginalSource as TextBox).AcceptsReturn)
{
BindingExpression be = ((TextBox)e.OriginalSource).GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
}
}
}
@ -425,13 +428,11 @@ namespace Microsoft.Windows.Controls.PropertyGrid
{
if (propertyItem.PropertyType.GetInterface("IList") != null)
{
bool isEditable = false;
var t = propertyItem.PropertyType.GetGenericArguments()[0];
if (!t.IsPrimitive && !t.Equals(typeof(String)))
isEditable = true;
editor = new Microsoft.Windows.Controls.PropertyGrid.Editors.CollectionEditor(isEditable);
editor = new Microsoft.Windows.Controls.PropertyGrid.Editors.CollectionEditor();
else
editor = new Microsoft.Windows.Controls.PropertyGrid.Editors.PrimitiveTypeCollectionEditor();
}
else
editor = new TextBlockEditor();

2
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

@ -216,6 +216,7 @@
<Compile Include="MaskedTextBox\Implementation\MaskedTextBox.cs" />
<Compile Include="MessageBox\Implementation\MessageBox.cs" />
<Compile Include="NumericUpDown\Implementation\NumericUpDown.cs" />
<Compile Include="CollectionEditors\Implementation\PrimitiveTypeCollectionEditor.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
@ -252,6 +253,7 @@
<Compile Include="PropertyGrid\Implementation\Editors\ICustomTypeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\IntegerUpDownEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\ITypeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\PrimitiveTypeCollectionEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TextBlockEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TextBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TypeEditor.cs" />

Loading…
Cancel
Save