瀏覽代碼

New DF variable from digital form designer

Kenric Nugteren 2 年之前
父節點
當前提交
c59c4d9bea

+ 1 - 1
InABox.DynamicGrid/DynamicColumnGrid.cs

@@ -159,7 +159,7 @@ namespace InABox.DynamicGrid
             return Columns[index];
         }
 
-        protected override void SaveItem(DynamicGridColumn item)
+        public override void SaveItem(DynamicGridColumn item)
         {
             try
             {

+ 2 - 2
InABox.DynamicGrid/DynamicDataGrid.cs

@@ -333,12 +333,12 @@ namespace InABox.DynamicGrid
                 ?? throw new Exception($"No {typeof(TEntity).Name} with ID {id}");
         }
 
-        protected override void SaveItem(TEntity item)
+        public override void SaveItem(TEntity item)
         {
             new Client<TEntity>().Save(item, "Edited by User");
         }
 
-        protected override void SaveItems(TEntity[] items)
+        public override void SaveItems(TEntity[] items)
         {
             new Client<TEntity>().Save(items, "Edited by User");
         }

+ 1 - 1
InABox.DynamicGrid/DynamicEnclosedListGrid.cs

@@ -125,7 +125,7 @@ namespace InABox.DynamicGrid
             return result.ToArray();
         }
 
-        protected override void SaveItem(TMany item)
+        public override void SaveItem(TMany item)
         {
             if (!Items.Contains(item))
                 Items.Add(item);

+ 1 - 1
InABox.DynamicGrid/DynamicExportMappingGrid.cs

@@ -56,7 +56,7 @@ namespace InABox.DynamicGrid
             action.Invoke(result, null);
         }
 
-        protected override void SaveItem(ImportMapping item)
+        public override void SaveItem(ImportMapping item)
         {
             if (!Items.Contains(item))
                 Items.Add(item);

+ 2 - 2
InABox.DynamicGrid/DynamicGrid.cs

@@ -2222,9 +2222,9 @@ namespace InABox.DynamicGrid
 
         protected abstract T LoadItem(CoreRow row);
 
-        protected abstract void SaveItem(T item);
+        public abstract void SaveItem(T item);
 
-        protected virtual void SaveItems(T[] items)
+        public virtual void SaveItems(T[] items)
         {
             foreach (var item in items)
                 SaveItem(item);

+ 1 - 1
InABox.DynamicGrid/DynamicGridFilterGrid.cs

@@ -55,7 +55,7 @@ namespace InABox.DynamicGrid
             action.Invoke(result, null);
         }
 
-        protected override void SaveItem(DynamicGridFilter item)
+        public override void SaveItem(DynamicGridFilter item)
         {
             if (!Filters.Contains(item))
                 Filters.Add(item);

+ 1 - 1
InABox.DynamicGrid/DynamicImportMappingGrid.cs

@@ -65,7 +65,7 @@ namespace InABox.DynamicGrid
             action.Invoke(result, null);
         }
 
-        protected override void SaveItem(ImportMapping item)
+        public override void SaveItem(ImportMapping item)
         {
             if (!Items.Contains(item))
                 Items.Add(item);

+ 1 - 1
InABox.DynamicGrid/DynamicManyToManyDataGrid.cs

@@ -66,7 +66,7 @@ namespace InABox.DynamicGrid
                 new Client<TManyToMany>().Delete(item, "");
         }
 
-        protected override void SaveItem(TManyToMany item)
+        public override void SaveItem(TManyToMany item)
         {
             new Client<TManyToMany>().Save(item, "");
         }

+ 1 - 1
InABox.DynamicGrid/DynamicManyToManyGrid.cs

@@ -261,7 +261,7 @@ namespace InABox.DynamicGrid
             return WorkingList[_recordmap[row].Index];
         }
 
-        protected override void SaveItem(TManyToMany item)
+        public override void SaveItem(TManyToMany item)
         {
             if (!WorkingList.Contains(item))
                 WorkingList.Add(item);

+ 1 - 1
InABox.DynamicGrid/DynamicOneToManyGrid.cs

@@ -202,7 +202,7 @@ namespace InABox.DynamicGrid
             return result.ToArray();
         }
 
