Avatar billede 2705 Nybegynder
18. august 2010 - 15:48 Der er 4 kommentarer og
2 løsninger

Forskellige elementer i en liste

Hej

Jeg har en grafisk editor hvor jeg har 3 forskellige typer elementer at arbejde med. Jeg har oprettet en klasse GFXElement som er en base-klasse med bl.a. X & Y koordinater. Til de 3 forskellige typer elementer (GFXButton, GFXLabel, GFXImage) er der så nogle properties som f.eks. kun er fælles for 2 af typerne.
Eksempel:
GFXButton og GFXLabel har begge en text men det har GFXImage ikke.

Når jeg grafisk markerer en enkelt type (f.eks. GFXButton) har jeg mulighed for at redigere alle dens properties i en usercontrol.
Men hvis jeg markerer forskellige typer elementer skal jeg på en måde have fundet ud hvilke properties der er fælles for dem der er valgt?

Jeg har tænkt på at lave en liste med de properties der findes, og lave en løkke hvor jeg tæller op hver gang jeg møder en fælles property. Til sidst kan jeg se om antallet af elementer svarer til min tæller for hver property og på den måde se om den er fælles for alle dem der er valgt.
Så hvis jeg har markeret en GFXButton og en GFXLabel er text fælles, men markerer jeg også en GFXImage er det kun X & Y der er fælles.
Håber i forstår, ellers bare spørg!
Avatar billede Pulchra Nybegynder
18. august 2010 - 21:44 #1
Tror dette måske ville være en løsning.


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    internal class Program
    {
        #region PropertyType enum

        public enum PropertyType
        {
            Text,
            XCoordinate,
            YCoordinate,
            Color
        }

        #endregion

        private static void Main(string[] args)
        {
            //Vil udskrive XCoordinate, YCoordinate
            PrintCommonProperties(new List<GfxElement>
                                      {
                                          new GfxLabel(),
                                          new GfxImage(),
                                          new GfxButton()
                                      });

            //Vil udskrive Text, XCoordinate, YCoordinate
            PrintCommonProperties(new List<GfxElement>
                                      {
                                          new GfxLabel(),
                                          new GfxButton()
                                      });

            PrintCommonProperties(new List<GfxElement>
                                      {
                                          new GfxImage(),
                                          new GfxColorButton()
                                      });

            Console.ReadKey();
        }

        private static void PrintCommonProperties(IEnumerable<GfxElement> gfxElements)
        {
            var values = (PropertyType[]) Enum.GetValues(typeof (PropertyType));

            IEnumerable<PropertyType> propertyTypes =
                values.Where(v => gfxElements.All(element => element.SupportsProperty(v)));

            Console.WriteLine(Environment.NewLine);
            foreach (PropertyType propertyType in propertyTypes)
            {
                Console.WriteLine(propertyType);
            }
        }

        #region Nested type: GfxButton

        public class GfxButton : GfxElement
        {
            public override bool SupportsProperty(PropertyType propertyType)
            {
                switch (propertyType)
                {
                    case PropertyType.Text:
                        return true;
                    default:
                        return base.SupportsProperty(propertyType);
                }
            }
        }

        #endregion

        #region Nested type: GfxColorButton

        public class GfxColorButton : GfxButton
        {
            public override bool SupportsProperty(PropertyType propertyType)
            {
                switch (propertyType)
                {
                    case PropertyType.Color:
                        return true;
                    default:
                        return base.SupportsProperty(propertyType);
                }
            }
        }

        #endregion

        #region Nested type: GfxElement

        public abstract class GfxElement
        {
            public virtual bool SupportsProperty(PropertyType propertyType)
            {
                switch (propertyType)
                {
                    case PropertyType.XCoordinate:
                    case PropertyType.YCoordinate:
                        return true;
                    default:
                        return false;
                }
            }
        }

        #endregion

        #region Nested type: GfxImage

        public class GfxImage : GfxElement
        {
            public override bool SupportsProperty(PropertyType propertyType)
            {
                switch (propertyType)
                {
                    case PropertyType.Color:
                        return true;
                    default:
                        return base.SupportsProperty(propertyType);
                }
            }
        }

        #endregion

        #region Nested type: GfxLabel

        public class GfxLabel : GfxElement
        {
            public override bool SupportsProperty(PropertyType propertyType)
            {
                switch (propertyType)
                {
                    case PropertyType.Text:
                        return true;
                    default:
                        return base.SupportsProperty(propertyType);
                }
            }
        }

        #endregion
    }
}

/Hallur
Avatar billede 2705 Nybegynder
19. august 2010 - 08:22 #2
Det kunne måske godt virke, men ville egentlig hellere definere i min usercontrol hvilke properties der er fælles, og tage den derfra...
Avatar billede Pulchra Nybegynder
19. august 2010 - 08:42 #3
ok, må sige at jeg ikke helt forstår hvad det er du har tænkt dig :) Kunnu du måske uddype det lidt, med f.eks. lidt pseudo kode?

/Hallur
Avatar billede 2705 Nybegynder
19. august 2010 - 09:29 #4
Jeg har prøvet at arbejde lidt videre på det og har fundet en løsning. Men du skal have tak for forsøget!

