icsharpcode / WpfDesigner

The WPF Designer from SharpDevelop
MIT License
958 stars 259 forks source link

Dynamic DesignItem #44

Closed khalili-mahdi closed 6 years ago

khalili-mahdi commented 6 years ago

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

jogibear9988 commented 6 years ago

Sure:

var changeGroup = designItemContainer.OpenGroup("blabla");
var button = new Button();
var buttonDesignItem = designItemContainer.Services.Component.RegisterComponentForDesigner(button);
designItemContainer.ContentProperty.CollectionElements.Add(buttonDesignItem);
changeGroup.Commit();
khalili-mahdi commented 6 years ago

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?

jogibear9988 commented 6 years ago

sure:

 buttonDesignItem.Properties.GetAttachedProperty(Canvas.LeftProperty).SetValue(130.0);
khalili-mahdi commented 6 years ago

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

jogibear9988 commented 6 years ago

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)

jogibear9988 commented 6 years ago

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

khalili-mahdi commented 6 years ago

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

khalili-mahdi commented 6 years ago

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

jogibear9988 commented 6 years ago

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(...“

khalili-mahdi commented 6 years ago

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?

jogibear9988 commented 6 years ago

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