-        protected override void SaveItem(TMany item)
+        public override void SaveItem(TMany item)
         {
             if (!Items.Contains(item))
                 Items.Add(item);

+ 1 - 1
InABox.DynamicGrid/Editors/JsonEditorControl.cs

@@ -31,7 +31,7 @@ namespace InABox.DynamicGrid
         {
         }
 
-        protected override void SaveItem(T item)
+        public override void SaveItem(T item)
         {
             CoreRow row;
             if (rowindex == -1)

+ 3 - 5
InABox.DynamicGrid/FormDesigner/DynamicFormControlGrid.cs

@@ -37,7 +37,7 @@ namespace InABox.DynamicGrid
             action?.Invoke(table, null);
         }
 
-        protected override void SaveItem(T item)
+        public override void SaveItem(T item)
         {
             if (!Items.Contains(item))
                 Items.Add(item);
@@ -45,12 +45,10 @@ namespace InABox.DynamicGrid
 
         protected override Document LoadDocument(Guid id)
         {
-            Document doc = null;
+            Document? doc = null;
             if (id == Guid.Empty)
                 doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(id)).FirstOrDefault();
-            if (doc == null)
-                doc = new Document();
-            return doc;
+            return doc ?? new Document();
         }
 
         protected override Document FindDocument(string filename)

+ 30 - 2
InABox.DynamicGrid/FormDesigner/DynamicFormDesignGrid.cs

@@ -180,6 +180,10 @@ namespace InABox.DynamicGrid
         public bool IsEditing { get => _mode == FormMode.Editing || _mode == FormMode.Filling; }
         public bool IsChanged => _isChanged;
 
+        public delegate DigitalFormVariable? CreateVariableHandler(Type fieldType);
+
+        public event CreateVariableHandler? OnCreateVariable;
+
         public IList<DigitalFormVariable> Variables
         {
             get => _variables;
@@ -669,7 +673,7 @@ namespace InABox.DynamicGrid
             }
         }
 
-        private void AddVariableClick(Tuple<DigitalFormVariable, int, int> tuple)
+        private void AddVariable(Tuple<DigitalFormVariable, int, int> tuple)
         {
             if(Activator.CreateInstance(tuple.Item1.FieldType()) is not DFLayoutField field)
             {
@@ -699,10 +703,34 @@ namespace InABox.DynamicGrid
                 var filtered = _variables.Where(x => !x.Hidden && !form.Elements.Any(v => string.Equals((v as DFLayoutField)?.Name, x.Code)));
                 foreach (var variable in filtered)
                     fields.Items.Add(CreateMenuItem(variable.Code, new Tuple<DigitalFormVariable, int, int>(variable, column, row),
-                        AddVariableClick));
+                        AddVariable));
                 if (fields.Items.Count > 0)
                     result.Items.Add(fields);
 
+                if(OnCreateVariable is not null)
+                {
+                    var variables = CreateMenuItem("Create New Variable", new Point(column, row), null);
+
+                    foreach (var fieldType in DFUtils.GetFieldTypes())
+                    {
+                        var caption = fieldType.GetCaption();
+                        if (string.IsNullOrWhiteSpace(caption))
+                        {
+                            caption = CoreUtils.Neatify(fieldType.Name);
+                        }
+                        variables.AddItem(caption, null, new Tuple<Type, int, int>(fieldType, column, row), (tuple) =>
+                        {
+                            var variable = OnCreateVariable?.Invoke(tuple.Item1);
+                            if(variable is not null)
+                            {
+                                _variables.Add(variable);
+                                AddVariable(new(variable, tuple.Item2, tuple.Item3));
+                            }
+                        });
+                    }
+                    result.Items.Add(variables);
+                }
+
 
                 var elements = CreateMenuItem("Add Object", new Point(column, row), null);
 

+ 8 - 1
InABox.DynamicGrid/FormDesigner/DynamicFormDesignWindow.xaml.cs

@@ -1,4 +1,5 @@
 using InABox.Core;
+using Org.BouncyCastle.Bcpg;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -22,7 +23,7 @@ namespace InABox.DynamicGrid
     public partial class DynamicFormDesignWindow : DynamicFormWindow
     {
 
-        public DynamicFormDesignWindow(): base()
+        public DynamicFormDesignWindow() : base()
         {
             InitializeComponent();
 
@@ -43,6 +44,12 @@ namespace InABox.DynamicGrid
             }
         }
 