Først definerer jeg en enum med de fælles properties jeg kan have.
Dernæst laver jeg en samlet variabel til fælles properties og til sidst tjekker jeg om hver property skal med. Håber det samtidig uddyber spørgsmålet lidt.

private enum PropertyType
        {
            Text = 1,
            TextColor = 2,
            Font = 4,
            X = 8,
            Y = 16,
            Width = 32,
            Height = 64,
            Image = 128,
        }

            bool firstrun = true;
            PropertyType common = 0;
            PropertyType ptBtn = PropertyType.X|PropertyType.Y|PropertyType.Text|PropertyType.TextColor|PropertyType.Font|PropertyType.Width|PropertyType.Height|PropertyType.Image;
            PropertyType ptLbl = PropertyType.X|PropertyType.Y|PropertyType.Text|PropertyType.TextColor|PropertyType.Font;
            PropertyType ptImg = PropertyType.X|PropertyType.Y|PropertyType.Image;

            foreach (GFXElement elem in this.elementList)
            {
                if (elem is GFXButton)
                {                   
                    if (firstrun)
                    {
                        common = ptBtn;
                    }
                    else
                    {
                        common &= ptBtn;
                    }
                }
                else if (elem is GFXLabel)
                {
                    if (firstrun)
                    {
                        common = ptLbl;
                    }
                    else
                    {
                        common &= ptLbl;
                    }
                }
                else if (elem is GFXImage)
                {
                    if (firstrun)
                    {
                        common = ptImg;
                    }
                    else
                    {
                        common &= ptImg;
                    }
                }
                firstrun = false;
            }

            if ((common & PropertyType.X) == PropertyType.X)
            {
                Console.WriteLine("X skal med");
            }
            if ((common & PropertyType.Y) == PropertyType.Y)
            {
                Console.WriteLine("Y skal med");
            }
            if ((common & PropertyType.Width) == PropertyType.Width)
            {
                Console.WriteLine("Width skal med");
            }
            if ((common & PropertyType.Height) == PropertyType.Height)
            {
                Console.WriteLine("Height skal med");
            }
            if ((common & PropertyType.Text) == PropertyType.Text)
            {
                Console.WriteLine("Text skal med");
            }
            if ((common & PropertyType.TextColor) == PropertyType.TextColor)
            {
                Console.WriteLine("TextColor skal med");
            }
            if ((common & PropertyType.Font) == PropertyType.Font)
            {
                Console.WriteLine("Font skal med");
            }
            if ((common & PropertyType.Image) == PropertyType.Image)
            {
                Console.WriteLine("Image skal med");
            }
Avatar billede Pulchra Nybegynder
19. august 2010 - 10:36 #5
Godt du har fået det til at spille.
Nu kunne jeg ikke lade være, men her er en anden version, som gør det samme som din, men bruger linq til at finde fælles propertytypes :)

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        private static readonly PropertyType[] AllPropertyTypes = (PropertyType[])Enum.GetValues(typeof(PropertyType));

        static void Main()
        {
            const PropertyType common = PropertyType.X | PropertyType.Y;
            const PropertyType ptBtn = common | PropertyType.Text | PropertyType.TextColor | PropertyType.Font | PropertyType.Width | PropertyType.Height | PropertyType.Image;
            const PropertyType ptLbl = common | PropertyType.Text | PropertyType.TextColor | PropertyType.Font;
            const PropertyType ptImg = common | PropertyType.Image;
            List<PropertyType> propertyList = new List<PropertyType> { ptBtn, ptLbl, ptImg };
            List<PropertyType> propertyList2 = new List<PropertyType> { ptBtn, ptLbl };
            List<PropertyType> propertyList3 = new List<PropertyType> { ptBtn };

            PrintSupportedProperties(propertyList);
            PrintSupportedProperties(propertyList2);
            PrintSupportedProperties(propertyList3);

            /*Dette vil udskrive:
                X
                Y

                Text
                TextColor
                Font
                X
                Y

                Text
                TextColor
                Font
                X
                Y
                Width
                Height
                Image
            */
        }

        private static void PrintSupportedProperties(IEnumerable<PropertyType> propertyList)
        {
            var commonPropertyTypes = AllPropertyTypes.Where(p => propertyList.All(types => (types & p) == p));
            Console.WriteLine(Environment.NewLine);
            foreach (PropertyType propertyType in commonPropertyTypes)
            {
                Console.WriteLine(propertyType);
            }
        }

        [Flags]
        private enum PropertyType
        {
            Text = 1,
            TextColor = 2,
            Font = 4,
            X = 8,
            Y = 16,
            Width = 32,
            Height = 64,
            Image = 128,
        }
    }
}

/Hallur
Avatar billede 2705 Nybegynder
19. august 2010 - 10:54 #6
Ja det var også en mulighed. Man sparer lidt kode, men på denne måde bruger man lister med PropertyTypes i stedet for lister med GFXElements som jeg allerede har at arbejde med.

Jeg ved ikke umiddelbart hvad der er smartest, men nu lader jeg det være som det er :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester