Browse Source

- MarkupExtension know loading as XamlObject: no difference between <Binding/> and {Binding} syntax.

- Support for NameScopes, Binding
- Remove TreeView dependency from PropertyGrid (now DataTemplates)
- Fixing Outline, XamlFormatter, ME Tokenizer/Parser
- Expremints with EnumBar

Broken: 
- BrushEditor (serialization still required)
- XamlObject.XmlElement must be always consistent
(in the case of ME it's detached from real Xml), during parsing too.

TODO: Designer Itself!

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3329 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Ivan Shumilin 18 years ago
parent
commit
d2b9992a47
  1. 10
      samples/XamlDesigner/App.xaml
  2. 2
      samples/XamlDesigner/Document.cs
  3. 3
      samples/XamlDesigner/DocumentView.xaml
  4. 2
      samples/XamlDesigner/NewFileTemplate.xaml
  5. 63
      samples/XamlDesigner/OutlineNode.cs
  6. 5
      samples/XamlDesigner/TestFiles/3.xaml
  7. 8
      samples/XamlDesigner/Themes/Generic.xaml
  8. 13
      samples/XamlDesigner/XamlDesigner.csproj
  9. 7
      samples/XamlDesigner/XamlFormatter.cs
  10. 46
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml
  11. 7
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/EnumBar.xaml
  12. 112
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/EnumBar.xaml.cs
  13. 26
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/EnumButton.cs
  14. 22
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Converters.cs
  15. 4
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs
  16. 12
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ExtensionMethods.cs
  17. 5
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs
  18. 19
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/BasicMetadata.cs
  19. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditor.cs
  20. 4
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyContextMenu.xaml
  21. 192
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGridView.xaml
  22. 24
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGridView.xaml.cs
  23. 101
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyTreeView.cs
  24. 15
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
  25. 31
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
  26. 9
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/MarkupExtensionTests.cs
  27. 152
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs
  28. 45
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionPrinter.cs
  29. 4
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
  30. 4
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs
  31. 52
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlMarkupValue.cs
  32. 168
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs
  33. 47
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs
  34. 54
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
  35. 233
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
  36. 41
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTextValue.cs
  37. 14
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeResolverProvider.cs
  38. 19
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs
  39. 26
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs

10
samples/XamlDesigner/App.xaml

@ -9,15 +9,5 @@
<Converters:CollapsedWhenFalse x:Key="CollapsedWhenFalse" /> <Converters:CollapsedWhenFalse x:Key="CollapsedWhenFalse" />
<Converters:FalseWhenZero x:Key="FalseWhenZero" /> <Converters:FalseWhenZero x:Key="FalseWhenZero" />
<Style x:Key="TabButtonStyle"
TargetType="ToggleButton">
<Setter Property="Width"
Value="50" />
<Setter Property="ClickMode"
Value="Press" />
<Setter Property="Margin"
Value="3 3 0 3" />
</Style>
</Application.Resources> </Application.Resources>
</Application> </Application>

2
samples/XamlDesigner/Document.cs

@ -203,7 +203,7 @@ namespace ICSharpCode.XamlDesigner
OutlineRoot = null; OutlineRoot = null;
} }
else { else {
OutlineRoot = new OutlineNode(DesignContext.RootItem); OutlineRoot = OutlineNode.Create(DesignContext.RootItem);
} }
UndoService.UndoStackChanged += new EventHandler(UndoService_UndoStackChanged); UndoService.UndoStackChanged += new EventHandler(UndoService_UndoStackChanged);
} }

3
samples/XamlDesigner/DocumentView.xaml

@ -5,10 +5,11 @@
xmlns:Integration="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" xmlns:Integration="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:TextEditor="clr-namespace:ICSharpCode.TextEditor;assembly=ICSharpCode.TextEditor" xmlns:TextEditor="clr-namespace:ICSharpCode.TextEditor;assembly=ICSharpCode.TextEditor"
xmlns:Default="clr-namespace:ICSharpCode.XamlDesigner" xmlns:Default="clr-namespace:ICSharpCode.XamlDesigner"
xmlns:DesignerControls="clr-namespace:ICSharpCode.WpfDesign.Designer.Controls;assembly=ICSharpCode.WpfDesign.Designer"
> >
<DockPanel> <DockPanel>
<Default:EnumBar Value="{Binding Mode}" <DesignerControls:EnumBar Value="{Binding Mode}"
DockPanel.Dock="Bottom"/> DockPanel.Dock="Bottom"/>
<Grid> <Grid>
<Integration:WindowsFormsHost Visibility="{Binding InXamlMode, Converter={StaticResource CollapsedWhenFalse}}"> <Integration:WindowsFormsHost Visibility="{Binding InXamlMode, Converter={StaticResource CollapsedWhenFalse}}">

2
samples/XamlDesigner/NewFileTemplate.xaml

@ -1,4 +1,4 @@
<Window xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation" <Window xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas />
</Window> </Window>

63
samples/XamlDesigner/OutlineNode.cs

@ -6,26 +6,37 @@ using System.ComponentModel;
using ICSharpCode.WpfDesign; using ICSharpCode.WpfDesign;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections; using System.Collections;
using ICSharpCode.WpfDesign.Designer;
namespace ICSharpCode.XamlDesigner namespace ICSharpCode.XamlDesigner
{ {
public class OutlineNode : INotifyPropertyChanged public class OutlineNode : INotifyPropertyChanged
{ {
public OutlineNode(DesignItem designItem) public static OutlineNode Create(DesignItem designItem)
{
OutlineNode node;
if (!outlineNodes.TryGetValue(designItem, out node)) {
node = new OutlineNode(designItem);
outlineNodes[designItem] = node;
}
return node;
}
//TODO: Reset with DesignContext
static Dictionary<DesignItem, OutlineNode> outlineNodes = new Dictionary<DesignItem, OutlineNode>();
OutlineNode(DesignItem designItem)
{ {
DesignItem = designItem; DesignItem = designItem;
UpdateChildren(); UpdateChildren();
//TODO (possible bug) //TODO
DesignItem.NameChanged += new EventHandler(DesignItem_NameChanged); DesignItem.NameChanged += new EventHandler(DesignItem_NameChanged);
DesignItem.PropertyChanged += new PropertyChangedEventHandler(DesignItem_PropertyChanged); DesignItem.PropertyChanged += new PropertyChangedEventHandler(DesignItem_PropertyChanged);
SelectionService.SelectionChanged += new EventHandler<DesignItemCollectionEventArgs>(Selection_SelectionChanged); SelectionService.SelectionChanged += new EventHandler<DesignItemCollectionEventArgs>(Selection_SelectionChanged);
} }
bool freezeChildren;
public DesignItem DesignItem { get; private set; } public DesignItem DesignItem { get; private set; }
public OutlineNode Parent { get; private set; }
public ISelectionService SelectionService { public ISelectionService SelectionService {
get { return DesignItem.Services.Selection; } get { return DesignItem.Services.Selection; }
@ -93,7 +104,6 @@ namespace ICSharpCode.XamlDesigner
void UpdateChildren() void UpdateChildren()
{ {
if (freezeChildren) return;
if (DesignItem.ContentPropertyName != null) { if (DesignItem.ContentPropertyName != null) {
var content = DesignItem.ContentProperty; var content = DesignItem.ContentProperty;
if (content.IsCollection) { if (content.IsCollection) {
@ -109,17 +119,13 @@ namespace ICSharpCode.XamlDesigner
void UpdateChildrenCore(IEnumerable<DesignItem> items) void UpdateChildrenCore(IEnumerable<DesignItem> items)
{ {
var cache = Children.ToDictionary(n => n.DesignItem);
Children.Clear(); Children.Clear();
foreach (var item in items) { foreach (var item in items) {
OutlineNode node; if (ModelTools.CanSelectComponent(item)) {
if (!cache.TryGetValue(item, out node)) { var node = OutlineNode.Create(item);
node = new OutlineNode(item);
}
Children.Add(node); Children.Add(node);
node.Parent = this; }
} }
} }
@ -129,7 +135,7 @@ namespace ICSharpCode.XamlDesigner
if (DesignItem.ContentProperty.IsCollection) { if (DesignItem.ContentProperty.IsCollection) {
foreach (var node in nodes) { foreach (var node in nodes) {
if (!CanAdd(DesignItem.ContentProperty.ReturnType, if (!CanCollectionAdd(DesignItem.ContentProperty.ReturnType,
node.DesignItem.ComponentType)) { node.DesignItem.ComponentType)) {
return false; return false;
} }
@ -143,7 +149,7 @@ namespace ICSharpCode.XamlDesigner
} }
} }
public static bool CanAdd(Type col, Type item) static bool CanCollectionAdd(Type col, Type item)
{ {
var e = col.GetInterface("IEnumerable`1"); var e = col.GetInterface("IEnumerable`1");
if (e != null && e.IsGenericType) { if (e != null && e.IsGenericType) {
@ -155,47 +161,26 @@ namespace ICSharpCode.XamlDesigner
public void Insert(IEnumerable<OutlineNode> nodes, OutlineNode after, bool copy) public void Insert(IEnumerable<OutlineNode> nodes, OutlineNode after, bool copy)
{ {
freezeChildren = true;
if (copy) { if (copy) {
nodes = nodes.Select(n => new OutlineNode(n.DesignItem.Clone())); nodes = nodes.Select(n => OutlineNode.Create(n.DesignItem.Clone()));
} }
else { else {
foreach (var node in nodes) { foreach (var node in nodes) {
Remove(node); node.DesignItem.Remove();
} }
} }
var index = after == null ? 0 : Children.IndexOf(after) + 1; var index = after == null ? 0 : Children.IndexOf(after) + 1;
var tempIndex = index;
foreach (var node in nodes) {
Children.Insert(tempIndex++, node);
node.Parent = this;
}
var content = DesignItem.ContentProperty; var content = DesignItem.ContentProperty;
if (content.IsCollection) { if (content.IsCollection) {
tempIndex = index;
foreach (var node in nodes) { foreach (var node in nodes) {
content.CollectionElements.Insert(tempIndex++, node.DesignItem); content.CollectionElements.Insert(index++, node.DesignItem);
} }
} }
else { else {
content.SetValue(nodes.First().DesignItem); content.SetValue(nodes.First().DesignItem);
} }
freezeChildren = false;
}
void Remove(OutlineNode node)
{
node.DesignItem.Remove();
if (node.Parent != null) {
node.Parent.Children.Remove(node);
node.Parent = null;
}
} }
#region INotifyPropertyChanged Members #region INotifyPropertyChanged Members

5
samples/XamlDesigner/TestFiles/3.xaml

@ -7,5 +7,10 @@
<sys:String x:Key="r1">Title</sys:String> <sys:String x:Key="r1">Title</sys:String>
<sys:String x:Key="r2">Width</sys:String> <sys:String x:Key="r2">Width</sys:String>
</Window.Resources> </Window.Resources>
<StackPanel>
<Button Name="b1"
Width="100"
Content="Button" />
<TextBlock Text="{Binding Path={StaticResource r1}, ElementName=root}" /> <TextBlock Text="{Binding Path={StaticResource r1}, ElementName=root}" />
</StackPanel>
</Window> </Window>

8
samples/XamlDesigner/Themes/Generic.xaml

@ -21,14 +21,6 @@
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type Default:EnumButton}"
BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Margin"
Value="3 3 0 3" />
<Setter Property="MinWidth"
Value="50" />
</Style>
<Brush x:Key="InsertBrush">#FFC73C</Brush> <Brush x:Key="InsertBrush">#FFC73C</Brush>
<Style x:Key="ExpandButtonStyle" <Style x:Key="ExpandButtonStyle"

13
samples/XamlDesigner/XamlDesigner.csproj

@ -111,10 +111,6 @@
<Compile Include="DragListener.cs" /> <Compile Include="DragListener.cs" />
<Compile Include="DragTreeView.cs" /> <Compile Include="DragTreeView.cs" />
<Compile Include="DragTreeViewItem.cs" /> <Compile Include="DragTreeViewItem.cs" />
<Compile Include="EnumButton.cs" />
<Compile Include="EnumBar.xaml.cs">
<DependentUpon>EnumBar.xaml</DependentUpon>
</Compile>
<Compile Include="ExtensionMethods.cs" /> <Compile Include="ExtensionMethods.cs" />
<Compile Include="IconItem.cs" /> <Compile Include="IconItem.cs" />
<Compile Include="MainWindow_Commands.cs" /> <Compile Include="MainWindow_Commands.cs" />
@ -148,10 +144,6 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="EnumBar.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml"> <Page Include="MainWindow.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -166,10 +158,9 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="TestFiles\3.xaml"> <None Include="TestFiles\3.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </None>
<Page Include="Themes\Generic.xaml"> <Page Include="Themes\Generic.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>

7
samples/XamlDesigner/XamlFormatter.cs

@ -37,10 +37,9 @@ namespace ICSharpCode.XamlDesigner
foreach (var c in node.Nodes()) { foreach (var c in node.Nodes()) {
if (c is XElement) { if (c is XElement) {
WalkElement(c as XElement); WalkElement(c as XElement);
} } else {
else {
NewLine(); NewLine();
Append(c.ToString()); Append(c.ToString().Trim());
} }
} }
} }
@ -91,7 +90,7 @@ namespace ICSharpCode.XamlDesigner
nextColumn -= Indenation; nextColumn -= Indenation;
NewLine(); NewLine();
Append("</" + e.Name.LocalName + ">"); Append("</" + name1 + ">");
} }
else { else {
Append(" />"); Append(" />");

46
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml

@ -1,6 +1,6 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:ICSharpCode.WpfDesign.Designer.Controls" xmlns:Controls="clr-namespace:ICSharpCode.WpfDesign.Designer.Controls"
> >
<!-- <!--
This file contains the default styles used by the Controls in ICSharpCode.WpfDesign.Designer.Controls This file contains the default styles used by the Controls in ICSharpCode.WpfDesign.Designer.Controls
@ -10,10 +10,18 @@
<ResourceDictionary Source="NumericUpDown.xaml" /> <ResourceDictionary Source="NumericUpDown.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type src:ResizeThumb}"> <Style TargetType="{x:Type Controls:EnumButton}"
BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Margin"
Value="3 3 0 3" />
<Setter Property="MinWidth"
Value="50" />
</Style>
<Style TargetType="{x:Type Controls:ResizeThumb}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type src:ResizeThumb}"> <ControlTemplate TargetType="{x:Type Controls:ResizeThumb}">
<Rectangle Name="thumbRectangle" <Rectangle Name="thumbRectangle"
Width="7" Height="7" SnapsToDevicePixels="True" Width="7" Height="7" SnapsToDevicePixels="True"
Stroke="Black" Fill="White" RadiusX="1.414" RadiusY="1.414"/> Stroke="Black" Fill="White" RadiusX="1.414" RadiusY="1.414"/>
@ -34,20 +42,20 @@
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type src:SelectionFrame}"> <Style TargetType="{x:Type Controls:SelectionFrame}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type src:SelectionFrame}"> <ControlTemplate TargetType="{x:Type Controls:SelectionFrame}">
<Rectangle Fill="#519ABFE5" Stroke="#FF7A8787" StrokeThickness="1"/> <Rectangle Fill="#519ABFE5" Stroke="#FF7A8787" StrokeThickness="1"/>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type src:ContainerDragHandle}"> <Style TargetType="{x:Type Controls:ContainerDragHandle}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type src:ContainerDragHandle}"> <ControlTemplate TargetType="{x:Type Controls:ContainerDragHandle}">
<Canvas Height="13" Width="13" Name="Canvas" SnapsToDevicePixels="True"> <Canvas Height="13" Width="13" Name="Canvas" SnapsToDevicePixels="True">
<Rectangle Height="13" Width="13" RadiusX="2" RadiusY="2" <Rectangle Height="13" Width="13" RadiusX="2" RadiusY="2"
Fill="#889ABFE5" Name="BorderRectangle" Stroke="#FF7A8FB5" StrokeThickness="1" /> Fill="#889ABFE5" Name="BorderRectangle" Stroke="#FF7A8FB5" StrokeThickness="1" />
@ -67,14 +75,14 @@
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type src:WindowClone}"> <Style TargetType="{x:Type Controls:WindowClone}">
<Setter Property="Width" <Setter Property="Width"
Value="640" /> Value="640" />
<Setter Property="Height" <Setter Property="Height"
Value="480" /> Value="480" />
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type src:WindowClone}"> <ControlTemplate TargetType="{x:Type Controls:WindowClone}">
<Border Background="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1,1,1,1" CornerRadius="5,5,5,5"> <Border Background="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1,1,1,1" CornerRadius="5,5,5,5">
<DockPanel Margin="4,0,4,4"> <DockPanel Margin="4,0,4,4">
<DockPanel Height="26" DockPanel.Dock="Top"> <DockPanel Height="26" DockPanel.Dock="Top">
@ -107,14 +115,14 @@
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type src:ErrorBalloon}"> <Style TargetType="{x:Type Controls:ErrorBalloon}">
<Setter Property="WindowStyle" Value="None"/> <Setter Property="WindowStyle" Value="None"/>
<Setter Property="AllowsTransparency" Value="True"/> <Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="SizeToContent" Value="WidthAndHeight"/> <Setter Property="SizeToContent" Value="WidthAndHeight"/>
<Setter Property="ShowInTaskbar" Value="False"/> <Setter Property="ShowInTaskbar" Value="False"/>
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type src:ErrorBalloon}"> <ControlTemplate TargetType="{x:Type Controls:ErrorBalloon}">
<Grid x:Name="LayoutRoot"> <Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
@ -150,21 +158,21 @@
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type src:GridRailAdorner}"> <Style TargetType="{x:Type Controls:GridRailAdorner}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type src:GridRailAdorner}"> <ControlTemplate TargetType="{x:Type Controls:GridRailAdorner}">
<Rectangle Fill="#302020ff"/> <Rectangle Fill="#302020ff"/>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type src:GridRowSplitterAdorner}"> <Style TargetType="{x:Type Controls:GridRowSplitterAdorner}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type src:GridRowSplitterAdorner}"> <ControlTemplate TargetType="{x:Type Controls:GridRowSplitterAdorner}">
<Grid Height="{x:Static src:GridRailAdorner.SplitterWidth}"> <Grid Height="{x:Static Controls:GridRailAdorner.SplitterWidth}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/> <!-- 10=RailSize --> <ColumnDefinition Width="10"/> <!-- 10=RailSize -->
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
@ -188,11 +196,11 @@
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type src:GridColumnSplitterAdorner}"> <Style TargetType="{x:Type Controls:GridColumnSplitterAdorner}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type src:GridColumnSplitterAdorner}"> <ControlTemplate TargetType="{x:Type Controls:GridColumnSplitterAdorner}">
<Grid Width="{x:Static src:GridRailAdorner.SplitterWidth}"> <Grid Width="{x:Static Controls:GridRailAdorner.SplitterWidth}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="10"/> <!-- 10=RailSize --> <RowDefinition Height="10"/> <!-- 10=RailSize -->
<RowDefinition Height="*"/> <RowDefinition Height="*"/>

