icsharpcode / WpfDesigner

The WPF Designer from SharpDevelop

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Dynamic DesignItem

khalili-mahdi opened this issue · comments

is there any way i can add designItem to designSurface dynamically ?

Sure:

var changeGroup = designItemContainer.OpenGroup("blabla");
var button = new Button();
var buttonDesignItem = designItemContainer.Services.Component.RegisterComponentForDesigner(button);
designItemContainer.ContentProperty.CollectionElements.Add(buttonDesignItem);
changeGroup.Commit();

i did this:
var designItemContainer = designSurface.DesignContext.RootItem; var changeGroup = designItemContainer.OpenGroup("blabla"); var button = new Button(); var buttonDesignItem = designItemContainer.Services.Component.RegisterComponentForDesigner(button); designItemContainer.ContentProperty.CollectionElements.Add(buttonDesignItem); changeGroup.Commit();
TY , can i change position of item in designPanel?

sure:

 buttonDesignItem.Properties.GetAttachedProperty(Canvas.LeftProperty).SetValue(130.0);

almost solved problem but there is a little issue here this does not changed my control position, i cant upload whole project , here is my base control

public class BaseControl : UserControl,INotifyPropertyChanged
    {
        XElement parser = XElement.Load("../../Resource/Parser2.xml");
        public BaseControl()
        {
            
        }

        #region Implementd INotify Interface
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion

        #region Dynamic Properties
        private IDictionary<string, object> Properties { get; set; } = new ConcurrentDictionary<string, object>();

        /// <summary>
        ///     this will return all dynamic properties created from xelement
        /// </summary>
        /// <returns></returns>
        public IDictionary<string, object> GetProperties()
        {
            return Properties;
        }

        #endregion

        #region Set parser refrence Xelement
        private ObservableCollection<XProperty> _xproperties = new ObservableCollection<XProperty>();
        /// <summary>
        /// give properties of parser as array to init properties
        /// </summary>
        /// <param name="elements">all properties of parser as array</param>
        public void InitParser(IEnumerable<XElement> elements)
        {
            foreach (var element in elements)
            {
                string name = element.Attribute("Name") != null ? element.Attribute("Name")?.Value : "";
                if (name == "") throw new Exception();
                string noeh = element.Attribute("Noeh") != null ? element.Attribute("Noeh")?.Value : "String";
                string exist = element.Attribute("Exist") != null ? element.Attribute("Exist")?.Value : "";
                string by = element.Attribute("By") != null ? element.Attribute("By")?.Value : "";
                string @default = element.Attribute("Default") != null ? element.Attribute("Default")?.Value : "";
                XProperty xelement = new XProperty(name, noeh, exist, by, @default);
                _xproperties.Add(xelement);
            }
            addProperties(_xproperties);
        }

        #endregion

        #region raw materials from parser without value
        ObservableCollection<XConverted> rawMaterials = new ObservableCollection<XConverted>();
        /// <summary>
        /// this will add raw properties from parser
        /// </summary>
        /// <param name="properties"></param>
        private void addProperties(ObservableCollection<XProperty> properties)
        {
            foreach (XProperty property in properties)
            {
                string tempEnum = "";
                Type type = null;
                if (!property.Noeh.Contains('$')&& !property.Noeh.Contains('#'))
                {
                    XType.Types.TryGetValue(property.Noeh, out type);
                }
                else
                {
                    if (property.Noeh.Contains('$'))
                    {
                        string temp = property.Noeh.Split('$')[0];
                        tempEnum = property.Noeh.Split('$')[1];
                        XType.Types.TryGetValue(temp, out type);
                    }
                    else
                    {
                        throw new NotImplementedException();
                        //string temp = property.Noeh.Split('#')[0];
                        //tempEnum = property.Noeh.Split('#')[1];
                        //XType.Types.TryGetValue(temp, out type);

                    }
                }
                XConverted xc = new XConverted(property.Name,type);
                xc.SetValue(property.Default==""?null:property.Default);
                if(tempEnum != "")
                {
                    var listEnums = parser.Descendants("Enums").First().Descendants("Enum");
                    var values = listEnums.First(o => o.Attribute("Key")?.Value == tempEnum).Attribute("Val")?.Value.Split('$');
                    xc.MyEnum = values;
                }
                rawMaterials.Add(xc);
            }
            AddValues();
        }
        #endregion

        #region initialize raw materials with values come from wfo
        
        /// <summary>
        /// initializing raw materials with values from wfo file
        /// </summary>
        /// <param name="Attributes"></param>
        public void Init(IEnumerable<XAttribute> Attributes)
        {
            if( rawMaterials.Count != 0)
            {
                foreach(XAttribute attribute in Attributes)
                {

                    string name = attribute.Name.ToString();
                    string value = attribute.Value;
                    rawMaterials.First(o => o.Key == name).SetValue(value);

                }
                AddValues();
            }
            else
            {
                throw new System.ArgumentException("You might not initialized parser use : InitParser() -> there is a null property", "rawMaterials");
            }
        }
        #endregion


        #region creating dictionary of properties to dynamic grid uses
        enum xx { one, two };
        ConcurrentDictionary<string, object> RawProperties = new ConcurrentDictionary<string, object>();
        /// <summary>
        /// adding values from wfo file to raw data and producing properties for propertygrid uses
        /// </summary>
        /// 
        private void AddValues()
        {
            foreach (XConverted data in rawMaterials)
            {
                object temp;
                switch (data.Type.Name)
                {
                    
                    case "Boolean":
                        temp = data.Value!=null? XConv.STB(data.Value): false;
                        break;
                    case "Int32":
                        temp = data.Value != null ? XConv.STI(data.Value):0;
                        break;
                    case "Enum":
                        xx yy1 = xx.one;
                        //default value => data.value
                        temp = data.Value != null ? XConv.STE(data.MyEnum) : yy1;
                        break;
                    case "Point":
                        temp = data.Value != null ? XConv.STP(data.Value):new System.Windows.Point(0,0);
                        break;
                    case "Thickness":
                        temp = data.Value != null ? XConv.STC(data.Value):new System.Windows.Thickness(0);
                        break;
                    case "long":
                        temp = data.Value != null ? XConv.STL(data.Value):0;
                        break;
                    case "float":
                        temp = data.Value != null ? XConv.STF(data.Value):0;
                        break;
                    default:
                        temp = data.Value!= null ? data.Value : "";
                        //string "String"
                        break;
                }
                if(!RawProperties.ContainsKey(data.Key))
                RawProperties.TryAdd(data.Key, temp);
                else
                {
                    RawProperties[data.Key] = temp;
                }
            }
            Properties = RawProperties;
            OnPropertyChanged(nameof(Properties));
        }
        #endregion

        #region raw data for propertyGrid
        private DictionaryPropertyGridAdapter<string, object> _selectedObj;
        public DictionaryPropertyGridAdapter<string, object> SelectedObj
        {
            get
            {
                if (_selectedObj == null)
                {
                    if(rawMaterials.Count == 0)
                    {
                        throw new NotImplementedException();
                    }
                    _selectedObj = new DictionaryPropertyGridAdapter<string, object>(this.GetProperties());
                }
                return _selectedObj;
            }
            set
            {
                _selectedObj = value;
                OnPropertyChanged(nameof(this.SelectedObj));
            }
        }
        #endregion
    }