+        public event DynamicFormDesignGrid.CreateVariableHandler OnCreateVariable
+        {
+            add => Grid.OnCreateVariable += value;
+            remove => Grid.OnCreateVariable -= value;
+        }
+
         public string SaveLayout()
         {
             return Form.SaveLayout();

+ 164 - 0
InABox.DynamicGrid/FormDesigner/DynamicFormLayoutGrid.cs

@@ -0,0 +1,164 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Controls;
+using System.Windows.Media.Imaging;
+using InABox.Core;
+using InABox.DynamicGrid;
+using InABox.WPF;
+
+namespace InABox.DynamicGrid
+{
+    public abstract class DynamicFormLayoutGrid<T> : DynamicOneToManyGrid<DigitalForm, DigitalFormLayout> where T : Entity, IRemotable, IPersistent, new()
+    {
+        private readonly BitmapImage design = Properties.Resources.design.AsBitmapImage();
+
+        public DynamicFormLayoutGrid()
+        {
+            Options.AddRange(DynamicGridOption.RecordCount);
+            ActionColumns.Add(new DynamicImageColumn(DesignImage, DesignClick));
+            //AddButton("Design", PRSDesktop.Resources.design.AsBitmapImage(), DesignClick);
+            HiddenColumns.Add(x => x.Layout);
+
+            AddButton("Auto Generate", null, AutoGenerate_Click);
+            AddButton("Duplicate", null, Duplicate_Click);
+        }
+
+        private bool Duplicate_Click(Button btn, CoreRow[] rows)
+        {
+            if (!rows.Any()) return false;
+
+            SaveItems(rows.Select(x =>
+            {
+                var layout = x.ToObject<DigitalFormLayout>();
+                layout.ID = Guid.Empty;
+                return layout;
+            }).ToArray());
+            return true;
+        }
+
+        private bool AutoGenerate_Click(Button btn, CoreRow[] rows)
+        {
+            var menu = new ContextMenu();
+
+            menu.AddItem("Desktop Layout", null, AddDesktop_Click);
+            menu.AddItem("Mobile Layout", null, AddMobile_Click);
+
+            menu.IsOpen = true;
+
+            return false;
+        }
+
+        private BitmapImage? DesignImage(CoreRow? row)
+        {
+            return row != null ? design : null;
+        }
+
+        private void AddMobile_Click()
+        {
+            var item = CreateItem();
+
+            item.Layout = DFLayout.GenerateAutoMobileLayout(GetVariables()).SaveLayout();
+            item.Type = DFLayoutType.Mobile;
+
+            if (EditItems(new[] { item }))
+            {
+                SaveItem(item);
+                Refresh(false, true);
+                OnChanged?.Invoke(this);
+            }
+        }
+
+        private void AddDesktop_Click()
+        {
+            var item = CreateItem();
+
+            item.Layout = DFLayout.GenerateAutoDesktopLayout(GetVariables()).SaveLayout();
+            item.Type = DFLayoutType.Desktop;
+
+            if (EditItems(new[] { item }))
+            {
+                SaveItem(item);
+                Refresh(false, true);
+                OnChanged?.Invoke(this);
+            }
+        }
+
+        private DynamicOneToManyGrid<DigitalForm, DigitalFormVariable>? GetVariableGrid()
+            => EditorGrid.Pages?.FirstOrDefault(x => x is DynamicOneToManyGrid<DigitalForm, DigitalFormVariable>)
+                as DynamicOneToManyGrid<DigitalForm, DigitalFormVariable>;
+
+        private List<DigitalFormVariable> GetVariables()
+            => GetVariableGrid()?.Items.ToList() ?? new List<DigitalFormVariable>();
+
+        private void Design(DigitalFormLayout layout)
+        {
+            var variables = GetVariables();
+
+            var newVariables = new List<DigitalFormVariable>();
+
+            var form = new DynamicFormDesignWindow
+            {
+                Type = layout.Type
+            };
+            form.OnCreateVariable += (fieldType) =>
+            {
+                if (DynamicVariableUtils.CreateAndEdit(Item, GetVariables(), fieldType, out var variable))
+                {
+                    newVariables.Add(variable);
+                    return variable;
+                }
+                return null;
+            };
+            form.LoadLayout(layout, variables);
+            form.Initialize();
+
+            if (form.ShowDialog() == true)
+            {
+                layout.Layout = form.SaveLayout();
+                SaveItem(layout);
+
+                var grid = GetVariableGrid();
+                if (grid is not null)
+                {
+                    grid.SaveItems(newVariables.ToArray());
+                    grid.Refresh(false, true);
+                }
+            }
+        }
+
+        private bool DesignClick(CoreRow? row)
+        {
+            if (row == null)
+                return false;
+
+            Design(LoadItem(row));
+
+            return false;
+        }
+
+
+        //public override void SaveItem(DigitalFormLayout item)
+        //{
+        //    bool bActive = item.Active;
+        //    foreach (var other in Items.Where(x=>(x != item) && (x.Type == item.Type)))
+        //    {
+        //        if (item.Active)
+        //        {
+        //            if (other.Active)
+        //                other.Active = false;
+        //        }
+        //        else
+        //            bActive = bActive || other.Active;
+        //    }
+        //    if (!bActive)
+        //        item.Active = true;
+        //    base.SaveItem(item);
+        //}
+
+        protected override void DoDoubleClick(object sender)
+        {
+            DesignClick(SelectedRows.FirstOrDefault());
+        }
+    }
+}

+ 107 - 94
InABox.DynamicGrid/FormDesigner/DynamicVariableGrid.cs

@@ -1,9 +1,11 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Windows;
 using System.Windows.Controls;
 using InABox.Core;
+using InABox.WPF;
 using NPOI.Util.Collections;
 
 namespace InABox.DynamicGrid
@@ -74,12 +76,105 @@ namespace InABox.DynamicGrid
             return true;
         }
 
-        public bool EditProperties(Type type, DFLayoutFieldProperties item)
+        private void CreateMenu(ContextMenu parent, string header, Type type)
+        {
+            parent.AddItem(header, null, type, (itemtype) =>
+            {
+                if(DynamicVariableUtils.CreateAndEdit(Item, Items, itemtype, out var variable))
+                {
+                    SaveItem(variable);
+                    Refresh(false, true);
+                }
+            });
+        }
+
+        protected override void DoAdd()
+        {
+            var menu = new ContextMenu();
+
+            foreach(var fieldType in DFUtils.GetFieldTypes())
+            {
+                var caption = fieldType.GetCaption();
+                if (string.IsNullOrWhiteSpace(caption))
+                {
+                    caption = CoreUtils.Neatify(fieldType.Name);
+                }
+                CreateMenu(menu, caption, fieldType);
+            }
+
+            menu.IsOpen = true;
+        }
+
+        /*protected override DigitalFormVariable LoadItem(CoreRow row)
+        {
+            return Items.FirstOrDefault(r => r.ID.Equals(row.Get<DigitalFormVariable, Guid>(c => c.ID)));
+        }*/
+
+        protected override void DoEdit()
+        {
+            if (!SelectedRows.Any())
+                return;
+            var variable = LoadItem(SelectedRows.First());
+            var properties = variable.CreateProperties();
+            if (DynamicVariableUtils.EditProperties(Item, Items, properties.GetType(), properties))
+            {
+                variable.SaveProperties(properties);
+                SaveItem(variable);
+                Refresh(false, true);
+            }
+        }
+
+        protected override void DoDelete()
+        {
+            var rows = SelectedRows.ToArray();
+
+            if (rows.Any())
+                if (CanDeleteItems(rows))
+                    if (MessageBox.Show("Are you sure you want to delete this variable? This will all cause data associated with this variable to be lost.\n(If you want to just hide the variable, set it to 'Hidden' instead.)", "Confirm Deletion", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+                    {
+                        DeleteItems(rows);
+                        SelectedRows = Array.Empty<CoreRow>();
+                        OnChanged?.Invoke(this);
+                        Refresh(false, true);
+                        SelectItems(null);
+                    }
+        }
+
+        protected override bool FilterRecord(CoreRow row)
+        {
+            return ShowHidden || !row.Get<DigitalFormVariable, bool>(x => x.Hidden);
+        }
+    }
+
+    public static class DynamicVariableUtils
+    {
+        public static bool CreateAndEdit(
+            DigitalForm form, IList<DigitalFormVariable> variables,
+            Type fieldType,
+            [NotNullWhen(true)] out DigitalFormVariable? variable)
+        {
+            var fieldBaseType = fieldType.GetSuperclassDefinition(typeof(DFLayoutField<>));
+            if (fieldBaseType != null)
+            {
+                var propertiesType = fieldBaseType.GetGenericArguments()[0];
+                var properties = Activator.CreateInstance(propertiesType) as DFLayoutFieldProperties;
+                if (DynamicVariableUtils.EditProperties(form, variables, propertiesType, properties))
+                {
+                    variable = new DigitalFormVariable();
+                    variable.SaveProperties(fieldType, properties);
+                    return true;
+                }
+            }
+            variable = null;
+            return false;
+        }
+
+        public static bool EditProperties(DigitalForm form, IList<DigitalFormVariable> variables, Type type, DFLayoutFieldProperties item)
         {
             var editor = new DynamicEditorForm(type);
             if (item is DFLayoutLookupFieldProperties)
             {
-                editor.OnFormCustomiseEditor += LookupEditor_OnFormCustomiseEditor;
+                editor.OnFormCustomiseEditor += (sender, items, column, editor) => LookupEditor_OnFormCustomiseEditor(sender, variables, items, column, editor);
                 editor.OnEditorValueChanged += (sender, name, value) =>
                 {
                     var result = DynamicGridUtils.UpdateEditorValue(new[] { item }, name, value);
@@ -95,7 +190,7 @@ namespace InABox.DynamicGrid
                         }
 
                         var propertiesEditor = grid.FindEditor(nameof(DFLayoutLookupFieldProperties.AdditionalProperties));
-                        if(propertiesEditor is MultiLookupEditorControl multi && multi.EditorDefinition is ComboMultiLookupEditor combo)
+                        if (propertiesEditor is MultiLookupEditorControl multi && multi.EditorDefinition is ComboMultiLookupEditor combo)
                         {
                             combo.Clear();
                             multi.Configure();
@@ -106,7 +201,7 @@ namespace InABox.DynamicGrid
             }
             else
             {
-                editor.OnFormCustomiseEditor += Editor_OnFormCustomiseEditor;
+                editor.OnFormCustomiseEditor += (sender, items, column, editor) => Editor_OnFormCustomiseEditor(sender, variables, column, editor);
             }
             editor.Items = new BaseObject[] { item };
             editor.OnDefineLookups += o =>
@@ -118,9 +213,9 @@ namespace InABox.DynamicGrid
                 // so that I can get access to the "AppliesTo" property, and thus the list of properties that can be updated
                 // Nothing to see here, I promise!
                 CoreTable? values;
-                if(o.ColumnName == "Property")
+                if (o.ColumnName == "Property")
                 {
-                    values = def.Values(colname, new object[] { Item });
+                    values = def.Values(colname, new object[] { form });
                 }
                 else
                 {
@@ -132,12 +227,12 @@ namespace InABox.DynamicGrid
             return editor.ShowDialog() == true;
         }
 
-        private void Editor_OnFormCustomiseEditor(IDynamicEditorForm sender, object[] items, DynamicGridColumn column, BaseEditor editor)
+        private static void Editor_OnFormCustomiseEditor(IDynamicEditorForm sender, IList<DigitalFormVariable> vars, DynamicGridColumn column, BaseEditor editor)
         {
             if ((column.ColumnName == "Expression" || column.ColumnName == "ColourExpression") && editor is ExpressionEditor exp)
             {
                 var variables = new List<string>();
-                foreach (var variable in Items)
+                foreach (var variable in vars)
                 {
                     //variables.Add(variable.Code);
                     foreach (var col in variable.GetVariableColumns())
@@ -150,99 +245,17 @@ namespace InABox.DynamicGrid
             }
         }
 
-        private void LookupEditor_OnFormCustomiseEditor(IDynamicEditorForm sender, object[] items, DynamicGridColumn column, BaseEditor editor)
+        private static void LookupEditor_OnFormCustomiseEditor(IDynamicEditorForm sender, IList<DigitalFormVariable> vars, object[] items, DynamicGridColumn column, BaseEditor editor)
         {
-            if(column.ColumnName == "Filter" && editor is FilterEditor fe)
+            if (column.ColumnName == "Filter" && editor is FilterEditor fe)
             {
-                var properties = items[0] as DFLayoutLookupFieldProperties;
+                var properties = (items[0] as DFLayoutLookupFieldProperties)!;
                 var lookupType = properties.LookupType;
                 var entityType = CoreUtils.GetEntityOrNull(lookupType);
                 fe.Type = entityType;
             }
-            Editor_OnFormCustomiseEditor(sender, items, column, editor);
-        }
-
-        private void CreateMenu(ContextMenu parent, string header, Type type)
-        {
-            var menu = new MenuItem();
-            menu.Header = header;
-            menu.Tag = type;
-            menu.Click += (o, e) =>
-            {
-                var itemtype = (o as MenuItem).Tag as Type;
-
-                var fieldBaseType = itemtype.GetSuperclassDefinition(typeof(DFLayoutField<>));
-                if(fieldBaseType != null)
-                {
-                    var propertiesType = fieldBaseType.GetGenericArguments()[0];
-                    var properties = Activator.CreateInstance(propertiesType) as DFLayoutFieldProperties;
-                    if (EditProperties(propertiesType, properties))
-                    {
-                        var variable = CreateItem();
-                        variable.SaveProperties(itemtype, properties);
-                        SaveItem(variable);
-                        Refresh(false, true);
-                    }
-                }
-            };
-            parent.Items.Add(menu);
-        }
-
-        protected override void DoAdd()
-        {
-            var menu = new ContextMenu();
-
-            foreach(var fieldType in DFUtils.GetFieldTypes())
-            {
-                var caption = fieldType.GetCaption();
-                if (string.IsNullOrWhiteSpace(caption))
-                {
-                    caption = CoreUtils.Neatify(fieldType.Name);
-                }
-                CreateMenu(menu, caption, fieldType);
-            }
-
-            menu.IsOpen = true;
-        }
-
-        /*protected override DigitalFormVariable LoadItem(CoreRow row)
-        {
-            return Items.FirstOrDefault(r => r.ID.Equals(row.Get<DigitalFormVariable, Guid>(c => c.ID)));
-        }*/
-
-        protected override void DoEdit()
-        {
-            if (!SelectedRows.Any())
-                return;
-            var variable = LoadItem(SelectedRows.First());
-            var properties = variable.CreateProperties();
-            if (EditProperties(properties.GetType(), properties))
-            {
-                variable.SaveProperties(properties);
-                SaveItem(variable);
-                Refresh(false, true);
-            }
+            Editor_OnFormCustomiseEditor(sender, vars, column, editor);
         }
 
-        protected override void DoDelete()
-        {
-            var rows = SelectedRows.ToArray();
-
-            if (rows.Any())
-                if (CanDeleteItems(rows))
-                    if (MessageBox.Show("Are you sure you want to delete this variable? This will all cause data associated with this variable to be lost.\n(If you want to just hide the variable, set it to 'Hidden' instead.)", "Confirm Deletion", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
-                    {
-                        DeleteItems(rows);
-                        SelectedRows = Array.Empty<CoreRow>();
-                        OnChanged?.Invoke(this);
-                        Refresh(false, true);
-                        SelectItems(null);
-                    }
-        }
-
-        protected override bool FilterRecord(CoreRow row)
-        {
-            return ShowHidden || !row.Get<DigitalFormVariable, bool>(x => x.Hidden);
-        }
     }
 }

+ 4 - 0
InABox.DynamicGrid/InABox.DynamicGrid.csproj

@@ -87,6 +87,7 @@
 
     <ItemGroup>
       <None Remove="Resources\add.png" />
+      <None Remove="Resources\design.png" />
       <None Remove="Resources\filter_set.png" />
       <None Remove="Resources\header_closed.png" />
       <Resource Include="Resources\add.png">
@@ -169,6 +170,9 @@
         <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       </Resource>
       <None Remove="Resources\disk.png" />
+      <Resource Include="Resources\design.png">
+        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      </Resource>
       <Resource Include="Resources\disk.png">
         <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       </Resource>

+ 10 - 0
InABox.DynamicGrid/Properties/Resources.Designer.cs

@@ -260,6 +260,16 @@ namespace InABox.DynamicGrid.Properties {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        public static System.Drawing.Bitmap design {
+            get {
+                object obj = ResourceManager.GetObject("design", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized resource of type System.Drawing.Bitmap.
         /// </summary>

+ 3 - 0
InABox.DynamicGrid/Properties/Resources.resx

@@ -443,4 +443,7 @@
   <data name="header_closed" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\header_closed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="design" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\design.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
 </root>

二進制
InABox.DynamicGrid/Resources/design.png