7
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/EnumBar.xaml

@ -0,0 +1,7 @@
<UserControl
x:Class="ICSharpCode.WpfDesign.Designer.Controls.EnumBar"
xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel x:Name="uxPanel"
Orientation="Horizontal" />
</UserControl>

112
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/EnumBar.xaml.cs

@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
namespace ICSharpCode.WpfDesign.Designer.Controls
{
public partial class EnumBar
{
public EnumBar()
{
InitializeComponent();
}
Type currentEnumType;
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(EnumBar),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public object Value {
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ContainerProperty =
DependencyProperty.Register("Container", typeof(Panel), typeof(EnumBar));
public Panel Container {
get { return (Panel)GetValue(ContainerProperty); }
set { SetValue(ContainerProperty, value); }
}
public static readonly DependencyProperty ButtonStyleProperty =
DependencyProperty.Register("ButtonStyle", typeof(Style), typeof(EnumBar));
public Style ButtonStyle {
get { return (Style)GetValue(ButtonStyleProperty); }
set { SetValue(ButtonStyleProperty, value); }
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == ValueProperty) {
var type = e.NewValue.GetType();
if (currentEnumType != type) {
currentEnumType = type;
uxPanel.Children.Clear();
foreach (var v in Enum.GetValues(type)) {
var b = new EnumButton();
b.Value = v;
b.Content = Enum.GetName(type, v);
b.SetBinding(StyleProperty, new Binding("ButtonStyle") { Source = this });
b.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(button_PreviewMouseLeftButtonDown);
uxPanel.Children.Add(b);
}
}
UpdateButtons();
UpdateContainer();
} else if (e.Property == ContainerProperty) {
UpdateContainer();
}
}
void UpdateButtons()
{
foreach (EnumButton c in uxPanel.Children) {
if (c.Value.Equals(Value)) {
c.IsChecked = true;
}
else {
c.IsChecked = false;
}
}
}
void UpdateContainer()
{
if (Container != null) {
for (int i = 0; i < uxPanel.Children.Count; i++) {
var c = uxPanel.Children[i] as EnumButton;
if (c.IsChecked.Value)
Container.Children[i].Visibility = Visibility.Visible;
else
Container.Children[i].Visibility = Visibility.Collapsed;
}
}
}
void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Value = (sender as EnumButton).Value;
e.Handled = true;
}
}
}

26
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/EnumButton.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls.Primitives;
using System.Windows;
namespace ICSharpCode.WpfDesign.Designer.Controls
{
public class EnumButton : ToggleButton
{
static EnumButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(EnumButton),
new FrameworkPropertyMetadata(typeof(EnumButton)));
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(EnumButton));
public object Value {
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
}
}

22
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Converters.cs

@ -39,6 +39,21 @@ namespace ICSharpCode.WpfDesign.Designer.Converters
} }
} }
public class CollapsedWhenFalse : IValueConverter
{
public static CollapsedWhenFalse Instance = new CollapsedWhenFalse();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class LevelConverter : IValueConverter public class LevelConverter : IValueConverter
{ {
public static LevelConverter Instance = new LevelConverter(); public static LevelConverter Instance = new LevelConverter();
@ -54,14 +69,13 @@ namespace ICSharpCode.WpfDesign.Designer.Converters
} }
} }
public class CollapsedWhenEmptyCollection : IValueConverter public class CollapsedWhenZero : IValueConverter
{ {
public static CollapsedWhenEmptyCollection Instance = new CollapsedWhenEmptyCollection(); public static CollapsedWhenZero Instance = new CollapsedWhenZero();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
ICollection col = value as ICollection; if (value == null || (int)value == 0) {
if (col != null && col.Count == 0) {
return Visibility.Collapsed; return Visibility.Collapsed;
} }
return Visibility.Visible; return Visibility.Visible;

4
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs

@ -70,7 +70,9 @@ namespace ICSharpCode.WpfDesign.Designer
_scrollViewer.Content = _designPanel; _scrollViewer.Content = _designPanel;
_scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible; _scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
_scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible; _scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible;
this.VisualChild = _scrollViewer; this.VisualChild = _scrollViewer;
this.DataContext = null;
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, OnUndoExecuted, OnUndoCanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, OnUndoExecuted, OnUndoCanExecute));
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, OnRedoExecuted, OnRedoCanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, OnRedoExecuted, OnRedoCanExecute));
@ -122,7 +124,7 @@ namespace ICSharpCode.WpfDesign.Designer
{ {
List<DesignItem> result = new List<DesignItem>(items.Count); List<DesignItem> result = new List<DesignItem>(items.Count);
foreach (DesignItem item in items) { foreach (DesignItem item in items) {
if (ModelTools.IsInDocument(item)) { if (ModelTools.IsInDocument(item) && ModelTools.CanSelectComponent(item)) {
result.Add(item); result.Add(item);
} }
} }

12
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ExtensionMethods.cs

@ -5,6 +5,7 @@ using System.Text;
using System.Reflection; using System.Reflection;
using System.Collections; using System.Collections;
using System.Windows; using System.Windows;
using System.Windows.Media;
namespace ICSharpCode.WpfDesign.Designer namespace ICSharpCode.WpfDesign.Designer
{ {
@ -26,9 +27,18 @@ namespace ICSharpCode.WpfDesign.Designer
{ {
var f = e.OriginalSource as FrameworkElement; var f = e.OriginalSource as FrameworkElement;
if (f != null) { if (f != null) {
return f.DataContext;; return f.DataContext;
} }
return null; return null;
} }
public static T FindAncestor<T>(this DependencyObject d, string name) where T : class
{
while (true) {
if (d == null) return null;
if (d is T && d is FrameworkElement && (d as FrameworkElement).Name == name) return d as T;
d = VisualTreeHelper.GetParent(d);
}
}
} }
} }