i have my own control and i create my own PropertyGrid with dynamic properties which is working but in design setting Canvas.LefProperty does not works, i know you have PropertyGrid but that is for your designItems which i have my own

Don't know what you mean!
You have your own Property Grid, which one?

You need to change the Properties of the DesignItem, not of the View or Component, or the XAML will not be changed. If you use your own Property Grid, maybe it has a event when a Property is changed wich you could use?

You could also change what our PropertyGrid is showing (see #45)

Maybe I've time next week to add a Example how I used "DesignItemBinding" to create my special Property Editors for some controls.

i have a list of controls which i make them from a xml file
public List<BaseControl> Controls { get; private set; } = new List<BaseControl>();
then i want to load this controls to view

foreach (BaseControl control in fd.Controls)
            {
                var designItemContainer = designSurface.DesignContext.RootItem;
                var changeGroup = designItemContainer.OpenGroup("blabla");

                var ControlDesignItem = designItemContainer.Services.Component.RegisterComponentForDesigner(control);
                //ControlDesignItem.Properties.GetAttachedProperty(Canvas.WidthProperty).SetValue(230.0);
                //ControlDesignItem.Properties.GetAttachedProperty(Canvas.HeightProperty).SetValue(230.0);
                ControlDesignItem.Properties.GetAttachedProperty(Canvas.RightProperty).SetValue(130.0);
                ControlDesignItem.Properties.GetAttachedProperty(Canvas.BottomProperty).SetValue(130.0);
                ControlDesignItem.Properties.GetAttachedProperty(Canvas.LeftProperty).SetValue(130.0);
                ControlDesignItem.Properties.GetAttachedProperty(Canvas.TopProperty).SetValue(130.0);

                designItemContainer.ContentProperty.CollectionElements.Add(ControlDesignItem);
                changeGroup.Commit();
            }

this is showing my control but my control is full size in DesignSurface
i can resize controls from designSurface UI but i am looking for a way to resize them with code and Canvas.LeftProperty does not works

i think maybe there is a property which setting my control row and col in grid , so i have 1 row and 1 col and its showing full size ,
so Can i set margin?
i tried this :
ControlDesignItem.Properties.GetAttachedProperty(Canvas.MarginProperty).SetValue(new Thickness(130));

If your Container is a Grid, Canvas.LeftProperty will have no Effect! And Margin is not an Attached Property, use GetProperty(FrameworkElement.MarginProperty... And the Value of the Margin needs to be a „new Thickness(...“

GJ man ,ty for your fast answers
yeah this is working
ControlDesignItem.Properties.GetProperty(FrameworkElement.MarginProperty).SetValue(new Thickness(130));
if i want to use Canvas.MarginProperty what container should i use?

Canvas.MarginProperty is same a Frameworkelement.MarginProperty (its a Derived Static Field). If you want to use Canvas.LeftProperty you should use a Canvas as a Container