5
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs

@ -69,6 +69,11 @@ namespace ICSharpCode.WpfDesign.Designer
&& b.CanPlace(items, PlacementType.Delete, PlacementAlignment.Center); && b.CanPlace(items, PlacementType.Delete, PlacementAlignment.Center);
} }
public static bool CanSelectComponent(DesignItem item)
{
return item.View != null;
}
/// <summary> /// <summary>
/// Deletes the specified components from their parent containers. /// Deletes the specified components from their parent containers.
/// If the deleted components are currently selected, they are deselected before they are deleted. /// If the deleted components are currently selected, they are deselected before they are deleted.

19
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/BasicMetadata.cs

@ -12,6 +12,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D; using System.Windows.Media.Media3D;
using System.Windows.Shapes; using System.Windows.Shapes;
using System.Windows.Media.Animation; using System.Windows.Media.Animation;
using System.Windows.Data;
namespace ICSharpCode.WpfDesign.Designer.PropertyGrid namespace ICSharpCode.WpfDesign.Designer.PropertyGrid
{ {
@ -543,6 +544,24 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid
Metadata.AddValueRange(Track.ViewportSizeProperty, 0, double.PositiveInfinity); Metadata.AddValueRange(Track.ViewportSizeProperty, 0, double.PositiveInfinity);
Metadata.AddValueRange(UIElement.OpacityProperty, 0, 1); Metadata.AddValueRange(UIElement.OpacityProperty, 0, 1);
Metadata.AddAdvancedProperty(typeof(Binding), "ValidationRules");
Metadata.AddAdvancedProperty(typeof(Binding), "ValidatesOnExceptions");
Metadata.AddAdvancedProperty(typeof(Binding), "ValidatesOnDataErrors");
Metadata.AddAdvancedProperty(typeof(Binding), "NotifyOnSourceUpdated");
Metadata.AddAdvancedProperty(typeof(Binding), "NotifyOnTargetUpdated");
Metadata.AddAdvancedProperty(typeof(Binding), "NotifyOnValidationError");
Metadata.AddAdvancedProperty(typeof(Binding), "ConverterParameter");
Metadata.AddAdvancedProperty(typeof(Binding), "ConverterCulture");
Metadata.AddAdvancedProperty(typeof(Binding), "Source");
Metadata.AddAdvancedProperty(typeof(Binding), "RelativeSource");
Metadata.AddAdvancedProperty(typeof(Binding), "IsAsync");
Metadata.AddAdvancedProperty(typeof(Binding), "AsyncState");
Metadata.AddAdvancedProperty(typeof(Binding), "BindsDirectlyToSource");
Metadata.AddAdvancedProperty(typeof(Binding), "UpdateSourceExceptionFilter");
Metadata.AddAdvancedProperty(typeof(BindingBase), "FallbackValue");
Metadata.AddAdvancedProperty(typeof(BindingBase), "StringFormat");
Metadata.AddAdvancedProperty(typeof(BindingBase), "TargetNullValue");
} }
} }
} }

2
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditor.cs

@ -171,8 +171,10 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.BrushEditor
public void Commit() public void Commit()
{ {
if (Brush != null) {
Property.Value = Brush.Clone(); Property.Value = Brush.Clone();
} }
}
#region INotifyPropertyChanged Members #region INotifyPropertyChanged Members

4
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyContextMenu.xaml

@ -5,10 +5,10 @@
<MenuItem Header="Reset" <MenuItem Header="Reset"
Click="Click_Reset" /> Click="Click_Reset" />
<MenuItem Header="TODO:"
IsEnabled="False"/>
<MenuItem Header="Binding" <MenuItem Header="Binding"
Click="Click_Binding" /> Click="Click_Binding" />
<MenuItem Header="TODO:"
IsEnabled="False" />
<MenuItem x:Name="uxStaticResource" <MenuItem x:Name="uxStaticResource"
Header="Static Resource"> Header="Static Resource">
<MenuItem Header="Resource1" /> <MenuItem Header="Resource1" />

192
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGridView.xaml

@ -1,4 +1,5 @@
<UserControl x:Class="ICSharpCode.WpfDesign.Designer.PropertyGrid.PropertyGridView" <UserControl x:Class="ICSharpCode.WpfDesign.Designer.PropertyGrid.PropertyGridView"
x:Name="root"
xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation" xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Converters="clr-namespace:ICSharpCode.WpfDesign.Designer.Converters" xmlns:Converters="clr-namespace:ICSharpCode.WpfDesign.Designer.Converters"
@ -6,8 +7,7 @@
xmlns:PropertyGridBase="clr-namespace:ICSharpCode.WpfDesign.PropertyGrid;assembly=ICSharpCode.WpfDesign" xmlns:PropertyGridBase="clr-namespace:ICSharpCode.WpfDesign.PropertyGrid;assembly=ICSharpCode.WpfDesign"
xmlns:Controls="clr-namespace:ICSharpCode.WpfDesign.Designer.Controls" xmlns:Controls="clr-namespace:ICSharpCode.WpfDesign.Designer.Controls"
Background="{x:Static SystemColors.ControlLightBrush}" Background="{x:Static SystemColors.ControlLightBrush}"
SnapsToDevicePixels="True" SnapsToDevicePixels="True">
>
<UserControl.Resources> <UserControl.Resources>
@ -61,7 +61,7 @@
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}"> <ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="#F9F9F4" <Border Background="#F9F9F4"
BorderThickness="1 0 1 0" BorderThickness="0 0 0 1"
BorderBrush="{x:Static SystemColors.ControlBrush}"> BorderBrush="{x:Static SystemColors.ControlBrush}">
<!--<TextBlock Text="More..." <!--<TextBlock Text="More..."
VerticalAlignment="Center" VerticalAlignment="Center"
@ -113,101 +113,6 @@
</Setter> </Setter>
</Style> </Style>
<Style TargetType="{x:Type PropertyGrid:PropertyTreeView}">
<Setter Property="Background"
Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PropertyGrid:PropertyTreeView}">
<Border BorderThickness="0 1 1 0"
BorderBrush="{x:Static SystemColors.ControlBrush}"
Background="{TemplateBinding Background}">
<!--<ScrollViewer HorizontalScrollBarVisibility="Disabled">-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsPresenter />
<Thumb x:Name="PART_Thumb"
HorizontalAlignment="Left"
Width="4"
Margin="-2 0 0 0"
Cursor="SizeWE">
<Thumb.RenderTransform>
<TranslateTransform X="{Binding FirstColumnWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type PropertyGrid:PropertyGridView}}}" />
</Thumb.RenderTransform>
<Thumb.Template>
<ControlTemplate>
<Border Background="Transparent" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
<!--</ScrollViewer>-->
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type PropertyGrid:PropertyTreeViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PropertyGrid:PropertyTreeViewItem}">
<DockPanel>
<Border MinHeight="20"
BorderThickness="1 0 0 1"
BorderBrush="{x:Static SystemColors.ControlBrush}"
Background="{TemplateBinding Background}"
DockPanel.Dock="Top">
<DockPanel>
<DockPanel Width="{Binding FirstColumnWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type PropertyGrid:PropertyGridView}}}"
DockPanel.Dock="Left">
<ToggleButton x:Name="expandButton"
DockPanel.Dock="Left"
Margin="{TemplateBinding Level, Converter={x:Static Converters:LevelConverter.Instance}}"
Style="{StaticResource ExpandButtonStyle}"
IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" />
<TextBlock Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
VerticalAlignment="Center"
Margin="7 0 0 0"
ToolTip="{Binding Description}"
FontWeight="{Binding FontWeight}"
/>
</DockPanel>
<Border BorderThickness="1 0 0 0"
BorderBrush="{x:Static SystemColors.ControlBrush}">
<ContentPresenter Content="{Binding Editor}"
VerticalAlignment="Center"
Margin="3 0" />
</Border>
</DockPanel>
</Border>
<ItemsPresenter x:Name="itemsHost" />
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded"
Value="False">
<Setter TargetName="itemsHost"
Property="Visibility"
Value="Collapsed" />
</Trigger>
<Trigger Property="HasItems"
Value="False">
<Setter TargetName="expandButton"
Property="Visibility"
Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CategoryExpanderStyle" <Style x:Key="CategoryExpanderStyle"
TargetType="Expander"> TargetType="Expander">
<Setter Property="Template"> <Setter Property="Template">
@ -265,19 +170,59 @@
Style="{StaticResource CategoryExpanderStyle}" Style="{StaticResource CategoryExpanderStyle}"
IsExpanded="{Binding IsExpanded}"> IsExpanded="{Binding IsExpanded}">
<StackPanel> <StackPanel>
<PropertyGrid:PropertyTreeView ItemsSource="{Binding Properties}" /> <ItemsControl ItemsSource="{Binding Properties}" />
<Expander Visibility="{Binding MoreProperties, Converter={x:Static Converters:CollapsedWhenEmptyCollection.Instance}}" <Expander Visibility="{Binding MoreProperties.Count, Converter={x:Static Converters:CollapsedWhenZero.Instance}}"
Style="{StaticResource MoreExpanderStyle}" Style="{StaticResource MoreExpanderStyle}"
IsExpanded="{Binding ShowMore}"> IsExpanded="{Binding ShowMore}">
<PropertyGrid:PropertyTreeView ItemsSource="{Binding MoreProperties}" <ItemsControl ItemsSource="{Binding MoreProperties}"
Background="#F9F9F4" /> Background="#F9F9F4" />
</Expander> </Expander>
</StackPanel> </StackPanel>
</Expander> </Expander>
</DataTemplate> </DataTemplate>
<HierarchicalDataTemplate DataType="{x:Type PropertyGridBase:PropertyNode}" <DataTemplate DataType="{x:Type PropertyGridBase:PropertyNode}">
ItemsSource="{Binding Children}" /> <StackPanel>
<Border x:Name="uxPropertyNodeRow"
MinHeight="20"
BorderThickness="0 0 0 1"
BorderBrush="{x:Static SystemColors.ControlBrush}"
DockPanel.Dock="Top">
<DockPanel>
<DockPanel Width="{Binding FirstColumnWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type PropertyGrid:PropertyGridView}}}"
DockPanel.Dock="Left">
<ToggleButton x:Name="expandButton"
DockPanel.Dock="Left"
Margin="{Binding Level, Converter={x:Static Converters:LevelConverter.Instance}}"
Style="{StaticResource ExpandButtonStyle}"
IsChecked="{Binding IsExpanded}"
Visibility="{Binding HasChildren, Converter={x:Static Converters:HiddenWhenFalse.Instance}}" />
<TextBlock Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
VerticalAlignment="Center"
Margin="7 0 0 0"
ToolTip="{Binding Description}"
FontWeight="{Binding FontWeight}" />
</DockPanel>
<Border BorderThickness="1 0 0 0"
BorderBrush="{x:Static SystemColors.ControlBrush}">
<ContentPresenter Content="{Binding Editor}"
VerticalAlignment="Center"
Margin="3 0" />
</Border>
</DockPanel>
</Border>
<StackPanel Visibility="{Binding IsExpanded, Converter={x:Static Converters:CollapsedWhenFalse.Instance}}">
<ItemsControl ItemsSource="{Binding Children}"
Visibility="{Binding Children.Count, Converter={x:Static Converters:CollapsedWhenZero.Instance}}" />
<Expander Visibility="{Binding MoreChildren.Count, Converter={x:Static Converters:CollapsedWhenZero.Instance}}"
Style="{StaticResource MoreExpanderStyle}">
<ItemsControl ItemsSource="{Binding MoreChildren}"
Background="#F9F9F4" />
</Expander>
</StackPanel>
</StackPanel>
</DataTemplate>
<!--<DataTemplate DataType="{x:Type FontFamily}"> <!--<DataTemplate DataType="{x:Type FontFamily}">
<TextBlock Text="{Binding}" <TextBlock Text="{Binding}"
@ -329,16 +274,43 @@
Height="21.277" Height="21.277"
Width="40" /> Width="40" />
</Grid> </Grid>
<TabControl SelectedIndex="{Binding CurrentTab, Converter={x:Static Converters:IntFromEnumConverter.Instance}}">
<TabItem Header="Properties"> <Controls:EnumBar Value="{Binding CurrentTab}"
Container="{Binding ElementName=c1}"
Margin="5 0 0 5"
DockPanel.Dock="Top">
<Controls:EnumBar.ButtonStyle>
<Style TargetType="ToggleButton">
<Setter Property="Width"
Value="70" />
</Style>
</Controls:EnumBar.ButtonStyle>
</Controls:EnumBar>
<Grid x:Name="c1"
Background="White">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"> <ScrollViewer HorizontalScrollBarVisibility="Disabled">
<ItemsControl ItemsSource="{Binding Categories}" /> <ItemsControl ItemsSource="{Binding Categories}" />
</ScrollViewer> </ScrollViewer>
</TabItem> <ScrollViewer HorizontalScrollBarVisibility="Disabled">
<TabItem Header="Events"> <ItemsControl ItemsSource="{Binding Events}" />
<PropertyGrid:PropertyTreeView ItemsSource="{Binding Events}" /> </ScrollViewer>
</TabItem> <Thumb x:Name="thumb"
</TabControl> HorizontalAlignment="Left"
Width="4"
Margin="-2 0 0 0"
Cursor="SizeWE">
<Thumb.RenderTransform>
<TranslateTransform X="{Binding FirstColumnWidth, ElementName=root}" />
</Thumb.RenderTransform>
<Thumb.Template>
<ControlTemplate>
<Border Background="Transparent" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
</DockPanel> </DockPanel>
</UserControl> </UserControl>

24
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGridView.xaml.cs

@ -12,6 +12,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
using ICSharpCode.WpfDesign.PropertyGrid;
namespace ICSharpCode.WpfDesign.Designer.PropertyGrid namespace ICSharpCode.WpfDesign.Designer.PropertyGrid
{ {
@ -24,7 +25,7 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid
InitializeComponent(); InitializeComponent();
AddHandler(Thumb.DragDeltaEvent, new DragDeltaEventHandler(dragDeltaHandler)); thumb.DragDelta += new DragDeltaEventHandler(thumb_DragDelta);
} }
static PropertyContextMenu propertyContextMenu = new PropertyContextMenu(); static PropertyContextMenu propertyContextMenu = new PropertyContextMenu();
@ -56,17 +57,30 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid
} }
} }
protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
{
var row = (e.OriginalSource as DependencyObject).FindAncestor<Border>("uxPropertyNodeRow");
if (row == null) return;
var node = row.DataContext as PropertyNode;
if (node.IsEvent) return;
var contextMenu = new PropertyContextMenu();
contextMenu.DataContext = node;
contextMenu.Placement = PlacementMode.Bottom;
contextMenu.HorizontalOffset = -30;
contextMenu.PlacementTarget = row;
contextMenu.IsOpen = true;
}
void clearButton_Click(object sender, RoutedEventArgs e) void clearButton_Click(object sender, RoutedEventArgs e)
{ {
PropertyGrid.ClearFilter(); PropertyGrid.ClearFilter();
} }
void dragDeltaHandler(object sender, DragDeltaEventArgs e) void thumb_DragDelta(object sender, DragDeltaEventArgs e)
{ {
Thumb thumb = e.OriginalSource as Thumb;
if (thumb != null && thumb.Name == "PART_Thumb") {
FirstColumnWidth = Math.Max(0, FirstColumnWidth + e.HorizontalChange); FirstColumnWidth = Math.Max(0, FirstColumnWidth + e.HorizontalChange);
} }
} }
} }
}

101
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyTreeView.cs

@ -1,101 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls.Primitives;
namespace ICSharpCode.WpfDesign.Designer.PropertyGrid
{
public class PropertyTreeView : TreeView
{
//static Dictionary<object, PropertyTreeViewItem> containersCache = new Dictionary<object, PropertyTreeViewItem>();
protected override DependencyObject GetContainerForItemOverride()
{
//return new Decorator();
return new PropertyTreeViewItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is PropertyTreeViewItem;
}
//protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
//{
// PrepareContainer(element, item);
//}
//internal void PrepareContainer(DependencyObject element, object item)
//{
// PropertyTreeViewItem container;
// if (!containersCache.TryGetValue(item, out container))
// {
// container = new PropertyTreeViewItem();
// containersCache[item] = container;
// }
// base.PrepareContainerForItemOverride(container, item);
// (element as Decorator).Child = container;
//}
}
public class PropertyTreeViewItem : TreeViewItem
{
//public PropertyTreeView ParentTree { get; private set; }
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level", typeof(int), typeof(PropertyTreeViewItem));
public int Level {
get { return (int)GetValue(LevelProperty); }
set { SetValue(LevelProperty, value); }
}
protected override DependencyObject GetContainerForItemOverride()
{
//return new Decorator();
return new PropertyTreeViewItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is PropertyTreeViewItem;
}
//protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
//{
// ParentTree.PrepareContainer(element, item);
//}
protected override void OnVisualParentChanged(DependencyObject oldParent)
{
base.OnVisualParentChanged(oldParent);
var parent = ItemsControl.ItemsControlFromItemContainer(this);
//ParentTree = parent as PropertyTreeView;
var parentItem = parent as PropertyTreeViewItem;
if (parentItem != null) {
Level = parentItem.Level + 1;
//ParentTree = parentItem.ParentTree;
}
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Right) {
e.Handled = true;
var contextMenu = new PropertyContextMenu();
contextMenu.DataContext = DataContext;
contextMenu.Placement = PlacementMode.Bottom;
contextMenu.HorizontalOffset = -30;
contextMenu.PlacementTarget = this;
contextMenu.IsOpen = true;
}
}
}
}

15
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj

@ -40,10 +40,12 @@
<Reference Include="PresentationCore"> <Reference Include="PresentationCore">
<Private>False</Private> <Private>False</Private>
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="PresentationFramework"> <Reference Include="PresentationFramework">
<Private>False</Private> <Private>False</Private>
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core"> <Reference Include="System.Core">
@ -51,8 +53,12 @@
</Reference> </Reference>
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="UIAutomationProvider">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase"> <Reference Include="WindowsBase">
<Private>False</Private> <Private>False</Private>
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -64,6 +70,10 @@
<Compile Include="Controls\ContainerDragHandle.cs" /> <Compile Include="Controls\ContainerDragHandle.cs" />
<Compile Include="Controls\DropDownButton.cs" /> <Compile Include="Controls\DropDownButton.cs" />
<Compile Include="Controls\EnterTextBox.cs" /> <Compile Include="Controls\EnterTextBox.cs" />
<Compile Include="Controls\EnumBar.xaml.cs">
<DependentUpon>EnumBar.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\EnumButton.cs" />
<Compile Include="Controls\GridAdorner.cs" /> <Compile Include="Controls\GridAdorner.cs" />
<Compile Include="Controls\NumericUpDown.cs" /> <Compile Include="Controls\NumericUpDown.cs" />
<Compile Include="Controls\SelectionFrame.cs" /> <Compile Include="Controls\SelectionFrame.cs" />
@ -133,7 +143,6 @@
<Compile Include="PropertyGrid\PropertyGridView.xaml.cs"> <Compile Include="PropertyGrid\PropertyGridView.xaml.cs">
<DependentUpon>PropertyGridView.xaml</DependentUpon> <DependentUpon>PropertyGridView.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="PropertyGrid\PropertyTreeView.cs" />
<Compile Include="ServiceRequiredException.cs" /> <Compile Include="ServiceRequiredException.cs" />
<Compile Include="Services\ChooseClass.cs" /> <Compile Include="Services\ChooseClass.cs" />
<Compile Include="Services\ChooseClassDialog.xaml.cs"> <Compile Include="Services\ChooseClassDialog.xaml.cs">
@ -174,6 +183,10 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<Private>True</Private> <Private>True</Private>
</ProjectReference> </ProjectReference>
<Page Include="Controls\EnumBar.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\NumericUpDown.xaml"> <Page Include="Controls\NumericUpDown.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>

31
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs

@ -13,6 +13,7 @@ using System.Diagnostics;
using ICSharpCode.WpfDesign.XamlDom; using ICSharpCode.WpfDesign.XamlDom;
using ICSharpCode.WpfDesign.Designer.Services; using ICSharpCode.WpfDesign.Designer.Services;
using System.Windows; using System.Windows;
using System.Windows.Markup;
namespace ICSharpCode.WpfDesign.Designer.Xaml namespace ICSharpCode.WpfDesign.Designer.Xaml
{ {
@ -188,16 +189,14 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
UndoService undoService = _designItem.Services.GetService<UndoService>(); UndoService undoService = _designItem.Services.GetService<UndoService>();
if (undoService != null) if (undoService != null)
undoService.Execute(new PropertyChangeAction(this, true, newValue, value)); undoService.Execute(new PropertyChangeAction(this, newValue, true));
else else
SetValueInternal(value, newValue); SetValueInternal(newValue);
} }
void SetValueInternal(object value, XamlPropertyValue newValue) void SetValueInternal(XamlPropertyValue newValue)
{ {
_property.ValueOnInstance = value;
_property.PropertyValue = newValue; _property.PropertyValue = newValue;
_designItem.NotifyPropertyChanged(this); _designItem.NotifyPropertyChanged(this);
} }
@ -205,7 +204,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
{ {
UndoService undoService = _designItem.Services.GetService<UndoService>(); UndoService undoService = _designItem.Services.GetService<UndoService>();
if (undoService != null) if (undoService != null)
undoService.Execute(new PropertyChangeAction(this, false, null, null)); undoService.Execute(new PropertyChangeAction(this, null, false));
else else
ResetInternal(); ResetInternal();
} }
@ -221,26 +220,19 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public sealed class PropertyChangeAction : ITransactionItem public sealed class PropertyChangeAction : ITransactionItem
{ {
XamlModelProperty property; XamlModelProperty property;
bool newIsSet;
XamlPropertyValue newValue;
object newObject;
XamlPropertyValue oldValue; XamlPropertyValue oldValue;
object oldObject; XamlPropertyValue newValue;
bool oldIsSet; bool oldIsSet;
bool newIsSet;
public PropertyChangeAction(XamlModelProperty property, bool newIsSet, XamlPropertyValue newValue, object newObject) public PropertyChangeAction(XamlModelProperty property, XamlPropertyValue newValue, bool newIsSet)
{ {
this.property = property; this.property = property;
this.newIsSet = newIsSet;
this.newValue = newValue; this.newValue = newValue;
this.newObject = newObject; this.newIsSet = newIsSet;
oldIsSet = property._property.IsSet; oldIsSet = property._property.IsSet;
oldValue = property._property.PropertyValue; oldValue = property._property.PropertyValue;
oldObject = property._property.ValueOnInstance;
} }
public string Title { public string Title {
@ -255,7 +247,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public void Do() public void Do()
{ {
if (newIsSet) if (newIsSet)
property.SetValueInternal(newObject, newValue); property.SetValueInternal(newValue);
else else
property.ResetInternal(); property.ResetInternal();
} }
@ -263,7 +255,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public void Undo() public void Undo()
{ {
if (oldIsSet) if (oldIsSet)
property.SetValueInternal(oldObject, oldValue); property.SetValueInternal(oldValue);
else else
property.ResetInternal(); property.ResetInternal();
} }
@ -279,7 +271,6 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
if (property._property == other.property._property) { if (property._property == other.property._property) {
newIsSet = other.newIsSet; newIsSet = other.newIsSet;
newValue = other.newValue; newValue = other.newValue;
newObject = other.newObject;
return true; return true;
} }
return false; return false;

9
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/MarkupExtensionTests.cs

@ -8,21 +8,18 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom
public class MarkupExtensionTests : TestHelper public class MarkupExtensionTests : TestHelper
{ {
[Test] [Test]
[Ignore]
public void Test1() public void Test1()
{ {
TestMarkupExtension("Title=\"{Binding}\""); TestMarkupExtension("Title=\"{Binding}\"");
} }
[Test] [Test]
[Ignore]
public void Test2() public void Test2()
{ {
TestMarkupExtension("Title=\"{Binding Some}\""); TestMarkupExtension("Title=\"{Binding Some}\"");
} }
[Test] [Test]
[Ignore]
public void Test3() public void Test3()
{ {
TestMarkupExtension("Title=\"{ Binding Some , ElementName = Some , Mode = TwoWay }\""); TestMarkupExtension("Title=\"{ Binding Some , ElementName = Some , Mode = TwoWay }\"");
@ -54,15 +51,15 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom
} }
[Test] [Test]
[Ignore]
public void Test8() public void Test8()
{ {
TestMarkupExtension("Content=\"{Binding Some, RelativeSource={RelativeSource Self}}\""); TestMarkupExtension("Content=\"{Binding Some, RelativeSource={RelativeSource Self}}\"");
} }
[Test] [Test]
[Ignore] //[ExpectedException]
[ExpectedException] // Must differ from official XamlReader result // Must differ from official XamlReader result, because Static dereference
// To catch this we should use XamlDocument.Save() instead of XamlWriter.Save(instance)
public void Test9() public void Test9()
{ {
TestMarkupExtension("Content=\"{x:Static t:MyStaticClass.StaticString}\""); TestMarkupExtension("Content=\"{x:Static t:MyStaticClass.StaticString}\"");

152
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs

@ -15,11 +15,13 @@ using System.Runtime.Serialization;
using System.Text; using System.Text;
using System.Windows.Markup; using System.Windows.Markup;
using System.Xml; using System.Xml;
using System.Reflection;
namespace ICSharpCode.WpfDesign.XamlDom namespace ICSharpCode.WpfDesign.XamlDom
{ {
/// <summary> /// <summary>
/// Tokenizer for markup extension attributes. /// Tokenizer for markup extension attributes.
/// [MS-XAML 6.6.7.1]
/// </summary> /// </summary>
sealed class MarkupExtensionTokenizer sealed class MarkupExtensionTokenizer
{ {
@ -69,10 +71,6 @@ namespace ICSharpCode.WpfDesign.XamlDom
AddToken(MarkupExtensionTokenKind.Comma, ","); AddToken(MarkupExtensionTokenKind.Comma, ",");
pos++; pos++;
break; break;
case '{':
AddToken(MarkupExtensionTokenKind.OpenBrace, "{");
pos++;
break;
default: default:
MembernameOrString(); MembernameOrString();
break; break;
@ -97,7 +95,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
ConsumeWhitespace(); ConsumeWhitespace();
} else { } else {
int braceTotal = 0; int braceTotal = 0;
while (braceTotal >= 0) { while (true) {
CheckNotEOF(); CheckNotEOF();
switch (text[pos]) { switch (text[pos]) {
case '\\': case '\\':
@ -110,20 +108,21 @@ namespace ICSharpCode.WpfDesign.XamlDom
braceTotal++; braceTotal++;
break; break;
case '}': case '}':
if (braceTotal != 0) { if (braceTotal == 0) goto stop;
b.Append(text[pos++]); b.Append(text[pos++]);
}
braceTotal--; braceTotal--;
break; break;
case ',': case ',':
case '=': case '=':
braceTotal = -1; if (braceTotal == 0) goto stop;
b.Append(text[pos++]);
break; break;
default: default:
b.Append(text[pos++]); b.Append(text[pos++]);
break; break;
} }
} }
stop:;
} }
CheckNotEOF(); CheckNotEOF();
string valueText = b.ToString(); string valueText = b.ToString();
@ -219,109 +218,106 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
} }
/// <summary>
/// [MS-XAML 6.6.7.2]
/// </summary>
static class MarkupExtensionParser static class MarkupExtensionParser
{ {
public static MarkupExtension ConstructMarkupExtension(string attributeText, XamlObject containingObject, XamlTypeResolverProvider typeResolver) public static XamlObject Parse(string text, XamlObject parent, XmlAttribute attribute)
{ {
if (containingObject == null) var tokens = MarkupExtensionTokenizer.Tokenize(text);
throw new ArgumentNullException("containingObject"); if (tokens.Count < 3
|| tokens[0].Kind != MarkupExtensionTokenKind.OpenBrace
Debug.WriteLine("ConstructMarkupExtension " + attributeText); || tokens[1].Kind != MarkupExtensionTokenKind.TypeName
|| tokens[tokens.Count-1].Kind != MarkupExtensionTokenKind.CloseBrace)
List<MarkupExtensionToken> markupExtensionTokens = MarkupExtensionTokenizer.Tokenize(attributeText);
if (markupExtensionTokens.Count < 3
|| markupExtensionTokens[0].Kind != MarkupExtensionTokenKind.OpenBrace
|| markupExtensionTokens[1].Kind != MarkupExtensionTokenKind.TypeName
|| markupExtensionTokens[markupExtensionTokens.Count-1].Kind != MarkupExtensionTokenKind.CloseBrace)
{ {
throw new XamlMarkupExtensionParseException("Invalid markup extension"); throw new XamlMarkupExtensionParseException("Invalid markup extension");
} }
string typeName = markupExtensionTokens[1].Value; var typeResolver = parent.ServiceProvider.Resolver;
string typeName = tokens[1].Value;
Type extensionType = typeResolver.Resolve(typeName + "Extension"); Type extensionType = typeResolver.Resolve(typeName + "Extension");
if (extensionType == null) extensionType = typeResolver.Resolve(typeName); if (extensionType == null) extensionType = typeResolver.Resolve(typeName);
if (extensionType == null || !typeof(MarkupExtension).IsAssignableFrom(extensionType)) { if (extensionType == null || !typeof(MarkupExtension).IsAssignableFrom(extensionType)) {
throw new XamlMarkupExtensionParseException("Unknown markup extension " + typeName + "Extension"); throw new XamlMarkupExtensionParseException("Unknown markup extension " + typeName + "Extension");
} }
if (extensionType == typeof(TypeExtension))
extensionType = typeof(MyTypeExtension);
if (extensionType == typeof(System.Windows.StaticResourceExtension))
extensionType = typeof(MyStaticResourceExtension);
List<string> positionalArgs = new List<string>(); List<string> positionalArgs = new List<string>();
List<KeyValuePair<string, string>> namedArgs = new List<KeyValuePair<string, string>>(); List<KeyValuePair<string, string>> namedArgs = new List<KeyValuePair<string, string>>();
for (int i = 2; i < markupExtensionTokens.Count - 1; i++) { for (int i = 2; i < tokens.Count - 1; i++) {
if (markupExtensionTokens[i].Kind == MarkupExtensionTokenKind.String) { if (tokens[i].Kind == MarkupExtensionTokenKind.String) {
positionalArgs.Add(markupExtensionTokens[i].Value); positionalArgs.Add(tokens[i].Value);
} else if (markupExtensionTokens[i].Kind == MarkupExtensionTokenKind.Membername) { } else if (tokens[i].Kind == MarkupExtensionTokenKind.Membername) {
if (markupExtensionTokens[i+1].Kind != MarkupExtensionTokenKind.Equals if (tokens[i+1].Kind != MarkupExtensionTokenKind.Equals
|| markupExtensionTokens[i+2].Kind != MarkupExtensionTokenKind.String) || tokens[i+2].Kind != MarkupExtensionTokenKind.String)
{ {
throw new XamlMarkupExtensionParseException("Invalid markup extension"); throw new XamlMarkupExtensionParseException("Invalid markup extension");
} }
namedArgs.Add(new KeyValuePair<string, string>(markupExtensionTokens[i].Value, namedArgs.Add(new KeyValuePair<string, string>(tokens[i].Value, tokens[i+2].Value));
markupExtensionTokens[i+2].Value));
i += 2; i += 2;
} }
} }
// Find the constructor with positionalArgs.Count arguments // Find the constructor with positionalArgs.Count arguments
var ctors = extensionType.GetConstructors().Where(c => c.GetParameters().Length == positionalArgs.Count).ToList(); var ctors = extensionType.GetConstructors().Where(c => c.GetParameters().Length == positionalArgs.Count).ToList();
if (ctors.Count < 1) if (ctors.Count < 1)
throw new XamlMarkupExtensionParseException("No constructor for " + extensionType.FullName + " found that takes " + positionalArgs.Count + " arguments"); throw new XamlMarkupExtensionParseException("No constructor for " +
if (ctors.Count > 1) extensionType.FullName + " found that takes " + positionalArgs.Count + " arguments");
throw new XamlMarkupExtensionParseException("Multiple constructors for " + extensionType.FullName + " found that take " + positionalArgs.Count + " arguments"); if (ctors.Count > 1) {
Debug.WriteLine("Multiple constructors for " +
extensionType.FullName + " found that take " + positionalArgs.Count + " arguments");
}
var ctorParameters = ctors[0].GetParameters(); var ctor = ctors[0];
object[] ctorArguments = new object[positionalArgs.Count]; var defaultCtor = extensionType.GetConstructor(Type.EmptyTypes);
for (int i = 0; i < ctorArguments.Length; i++) { bool mappingToProperties = defaultCtor != null;
Type parameterType = ctorParameters[i].ParameterType; List<PropertyInfo> map = new List<PropertyInfo>();
TypeConverter c = XamlNormalPropertyInfo.GetCustomTypeConverter(parameterType)
?? TypeDescriptor.GetConverter(parameterType); if (mappingToProperties) {
ctorArguments[i] = XamlTextValue.AttributeTextToObject(positionalArgs[i], foreach (var param in ctor.GetParameters()) {
containingObject, var prop = extensionType.GetProperty(param.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
c); if (prop == null) {
} mappingToProperties = false;
MarkupExtension result = (MarkupExtension)ctors[0].Invoke(ctorArguments); break;
foreach (var pair in namedArgs) {
string memberName = pair.Key;
if (memberName.Contains(".")) {
throw new NotImplementedException();
} else {
if (memberName.Contains(":"))
memberName = memberName.Substring(memberName.IndexOf(':') + 1);
var property = extensionType.GetProperty(memberName);
if (property == null)
throw new XamlMarkupExtensionParseException("Property not found: " + extensionType.FullName + "." + memberName);
TypeConverter c = TypeDescriptor.GetConverter(property.PropertyType);
object propValue = XamlTextValue.AttributeTextToObject(pair.Value,
containingObject,
c);
property.SetValue(result, propValue, null);
} }
map.Add(prop);
} }
return result;
} }
sealed class MyTypeExtension : TypeExtension object instance;
{ if (mappingToProperties) {
public MyTypeExtension() {} instance = defaultCtor.Invoke(null);
} else {
public MyTypeExtension(string typeName) : base(typeName) {} var ctorParamsInfo = ctor.GetParameters();
var ctorParams = new object[ctorParamsInfo.Length];
for (int i = 0; i < ctorParams.Length; i++) {
var paramType = ctorParamsInfo[i].ParameterType;
ctorParams[i] = XamlParser.CreateObjectFromAttributeText(positionalArgs[i], paramType, parent);
}
instance = ctor.Invoke(ctorParams);
//TODO
//XamlObject.ConstructorArgsProperty - args collection
//Reinvoke ctor when needed
} }
sealed class MyStaticResourceExtension : System.Windows.StaticResourceExtension XamlObject result = parent.OwnerDocument.CreateObject(instance);
{ if (attribute != null) result.XmlAttribute = attribute;
public MyStaticResourceExtension() {} result.ParentObject = parent;
public MyStaticResourceExtension(object resourceKey) : base(resourceKey) {}
public override object ProvideValue(IServiceProvider serviceProvider) if (mappingToProperties) {
{ for (int i = 0; i < positionalArgs.Count; i++) {
XamlTypeResolverProvider xamlTypeResolver = (XamlTypeResolverProvider)serviceProvider.GetService(typeof(XamlTypeResolverProvider)); var a = parent.OwnerDocument.XmlDocument.CreateAttribute(map[i].Name);
if (xamlTypeResolver == null) a.Value = positionalArgs[i];
throw new XamlLoadException("XamlTypeResolverProvider not found."); XamlParser.ParseObjectAttribute(result, a, false);
return xamlTypeResolver.FindResource(this.ResourceKey); }
} }
foreach (var pair in namedArgs) {
var a = parent.OwnerDocument.XmlDocument.CreateAttribute(pair.Key);
a.Value = pair.Value;
XamlParser.ParseObjectAttribute(result, a, false);
}
return result;
} }
} }
} }

45
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionPrinter.cs

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ICSharpCode.WpfDesign.XamlDom
{
public static class MarkupExtensionPrinter
{
public static bool CanPrint(XamlObject obj)
{
return true;
}
public static string Print(XamlObject obj)
{
StringBuilder sb = new StringBuilder();
sb.Append("{");
sb.Append(obj.GetNameForMarkupExtension());
bool first = true;
foreach (var property in obj.Properties) {
if (!property.IsSet) continue;
if (first)
sb.Append(" ");
else
sb.Append(", ");
first = false;
sb.Append(property.GetNameForMarkupExtension());
sb.Append("=");
var value = property.PropertyValue;
if (value is XamlTextValue) {
sb.Append((value as XamlTextValue).Text);
} else if (value is XamlObject) {
sb.Append(Print(value as XamlObject));
}
}
sb.Append("}");
return sb.ToString();
}
}
}

4
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj

@ -52,6 +52,7 @@
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="WindowsBase"> <Reference Include="WindowsBase">
<Private>False</Private> <Private>False</Private>
@ -65,11 +66,12 @@
<Compile Include="CollectionElementsCollection.cs" /> <Compile Include="CollectionElementsCollection.cs" />
<Compile Include="CollectionSupport.cs" /> <Compile Include="CollectionSupport.cs" />
<Compile Include="MarkupExtensionParser.cs" /> <Compile Include="MarkupExtensionParser.cs" />
<Compile Include="MarkupExtensionPrinter.cs" />
<Compile Include="XamlConstants.cs" /> <Compile Include="XamlConstants.cs" />
<Compile Include="XamlDocument.cs" /> <Compile Include="XamlDocument.cs" />
<Compile Include="XamlLoadException.cs" /> <Compile Include="XamlLoadException.cs" />
<Compile Include="XamlMarkupValue.cs" />
<Compile Include="XamlObject.cs" /> <Compile Include="XamlObject.cs" />
<Compile Include="XamlObjectServiceProvider.cs" />
<Compile Include="XamlParser.cs" /> <Compile Include="XamlParser.cs" />
<Compile Include="XamlParserSettings.cs" /> <Compile Include="XamlParserSettings.cs" />
<Compile Include="XamlProperty.cs" /> <Compile Include="XamlProperty.cs" />

4
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs

@ -60,7 +60,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
if (containingObject != null) { if (containingObject != null) {
if (containingObject.OwnerDocument != document) if (containingObject.OwnerDocument != document)
throw new ArgumentException("Containing object must belong to the document!"); throw new ArgumentException("Containing object must belong to the document!");
baseServiceProvider = new XamlTypeResolverProvider(containingObject); baseServiceProvider = containingObject.ServiceProvider;
} else { } else {
baseServiceProvider = document.ServiceProvider; baseServiceProvider = document.ServiceProvider;
} }
@ -148,7 +148,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
/// </summary> /// </summary>
public XamlPropertyValue CreateNullValue() public XamlPropertyValue CreateNullValue()
{ {
return new XamlMarkupValue((XamlObject)CreatePropertyValue(new System.Windows.Markup.NullExtension(), null)); return CreateObject(new NullExtension());
} }
/// <summary> /// <summary>

52
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlMarkupValue.cs

@ -1,52 +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.Windows.Markup;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Represents a markup extension.
/// </summary>
public class XamlMarkupValue : XamlPropertyValue
{
XamlObject markupObject;
internal XamlMarkupValue(XamlObject markupObject)
{
this.markupObject = markupObject;
}
internal override object GetValueFor(XamlPropertyInfo targetProperty)
{
return ((MarkupExtension)markupObject.Instance).ProvideValue(markupObject.OwnerDocument.ServiceProvider);
}
internal override void OnParentPropertyChanged()
{
base.OnParentPropertyChanged();
markupObject.ParentProperty = this.ParentProperty;
}
internal override void RemoveNodeFromParent()
{
markupObject.RemoveNodeFromParent();
}
internal override void AddNodeTo(XamlProperty property)
{
markupObject.AddNodeTo(property);
}
internal override System.Xml.XmlNode GetNodeForCollection()
{
return markupObject.GetNodeForCollection();
}
}
}

168
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs

@ -11,12 +11,15 @@ using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Windows.Markup; using System.Windows.Markup;
using System.Xml; using System.Xml;
using System.Windows.Data;
using System.Windows;
namespace ICSharpCode.WpfDesign.XamlDom namespace ICSharpCode.WpfDesign.XamlDom
{ {
/// <summary> /// <summary>
/// Represents a xaml object element. /// Represents a xaml object element.
/// </summary> /// </summary>
[DebuggerDisplay("XamlObject: {Instance}")]
public sealed class XamlObject : XamlPropertyValue public sealed class XamlObject : XamlPropertyValue
{ {
XamlDocument document; XamlDocument document;
@ -37,6 +40,9 @@ namespace ICSharpCode.WpfDesign.XamlDom
if (contentAttrs != null && contentAttrs.Length > 0) { if (contentAttrs != null && contentAttrs.Length > 0) {
this.contentPropertyName = contentAttrs[0].Name; this.contentPropertyName = contentAttrs[0].Name;
} }
ServiceProvider = new XamlObjectServiceProvider(this);
CreateWrapper();
} }
/// <summary>For use by XamlParser only.</summary> /// <summary>For use by XamlParser only.</summary>
@ -56,8 +62,12 @@ namespace ICSharpCode.WpfDesign.XamlDom
#region XamlPropertyValue implementation #region XamlPropertyValue implementation
internal override object GetValueFor(XamlPropertyInfo targetProperty) internal override object GetValueFor(XamlPropertyInfo targetProperty)
{ {
if (instance is MarkupExtension) { if (IsMarkupExtension) {
return ((MarkupExtension)instance).ProvideValue(new XamlTypeResolverProvider(this)); var value = ProvideValue();
if (value is string && targetProperty != null && targetProperty.ReturnType != typeof(string)) {
return XamlParser.CreateObjectFromAttributeText((string)value, targetProperty, this);
}
return value;
} else { } else {
return instance; return instance;
} }
@ -91,10 +101,87 @@ namespace ICSharpCode.WpfDesign.XamlDom
get { return element; } get { return element; }
} }
// exists only for ME root
XmlAttribute xmlAttribute;
internal XmlAttribute XmlAttribute {
get { return xmlAttribute; }
set {
xmlAttribute = value;
element = VirualAttachTo(XmlElement, value.OwnerElement);
}
}
public bool IsMarkupExtensionRoot {
get { return XmlAttribute != null; }
}
static XmlElement VirualAttachTo(XmlElement e, XmlElement target)
{
var prefix = target.GetPrefixOfNamespace(e.NamespaceURI);
XmlElement newElement = e.OwnerDocument.CreateElement(prefix, e.Name, e.NamespaceURI);
foreach (XmlAttribute a in target.Attributes) {
if (a.Name.StartsWith("xmlns")) {
newElement.Attributes.Append(a.Clone() as XmlAttribute);
}
}
while (e.HasChildNodes) {
newElement.AppendChild(e.FirstChild);
}
XmlAttributeCollection ac = e.Attributes;
while (ac.Count > 0) {
newElement.Attributes.Append(ac[0]);
}
return newElement;
}
internal override void AddNodeTo(XamlProperty property) internal override void AddNodeTo(XamlProperty property)
{ {
if (!UpdateMarkupExtension(true)) {
property.AddChildNodeToProperty(element); property.AddChildNodeToProperty(element);
} }
}
internal override void RemoveNodeFromParent()
{
if (XmlAttribute != null) {
XmlAttribute.OwnerElement.RemoveAttribute(XmlAttribute.Name);
xmlAttribute = null;
} else {
element.ParentNode.RemoveChild(element);
}
}
internal void OnPropertyChanged(XamlProperty property)
{
UpdateMarkupExtension(false);
}
bool UpdateMarkupExtension(bool canCreate)
{
if (IsMarkupExtension) {
var obj = this;
while (obj != null && obj.IsMarkupExtension) {
obj.ParentProperty.UpdateValueOnInstance();
if (obj.IsMarkupExtensionRoot) break;
obj = obj.ParentObject;
}
if (!obj.IsMarkupExtension) obj = null;
if (obj == null && !canCreate) return false;
var root = obj ?? this;
if (MarkupExtensionPrinter.CanPrint(root)) {
var s = MarkupExtensionPrinter.Print(root);
root.XmlAttribute = root.ParentProperty.SetAttribute(s);
return root == this;
}
}
return false;
}
/// <summary> /// <summary>
/// Gets the XamlDocument where this XamlObject is declared in. /// Gets the XamlDocument where this XamlObject is declared in.
@ -110,6 +197,14 @@ namespace ICSharpCode.WpfDesign.XamlDom
get { return instance; } get { return instance; }
} }
public bool IsMarkupExtension {
get { return instance is MarkupExtension; }
}
public DependencyObject DependencyObject {
get { return instance as DependencyObject; }
}
/// <summary> /// <summary>
/// Gets the type of this object element. /// Gets the type of this object element.
/// </summary> /// </summary>
@ -135,11 +230,6 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
} }
internal override void RemoveNodeFromParent()
{
element.ParentNode.RemoveChild(element);
}
/// <summary> /// <summary>
/// Finds the specified property, or creates it if it doesn't exist. /// Finds the specified property, or creates it if it doesn't exist.
/// </summary> /// </summary>
@ -211,5 +301,69 @@ namespace ICSharpCode.WpfDesign.XamlDom
else else
element.SetAttribute(name, XamlConstants.XamlNamespace, value); element.SetAttribute(name, XamlConstants.XamlNamespace, value);
} }
public XamlObjectServiceProvider ServiceProvider { get; set; }
MarkupExtensionWrapper wrapper;
void CreateWrapper()
{
if (Instance is Binding) {
wrapper = new BindingWrapper();
} else if (Instance is StaticResourceExtension) {
wrapper = new StaticResourceWrapper();
}
if (wrapper != null) {
wrapper.XamlObject = this;
}
}
object ProvideValue()
{
if (wrapper != null) {
return wrapper.ProvideValue();
}
return (Instance as MarkupExtension).ProvideValue(ServiceProvider);
}
internal string GetNameForMarkupExtension()
{
return XmlElement.Name;
}
}
abstract class MarkupExtensionWrapper
{
public XamlObject XamlObject { get; set; }
public abstract object ProvideValue();
}
class BindingWrapper : MarkupExtensionWrapper
{
public override object ProvideValue()
{
var target = XamlObject.Instance as Binding;
//TODO: XamlObject.Clone()
var b = new Binding();
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(target)) {
if (pd.IsReadOnly) continue;
try {
var val1 = pd.GetValue(b);
var val2 = pd.GetValue(target);
if (object.Equals(val1, val2)) continue;
pd.SetValue(b, val2);
} catch {}
}
return b.ProvideValue(XamlObject.ServiceProvider);
}
}
class StaticResourceWrapper : MarkupExtensionWrapper
{
public override object ProvideValue()
{
var target = XamlObject.Instance as StaticResourceExtension;
return XamlObject.ServiceProvider.Resolver.FindResource(target.ResourceKey);
}
} }
} }

47
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
namespace ICSharpCode.WpfDesign.XamlDom
{
public class XamlObjectServiceProvider : IServiceProvider, IProvideValueTarget
{
public XamlObjectServiceProvider(XamlObject obj)
{
XamlObject = obj;
Resolver = new XamlTypeResolverProvider(obj);
}
public XamlObject XamlObject { get; private set; }
internal XamlTypeResolverProvider Resolver { get; private set; }
#region IServiceProvider Members
public object GetService(Type serviceType)
{
if (serviceType == typeof(IProvideValueTarget)) {
return this;
}
if (serviceType == typeof(IXamlTypeResolver)) {
return Resolver;
}
return null;
}
#endregion
#region IProvideValueTarget Members
public object TargetObject {
get { return XamlObject.ParentProperty.ParentObject.Instance; }
}
public object TargetProperty {
get { return XamlObject.ParentProperty.DependencyProperty; }
}
#endregion
}
}

54
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs

@ -184,6 +184,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
currentXamlObject = obj; currentXamlObject = obj;
obj.ParentObject = parentXamlObject; obj.ParentObject = parentXamlObject;
if (parentXamlObject == null && obj.DependencyObject != null) {
NameScope.SetNameScope(obj.DependencyObject, new NameScope());
}
ISupportInitialize iSupportInitializeInstance = instance as ISupportInitialize; ISupportInitialize iSupportInitializeInstance = instance as ISupportInitialize;
if (iSupportInitializeInstance != null) { if (iSupportInitializeInstance != null) {
iSupportInitializeInstance.BeginInit(); iSupportInitializeInstance.BeginInit();
@ -275,7 +279,6 @@ namespace ICSharpCode.WpfDesign.XamlDom
throw new XamlLoadException("This element does not have a default value, cannot assign to it"); throw new XamlLoadException("This element does not have a default value, cannot assign to it");
} }
obj.AddProperty(new XamlProperty(obj, defaultProperty, setDefaultValueTo)); obj.AddProperty(new XamlProperty(obj, defaultProperty, setDefaultValueTo));
defaultProperty.SetValue(obj.Instance, setDefaultValueTo.GetValueFor(defaultProperty));
} }
} }
@ -393,10 +396,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
} }
XamlPropertyInfo GetPropertyInfo(object elementInstance, Type elementType, XmlAttribute attribute) static XamlPropertyInfo GetPropertyInfo(object elementInstance, Type elementType, XmlAttribute attribute, XamlTypeFinder typeFinder)
{ {
if (attribute.LocalName.Contains(".")) { if (attribute.LocalName.Contains(".")) {
return GetPropertyInfo(settings.TypeFinder, elementInstance, elementType, GetAttributeNamespace(attribute), attribute.LocalName); return GetPropertyInfo(typeFinder, elementInstance, elementType, GetAttributeNamespace(attribute), attribute.LocalName);
} else { } else {
return FindProperty(elementInstance, elementType, attribute.LocalName); return FindProperty(elementInstance, elementType, attribute.LocalName);
} }
@ -423,12 +426,29 @@ namespace ICSharpCode.WpfDesign.XamlDom
propertyName = qualifiedName.Substring(pos + 1); propertyName = qualifiedName.Substring(pos + 1);
} }
void ParseObjectAttribute(XamlObject obj, XmlAttribute attribute) static void ParseObjectAttribute(XamlObject obj, XmlAttribute attribute)
{ {
XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.Instance, obj.ElementType, attribute); ParseObjectAttribute(obj, attribute, true);
XamlTextValue textValue = new XamlTextValue(document, attribute); }
obj.AddProperty(new XamlProperty(obj, propertyInfo, textValue));
propertyInfo.SetValue(obj.Instance, textValue.GetValueFor(propertyInfo)); internal static void ParseObjectAttribute(XamlObject obj, XmlAttribute attribute, bool real)
{
XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.Instance, obj.ElementType, attribute, obj.OwnerDocument.TypeFinder);
XamlPropertyValue value = null;
var valueText = attribute.Value;
if (valueText.StartsWith("{") && !valueText.StartsWith("{}")) {
var xamlObject = MarkupExtensionParser.Parse(valueText, obj, real ? attribute : null);
value = xamlObject;
} else {
if (real)
value = new XamlTextValue(obj.OwnerDocument, attribute);
else
value = new XamlTextValue(obj.OwnerDocument, valueText);
}
var property = new XamlProperty(obj, propertyInfo, value);
obj.AddProperty(property);
} }
static bool ObjectChildElementIsPropertyElement(XmlElement element) static bool ObjectChildElementIsPropertyElement(XmlElement element)
@ -482,12 +502,28 @@ namespace ICSharpCode.WpfDesign.XamlDom
XamlProperty xp = new XamlProperty(obj, propertyInfo, childValue); XamlProperty xp = new XamlProperty(obj, propertyInfo, childValue);
xp.ParserSetPropertyElement(element); xp.ParserSetPropertyElement(element);
obj.AddProperty(xp); obj.AddProperty(xp);
propertyInfo.SetValue(obj.Instance, childValue.GetValueFor(propertyInfo));
} }
} }
} }
currentXmlSpace = oldXmlSpace; currentXmlSpace = oldXmlSpace;
} }
internal static object CreateObjectFromAttributeText(string valueText, XamlPropertyInfo targetProperty, XamlObject scope)
{
return targetProperty.TypeConverter.ConvertFromString(
scope.OwnerDocument.GetTypeDescriptorContext(scope),
CultureInfo.InvariantCulture, valueText);
}
internal static object CreateObjectFromAttributeText(string valueText, Type targetType, XamlObject scope)
{
var converter =
XamlNormalPropertyInfo.GetCustomTypeConverter(targetType) ??
TypeDescriptor.GetConverter(targetType);
return converter.ConvertFromInvariantString(
scope.OwnerDocument.GetTypeDescriptorContext(scope), valueText);
}
} }
} }

233
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs

@ -12,6 +12,7 @@ using System.Diagnostics;
using System.Text; using System.Text;
using System.Xml; using System.Xml;
using System.Windows; using System.Windows;
using System.Windows.Markup;
namespace ICSharpCode.WpfDesign.XamlDom namespace ICSharpCode.WpfDesign.XamlDom
{ {
@ -34,10 +35,14 @@ namespace ICSharpCode.WpfDesign.XamlDom
internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo, XamlPropertyValue propertyValue) internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo, XamlPropertyValue propertyValue)
: this(parentObject, propertyInfo) : this(parentObject, propertyInfo)
{ {
PossiblyNameChanged(null, propertyValue);
this.propertyValue = propertyValue; this.propertyValue = propertyValue;
if (propertyValue != null) { if (propertyValue != null) {
propertyValue.ParentProperty = this; propertyValue.ParentProperty = this;
} }
UpdateValueOnInstance();
} }
internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo) internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo)
@ -112,17 +117,57 @@ namespace ICSharpCode.WpfDesign.XamlDom
/// </summary> /// </summary>
public XamlPropertyValue PropertyValue { public XamlPropertyValue PropertyValue {
get { return propertyValue; } get { return propertyValue; }
set { set { SetPropertyValue(value); }
}
/// <summary>
/// Gets if the property is a collection property.
/// </summary>
public bool IsCollection {
get { return isCollection; }
}
/// <summary>
/// Gets the collection elements of the property. Is empty if the property is not a collection.
/// </summary>
public IList<XamlPropertyValue> CollectionElements {
get { return collectionElements ?? emptyCollectionElementsArray; }
}
/// <summary>
/// Gets if the property is set.
/// </summary>
public bool IsSet {
get { return propertyValue != null || collectionElements != null; }
}
/// <summary>
/// Occurs when the value of the IsSet property has changed.
/// </summary>
public event EventHandler IsSetChanged;
/// <summary>
/// Occurs when the value of the property has changed.
/// </summary>
public event EventHandler ValueChanged;
void SetPropertyValue(XamlPropertyValue value)
{
if (IsCollection) { if (IsCollection) {
throw new InvalidOperationException("Cannot set the value of collection properties."); throw new InvalidOperationException("Cannot set the value of collection properties.");
} }
bool wasSet = this.IsSet; bool wasSet = this.IsSet;
PossiblyNameChanged(propertyValue, value);
ResetInternal(); ResetInternal();
propertyValue = value; propertyValue = value;
propertyValue.AddNodeTo(this);
propertyValue.ParentProperty = this; propertyValue.ParentProperty = this;
propertyValue.AddNodeTo(this);
UpdateValueOnInstance();
ParentObject.OnPropertyChanged(this);
if (!wasSet) { if (!wasSet) {
if (IsSetChanged != null) { if (IsSetChanged != null) {
@ -133,6 +178,51 @@ namespace ICSharpCode.WpfDesign.XamlDom
ValueChanged(this, EventArgs.Empty); ValueChanged(this, EventArgs.Empty);
} }
} }
internal void UpdateValueOnInstance()
{
if (PropertyValue != null) {
try {
ValueOnInstance = PropertyValue.GetValueFor(propertyInfo);
}
catch {
Debug.WriteLine("UpdateValueOnInstance() failed");
}
}
}
/// <summary>
/// Resets the properties value.
/// </summary>
public void Reset()
{
if (IsSet) {
propertyInfo.ResetValue(parentObject.Instance);
ResetInternal();
ParentObject.OnPropertyChanged(this);
if (IsSetChanged != null) {
IsSetChanged(this, EventArgs.Empty);
}
if (ValueChanged != null) {
ValueChanged(this, EventArgs.Empty);
}
}
}
void ResetInternal()
{
if (propertyValue != null) {
propertyValue.RemoveNodeFromParent();
propertyValue.ParentProperty = null;
propertyValue = null;
}
if (_propertyElement != null) {
_propertyElement.ParentNode.RemoveChild(_propertyElement);
_propertyElement = null;
}
} }
XmlElement _propertyElement; XmlElement _propertyElement;
@ -201,67 +291,38 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
} }
/// <summary> internal XmlAttribute SetAttribute(string value)
/// Gets if the property is a collection property.
/// </summary>
public bool IsCollection {
get { return isCollection; }
}
/// <summary>
/// Gets the collection elements of the property. Is empty if the property is not a collection.
/// </summary>
public IList<XamlPropertyValue> CollectionElements {
get { return collectionElements ?? emptyCollectionElementsArray; }
}
/// <summary>
/// Gets if the property is set.
/// </summary>
public bool IsSet {
get { return propertyValue != null || collectionElements != null; }
}
/// <summary>
/// Occurs when the value of the IsSet property has changed.
/// </summary>
public event EventHandler IsSetChanged;
/// <summary>
/// Occurs when the value of the property has changed.
/// </summary>
public event EventHandler ValueChanged;
/// <summary>
/// Resets the properties value.
/// </summary>
public void Reset()
{ {
if (IsSet) { string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType);
propertyInfo.ResetValue(parentObject.Instance); string name;
if (IsAttached)
ResetInternal(); name = PropertyTargetType.Name + "." + PropertyName;
else
name = PropertyName;
if (IsSetChanged != null) { var element = ParentObject.XmlElement;
IsSetChanged(this, EventArgs.Empty); if (element.GetPrefixOfNamespace(ns) == "") {
} element.SetAttribute(name, value);
if (ValueChanged != null) { return element.GetAttributeNode(name);
ValueChanged(this, EventArgs.Empty); } else {
} element.SetAttribute(name, ns, value);
return element.GetAttributeNode(name, ns);
} }
} }
void ResetInternal() internal string GetNameForMarkupExtension()
{ {
if (propertyValue != null) { string name;
propertyValue.RemoveNodeFromParent(); if (IsAttached)
propertyValue.ParentProperty = null; name = PropertyTargetType.Name + "." + PropertyName;
propertyValue = null; else
} name = PropertyName;
if (_propertyElement != null) {
_propertyElement.ParentNode.RemoveChild(_propertyElement); var element = ParentObject.XmlElement;
_propertyElement = null; string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType);
} var prefix = element.GetPrefixOfNamespace(ns);
if (prefix == "") return name;
return prefix + ":" + name;
} }
/// <summary> /// <summary>
@ -300,6 +361,54 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
} }
public bool IsAdvanced {
get { return propertyInfo.IsAdvanced; }
}
public DependencyProperty DependencyProperty {
get {
return propertyInfo.DependencyProperty;
}
}
void PossiblyNameChanged(XamlPropertyValue oldValue, XamlPropertyValue newValue)
{
if (PropertyName == "Name" && ReturnType == typeof(string)) {
string oldName = null;
string newName = null;
var oldTextValue = oldValue as XamlTextValue;
if (oldTextValue != null) oldName = oldTextValue.Text;
var newTextValue = newValue as XamlTextValue;
if (newTextValue != null) newName = newTextValue.Text;
var obj = ParentObject;
while (obj != null) {
var nameScope = obj.Instance as INameScope;
if (nameScope == null) {
if (obj.DependencyObject != null)
nameScope = NameScope.GetNameScope(obj.DependencyObject);
}
if (nameScope != null) {
if (oldName != null) {
nameScope.UnregisterName(oldName);
}
if (newName != null) {
nameScope.RegisterName(newName, ParentObject.Instance);
}
break;
}
obj = obj.ParentObject;
}
}
}
void PossiblyMarkupExtensionChanged(XamlPropertyValue part)
{
}
/*public bool IsAttributeSyntax { /*public bool IsAttributeSyntax {
get { get {
return attribute != null; return attribute != null;
@ -317,15 +426,5 @@ namespace ICSharpCode.WpfDesign.XamlDom
return attribute == null && element == null; return attribute == null && element == null;
} }
}*/ }*/
public bool IsAdvanced {
get { return propertyInfo.IsAdvanced; }
}
public DependencyProperty DependencyProperty {
get {
return propertyInfo.DependencyProperty;
}
}
} }
} }

41
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTextValue.cs

@ -113,34 +113,11 @@ namespace ICSharpCode.WpfDesign.XamlDom
{ {
if (ParentProperty == null) if (ParentProperty == null)
throw new InvalidOperationException("Cannot call GetValueFor while ParentProperty is null"); throw new InvalidOperationException("Cannot call GetValueFor while ParentProperty is null");
if (attribute != null) {
return AttributeTextToObject(attribute.Value, ParentProperty.ParentObject,
targetProperty != null ? targetProperty.TypeConverter : XamlNormalPropertyInfo.StringTypeConverter);
}
if (targetProperty == null) if (targetProperty == null)
return this.Text; return this.Text;
return targetProperty.TypeConverter.ConvertFromString(
document.GetTypeDescriptorContext(ParentProperty.ParentObject),
CultureInfo.InvariantCulture, this.Text);
}
internal static object AttributeTextToObject(string attributeText, XamlObject containingObject, return XamlParser.CreateObjectFromAttributeText(Text, targetProperty, ParentProperty.ParentObject);
TypeConverter typeConverter)
{
if (attributeText.StartsWith("{}")) {
return typeConverter.ConvertFromString(
containingObject.OwnerDocument.GetTypeDescriptorContext(containingObject), CultureInfo.InvariantCulture,
attributeText.Substring(2));
} else if (attributeText.StartsWith("{")) {
XamlTypeResolverProvider xtrp = new XamlTypeResolverProvider(containingObject);
MarkupExtension extension = MarkupExtensionParser.ConstructMarkupExtension(
attributeText, containingObject, xtrp);
return extension.ProvideValue(xtrp);
} else {
return typeConverter.ConvertFromString(
containingObject.OwnerDocument.GetTypeDescriptorContext(containingObject), CultureInfo.InvariantCulture,
attributeText);
}
} }
internal override void RemoveNodeFromParent() internal override void RemoveNodeFromParent()
@ -158,19 +135,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
if (attribute != null) { if (attribute != null) {
property.ParentObject.XmlElement.Attributes.Append(attribute); property.ParentObject.XmlElement.Attributes.Append(attribute);
} else if (textValue != null) { } else if (textValue != null) {
string ns = property.ParentObject.OwnerDocument.GetNamespaceFor(property.PropertyTargetType); attribute = property.SetAttribute(textValue);
string name;
if (property.IsAttached)
name = property.PropertyTargetType.Name + "." + property.PropertyName;
else
name = property.PropertyName;
if (property.ParentObject.XmlElement.GetPrefixOfNamespace(ns) == "") {
property.ParentObject.XmlElement.SetAttribute(name, textValue);
attribute = property.ParentObject.XmlElement.GetAttributeNode(name);
} else {
property.ParentObject.XmlElement.SetAttribute(name, ns, textValue);
attribute = property.ParentObject.XmlElement.GetAttributeNode(name, ns);
}
textValue = null; textValue = null;
} else if (cDataSection != null) { } else if (cDataSection != null) {
property.AddChildNodeToProperty(cDataSection); property.AddChildNodeToProperty(cDataSection);

14
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeResolverProvider.cs

@ -21,7 +21,6 @@ namespace ICSharpCode.WpfDesign.XamlDom
{ {
XamlDocument document; XamlDocument document;
XamlObject containingObject; XamlObject containingObject;
XmlElement containingElement;
public XamlTypeResolverProvider(XamlObject containingObject) public XamlTypeResolverProvider(XamlObject containingObject)
{ {
@ -29,7 +28,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
throw new ArgumentNullException("containingObject"); throw new ArgumentNullException("containingObject");
this.document = containingObject.OwnerDocument; this.document = containingObject.OwnerDocument;
this.containingObject = containingObject; this.containingObject = containingObject;
this.containingElement = containingObject.XmlElement; }
XmlElement ContainingElement{
get { return containingObject.XmlElement; }
} }
public Type Resolve(string typeName) public Type Resolve(string typeName)
@ -37,10 +39,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
string typeNamespaceUri; string typeNamespaceUri;
string typeLocalName; string typeLocalName;
if (typeName.Contains(":")) { if (typeName.Contains(":")) {
typeNamespaceUri = containingElement.GetNamespaceOfPrefix(typeName.Substring(0, typeName.IndexOf(':'))); typeNamespaceUri = ContainingElement.GetNamespaceOfPrefix(typeName.Substring(0, typeName.IndexOf(':')));
typeLocalName = typeName.Substring(typeName.IndexOf(':') + 1); typeLocalName = typeName.Substring(typeName.IndexOf(':') + 1);
} else { } else {
typeNamespaceUri = containingElement.NamespaceURI; typeNamespaceUri = ContainingElement.GetNamespaceOfPrefix("");
typeLocalName = typeName; typeLocalName = typeName;
} }
if (string.IsNullOrEmpty(typeNamespaceUri)) if (string.IsNullOrEmpty(typeNamespaceUri))
@ -60,10 +62,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
{ {
string propertyNamespace; string propertyNamespace;
if (propertyName.Contains(":")) { if (propertyName.Contains(":")) {
propertyNamespace = containingElement.GetNamespaceOfPrefix(propertyName.Substring(0, propertyName.IndexOf(':'))); propertyNamespace = ContainingElement.GetNamespaceOfPrefix(propertyName.Substring(0, propertyName.IndexOf(':')));
propertyName = propertyName.Substring(propertyName.IndexOf(':') + 1); propertyName = propertyName.Substring(propertyName.IndexOf(':') + 1);
} else { } else {
propertyNamespace = containingElement.NamespaceURI; propertyNamespace = ContainingElement.GetNamespaceOfPrefix("");
} }
Type elementType = null; Type elementType = null;
XamlObject obj = containingObject; XamlObject obj = containingObject;

19
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs

@ -9,12 +9,6 @@ using System.ComponentModel;
namespace ICSharpCode.WpfDesign namespace ICSharpCode.WpfDesign
{ {
public class NumberRange
{
public double Min;
public double Max;
}
public static class Metadata public static class Metadata
{ {
public static string GetFullName(this DependencyProperty p) public static string GetFullName(this DependencyProperty p)
@ -95,6 +89,13 @@ namespace ICSharpCode.WpfDesign
} }
} }
public static void AddAdvancedProperty(Type type, string member)
{
lock (advancedProperties) {
advancedProperties.Add(type.FullName + "." + member);
}
}
public static bool IsAdvanced(DesignItemProperty p) public static bool IsAdvanced(DesignItemProperty p)
{ {
lock (advancedProperties) { lock (advancedProperties) {
@ -127,4 +128,10 @@ namespace ICSharpCode.WpfDesign
return null; return null;
} }
} }
public class NumberRange
{
public double Min;
public double Max;
}
} }

26
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -21,6 +21,7 @@ namespace ICSharpCode.WpfDesign.PropertyGrid
{ {
this.Properties = properties; this.Properties = properties;
this.Parent = parent; this.Parent = parent;
this.Level = parent == null ? 0 : parent.Level + 1;
foreach (var property in properties) { foreach (var property in properties) {
property.ValueChanged += new EventHandler(property_ValueChanged); property.ValueChanged += new EventHandler(property_ValueChanged);
@ -28,6 +29,7 @@ namespace ICSharpCode.WpfDesign.PropertyGrid
Editor = EditorManager.CreateEditor(FirstProperty); Editor = EditorManager.CreateEditor(FirstProperty);
Children = new ObservableCollection<PropertyNode>(); Children = new ObservableCollection<PropertyNode>();
MoreChildren = new ObservableCollection<PropertyNode>();
UpdateChildren(); UpdateChildren();
} }
@ -50,7 +52,9 @@ namespace ICSharpCode.WpfDesign.PropertyGrid
public DesignItemProperty FirstProperty { get { return Properties[0]; } } public DesignItemProperty FirstProperty { get { return Properties[0]; } }
public PropertyNode Parent { get; private set; } public PropertyNode Parent { get; private set; }
public int Level { get; private set; }
public ObservableCollection<PropertyNode> Children { get; private set; } public ObservableCollection<PropertyNode> Children { get; private set; }
public ObservableCollection<PropertyNode> MoreChildren { get; private set; }
bool isExpanded; bool isExpanded;
@ -60,10 +64,15 @@ namespace ICSharpCode.WpfDesign.PropertyGrid
} }
set { set {
isExpanded = value; isExpanded = value;
UpdateChildren();
RaisePropertyChanged("IsExpanded"); RaisePropertyChanged("IsExpanded");
} }
} }
public bool HasChildren {
get { return Children.Count > 0 || MoreChildren.Count > 0; }
}
public object Description { public object Description {
get { get {
IPropertyDescriptionService s = Services.GetService<IPropertyDescriptionService>(); IPropertyDescriptionService s = Services.GetService<IPropertyDescriptionService>();
@ -132,6 +141,7 @@ namespace ICSharpCode.WpfDesign.PropertyGrid
public void CreateBinding() public void CreateBinding()
{ {
Value = new Binding(); Value = new Binding();
IsExpanded = true;
} }
void SetValueCore(object value) void SetValueCore(object value)
@ -165,22 +175,28 @@ namespace ICSharpCode.WpfDesign.PropertyGrid
void UpdateChildren() void UpdateChildren()
{ {
Children.Clear(); Children.Clear();
MoreChildren.Clear();
if (Parent == null || Parent.IsExpanded) { if (Parent == null || Parent.IsExpanded) {
if (IsAmbiguous || FirstProperty.IsCollection || FirstProperty.Value == null) { if (IsAmbiguous || FirstProperty.IsCollection || FirstProperty.Value == null) {}
return; else {
}
var item = FirstProperty.Value; var item = FirstProperty.Value;
var list = TypeHelper.GetAvailableProperties(item.ComponentType) var list = TypeHelper.GetAvailableProperties(item.ComponentType)
.OrderBy(d => d.Name) .OrderBy(d => d.Name)
.Select(d => new PropertyNode(new[] { item.Properties[d.Name] }, this)); .Select(d => new PropertyNode(new[] { item.Properties[d.Name] }, this));
foreach (var node in list) { foreach (var node in list) {
if (Metadata.IsAdvanced(node.FirstProperty)) {
MoreChildren.Add(node);
} else {
Children.Add(node); Children.Add(node);
} }
} }
} }
}
RaisePropertyChanged("HasChildren");
}
#region INotifyPropertyChanged Members #region INotifyPropertyChanged Members

Loading…
Cancel
Save