IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Presentation Foundation Discussion :

Créer un contrôle utilisateur représentant une zone éditable sur une carte


Sujet :

Windows Presentation Foundation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Décembre 2015
    Messages : 3
    Par défaut Créer un contrôle utilisateur représentant une zone éditable sur une carte
    Bonjour,

    J'ai écrit un programme en WPF qui utilise une carte Bing Map sur laquelle je peux créer, en double-cliquant, des points définissant une zone.

    Voici un exemple de zone créée avec 4 points:
    Nom : Zone.png
Affichages : 587
Taille : 57,0 Ko

    Pour ce faire, en utilisant le concept MVVM, j'ai défini, dans ma ViewModel, une ObservableCollection d'objets Area constituant la source du MapItemsControl de la carte. La classe Area possède une propriété de type LocationCollection. Voici le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class Area
    {
    	public Area ()
    	{
    		this.Locations = new LocationCollection();
    	}
    	public LocationCollection Locations { get; set; }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //Dans la ViewModel
    public ObservableCollection<Area> Areas { get; set; }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //Dans la View
    <map:Map>
    	<map:MapItemsControl ItemsSource="{Binding Areas}">
    		<map:MapItemsControl.ItemTemplate>
    			<DataTemplate>
    				<map:MapPolygon Locations="{Binding Locations}" Fill="Red"/>
    			</DataTemplate>
    		</map:MapItemsControl.ItemTemplate>
    	</map:MapItemsControl>
    </map:Map>
    Pour l'instant, j'utilise un MapPolygon comme DataTemplate. J'aimerais le remplacer par un contrôle personnalisé en WPF qui afficherait aux points de définition de la zone des disques que l'utilisateur pourrait déplacer sur la carte afin de modifier la zone. Ces disques seraient uniquement visibles lorsque la zone est éditable. Les disques auraient, évidemment, la même location que les points définissant la zone.

    Le contrôle ressemblerait à ceci:
    Nom : Exemple_controle.png
Affichages : 476
Taille : 5,3 Ko

    Je ne vois pas comment réaliser le contrôle composé, finalement, d'un nombre de pushpins égal au nombre de points définis par l'utilisateur et d'un MapPolygon dont le nombre de côtés est également égal au nombre de points définis.

    Pouvez-vous me mettre sur la voie ?

    D'avance, merci.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Par défaut
    en fait avec wpf il y a un truc sympa a utiliser
    pour la carte tu utilise un canvas sur lequel tu place ton dessin que tu dessine et pour faire les points d'ancrage modifiable tu utilise le concept d'adorner ....
    cherche de ce coté
    je sais pas si ça répond au besoin que tu as mais au niveau concept ça ressemble a cela

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Décembre 2015
    Messages : 3
    Par défaut Test des Adorners
    En me basant sur l'exemple de Microsoft donné ici, j'ai réussi à mettre les points d'ancrage sur une TextBox (rectangle). Mais lorsque je dessine un polygone quelconque (autre qu'un rectangle), les points d'ancrage définissent un rectangle englobant mon polygone.

    Nom : Adorner.png
Affichages : 511
Taille : 3,1 Ko

    Ce n'est malheureusement pas ce que je veux. La méthode OnRender (voir le lien ci-dessus) utilise un objet RECT pour indiquer les points où mettre les ornements. Peut-on utiliser une autre classe pour mieux épouser la forme de mon polygone ?

    Je repose la question de mon premier post: N'existe-t-il pas un moyen en WPF de compléter le DataTemplate ci-dessous afin d'utiliser les points définis sur la carte par un utilisateur ("Locations" qui est une LocationCollection) pour afficher le polygone et les ronds à chaque angle du polygone ayant chacun pour position les items de la collection "Locations".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //Dans la View
    <map:Map>
    	<map:MapItemsControl ItemsSource="{Binding Areas}">
    		<map:MapItemsControl.ItemTemplate>
    			<DataTemplate>
    				<map:MapPolygon Locations="{Binding Locations}" Fill="Red"/>
    			</DataTemplate>
    		</map:MapItemsControl.ItemTemplate>
    	</map:MapItemsControl>
    </map:Map>

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Par défaut
    tu as regardé sur les adorner ?
    http://www.codeproject.com/Articles/...orners-in-XAML

    puis
    https://msdn.microsoft.com/fr-fr/lib...or=-2147217396

    http://www.nbdtech.com/Blog/archive/...ol-on-the.aspx

    et comme tu peux placer dans l'adorner autant de point d'ancrage que tu veux sur la forme que tu veux
    normalement tu peux faire ce que tu souhaite
    ainsi moi j'ai utiliser les adorner pour cela

    des points sur des courbes
    Nom : Image23.png
Affichages : 536
Taille : 68,5 Ko

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    49
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 49
    Par défaut
    En gros cela revient à afficher une couche vecteur par dessus une couche tuile. Sa ressemble fortement à du SIG.

    En modifiant radicalement ta réflexion tu peux partir sur un composant cartographique (MapWinGis, MapSui) et créer deux couches, une couche tuile avec Bing comme source (à voir si c'est possible avec Bing, sinon OpenStreetMap) et une couche vecteur.

    Les couches vecteurs permettent d'afficher des géométries (Point, Multipoint, Ligne, Multi Ligne, Polygone, Multi Polygone) et de les affiché grâce à un style (bordure, remplissage, texte, ...).

  6. #6
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour

    C'est un petit defi que tu peux relever dans le control Map WPF..

    Voici en premier un code exemple d'un AdornerPolygon (cas d'un Adorner pour 3 polygones dans un panel Canvas "itemhostpanel" d'un ItemsControl)....pour illustrer le probleme à resoudre.

    code behind .cs du Class Data (3 polygones à sommets crees aleatoirements):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Media;
    using System.Collections.ObjectModel;
    using System.Windows;
     
    namespace WPFTestApplication
    {
        public  class Zone
        {
            public Zone()
            {
                this.Locations = new PointCollection();
            }
            public PointCollection Locations { get; set; }
        }
     
        public class Zones:ObservableCollection<Zone>
        {
            private Zone zn;
            private int numVrtex ;
            private Random rnd = new Random();
            public Zones()
            {
     
                numVrtex = 6;
                zn = CreateZone(numVrtex);
                this.Add(zn);
     
                numVrtex = 4;
                zn = CreateZone(numVrtex);
                this.Add(zn);
     
                numVrtex = 3;
                zn = CreateZone(numVrtex);
                this.Add(zn);
     
            }
            private Zone CreateZone(int num)
            {
                Zone s = new Zone();
                for (int i = 1; i < num + 1; i++)
                {
                    Point p = new Point(rnd.Next(50, 500), rnd.Next(50, 500));
                    s.Locations.Add(p);
     
                }
                return s;
            }
     
        }
    }
    code behind .cs de l'AdornerPolygon:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Documents;
    using System.Windows.Controls.Primitives;
    using System.Windows.Shapes;
    using System.Collections;
    using System.Windows.Media;
     
     
    namespace WPFTestApplication
    {
        public class AdornerPolygon:Adorner
        {
            private Thumb theThumb ; 
            private Polygon thePolygon ; 
            private VisualCollection children;
     
            public AdornerPolygon(UIElement adornedElement)
                : base(adornedElement)
            {
                children = new VisualCollection(this);
     
                thePolygon =(Polygon)adornedElement;
     
                for (int i = 0; i < thePolygon.Points.Count; i++)
    			{
                    theThumb = new Thumb();
                    theThumb.Tag = i;
                    theThumb.DragDelta += new DragDeltaEventHandler(theThumb_DragDelta);
                    theThumb.MouseEnter += new System.Windows.Input.MouseEventHandler(AdornerPolygon_MouseEnter);
                    theThumb.MouseLeave += new System.Windows.Input.MouseEventHandler(AdornerPolygon_MouseLeave);
     
                    BuildAdornerCorner(theThumb);
     
     
                }
            }
     
     
     
     
            void theThumb_DragDelta(object sender, DragDeltaEventArgs args)
            {
                FrameworkElement adornedElement = this.AdornedElement as FrameworkElement ;
     
                Thumb hitThumb   = sender as  Thumb;
     
     
                if (adornedElement == null || hitThumb == null ) return;
     
                // Ensure that the Width and Height are properly initialized after the resize.
     
                EnforceSize(adornedElement);
     
                // Deplace le point du Polygon
     
                int index =children.IndexOf( hitThumb);
                Point p = thePolygon.Points[index];
                p.X += args.HorizontalChange;
                p.Y += args.VerticalChange;
                thePolygon.Points[index] = p;
     
                // Maj du Size du Polygon 
                // veuillez utiliser ActualWidt & ActualHeight du polygon
                // bogus dans exemple MSDN
     
                adornedElement.Width = Math.Max(
                    adornedElement.ActualWidth + args.HorizontalChange,
                    hitThumb.ActualWidth);
     
                adornedElement.Height = Math.Max(
                    adornedElement.ActualHeight + args.VerticalChange,
                    hitThumb.ActualHeight);
     
     
            }
     
     
     
            void AdornerPolygon_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
            {
                foreach (Thumb  item in children )
                {
                    item.Opacity = 1.0;
                }
     
            }
            void AdornerPolygon_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
            {
                foreach (Thumb item in children)
                {
                    item.Opacity = 0.0;
                }
     
            }
     
     
            #region Overrides
     
            protected override Visual GetVisualChild(int index)
            {
                return children[index];
            }
            protected override int VisualChildrenCount
            {
                get
                {
                    return children.Count;
                }
            }
            protected override Size ArrangeOverride(Size finalSize)
            {
                // adornerWidth & adornerHeight are used for placement as well.
     
                Double adornerWidth   = this.DesiredSize.Width;
                Double adornerHeight  = this.DesiredSize.Height;
                int index;
                foreach (Thumb item in children)
                {
                    index = (int)item.Tag;
                    Point p = thePolygon.Points[index];
                    item.Arrange(
                        new Rect(p.X - adornerWidth / 2, p.Y - adornerHeight / 2, 
                            adornerWidth, adornerHeight));	
                }
     
                //  Return the final size.
                return finalSize;
     
            }
     
            #endregion
     
     
            #region Private Methods
     
            private void BuildAdornerCorner(Thumb cornerThumb)
            {
                cornerThumb.Height = 10;
                cornerThumb.Width = 10;
                cornerThumb.Opacity = 0.0;
                cornerThumb.Background = new SolidColorBrush(Colors.MediumBlue  );
                children.Add(cornerThumb);
            }
     
     
     
            private void EnforceSize(FrameworkElement adornedElement)
            {
                if (adornedElement.Width.Equals(Double.NaN)) 
                      adornedElement.Width = adornedElement.DesiredSize.Width ;
     
                if (adornedElement.Height.Equals(Double.NaN)) 
                adornedElement.Height = adornedElement.DesiredSize.Height;
     
                FrameworkElement parent   = adornedElement.Parent as  FrameworkElement;
                if (parent != null)
                {
                        adornedElement.MaxHeight = parent.ActualHeight;
                        adornedElement.MaxWidth = parent.ActualWidth;
                }
     
     
            }
     
            #endregion
        }
    }
    code xaml du UserControl ControlExemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    <UserControl x:Class="WPFTestApplication.ControlAdorner"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:map="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
                 xmlns:local="clr-namespace:WPFTestApplication" 
     
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <UserControl.Resources>
            <local:Areas x:Key="myAreas" />
            <!--notre ancre-->
            <DataTemplate
                x:Key="PolygonTemplate"
                DataType="{x:Type local:Area}">
                <map:MapLayer 
                    x:Name="mapLayer"
                    Loaded="mapLayer_Loaded">
                    <map:MapPolygon 
                        x:Name="polygon"
                        Fill="Red" Stroke="DarkBlue" StrokeThickness="2.0"
                        Locations="{Binding Locations}"
                        >
                    </map:MapPolygon>
                    <map:MapItemsControl
                        ItemsSource="{Binding Locations}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate DataType="{x:Type map:Location}">
                                <TextBlock 
                                   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                                    FontSize="8"
                                    Background="Aquamarine"
                                    map:MapLayer.Position="{Binding Path=.}"
                                    Text="{Binding Path=CityName}"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
     
                    </map:MapItemsControl>
     
                </map:MapLayer>
     
            </DataTemplate>
        </UserControl.Resources>
        <Grid>
            <map:Map 
                x:Name="myMap"
                Center="36.351716,6.603069" ZoomLevel="8"
                CredentialsProvider="An5r6DfqH31dlVRbpF1b_0ohdgiqCGwVLOZo6-_o0TsRmI0ZNMDWyxWjmbk-OY8T"
                >
                <map:MapItemsControl    
                    ItemsSource="{Binding Source={StaticResource myAreas}}"
                    ItemTemplate="{StaticResource PolygonTemplate}">
                </map:MapItemsControl>
            </map:Map>
        </Grid>
    </UserControl>
    code .cs UserControl ControlExemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    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;
     
    namespace WPFTestApplication
    {
        /// <summary>
        /// Logique d'interaction pour MyControlExemple2.xaml
        /// </summary>
        public partial class ControlExemple : UserControl
        {
            private AdornerLayer myAdornerLayer;
            public ControlExemple()
            {
                InitializeComponent();
            }
     
     
            private void panelRoot_Loaded(object sender, RoutedEventArgs e)
            {
                Canvas panel = sender as Canvas;
     
                myAdornerLayer = AdornerLayer.GetAdornerLayer(panel );
                foreach ( UIElement  item in panel.Children )
                {
                    ContentPresenter cp = item as ContentPresenter;
     
                    Polygon pln = cp.ContentTemplate.FindName("polygon", cp) as Polygon;
                    if (pln ==null ) continue;
                    myAdornerLayer.Add(new AdornerPolygon(pln));
                }
            }
     
     
        }
    }
    Dans le cas du control la "sauce code" est plus epaisse sans etre indigested !!!

    1er probleme à resoudre : "customizer" un AdornerMapPolygon herite qui doit OVERRIDER (redefinir) les methods :

    1/ GetVisualChildren et VisualChildren (les childrens sont les Thumbs de notre AdornerMapPolygon => egal au nbre de sommets du MapPolgon)...

    2/ ArrangeOverride qui gere la disposition des Thumbs sur les sommets du MapPolygon.Les coords des sommets doivent etre dans WPF en unite de rendu c.à.d des PIXELSl !!!
    ArrangeOverride a besoin d'une reference sur le control Map principal pour faire la conversion de Location à Point (pixel) grace à Map.LocationToViewportPoint...

    3/ EventHandler DragDelta des Thumbs a besoin d'une reference sur le control Map pour pour faire la conversion Aller-Retour (Map.LocationToViewportPoint & Map.ViewportPointToLocation)
    Vu les exigencies en 2/ et 3/ et que l'unique Ctor du AdornerMapPolygon est impose (il ne peut recevoir qu'un parametre aka l'adornedElement ou notre MapPolygon),le seul moyen de fournir cette reference est de la "fourguer" dans le champ "Tag" du MapPolygon...

    2eme probleme à resoudre ;
    - creer l'AdornerMapPolygon par code (un adorner en effet n'a pas de Ctor public sans parametre <=> ne peut etre utiliser en xaml)....

    Pour cela le MapPolygon ou (tout autre control custom) doit toujour etre defini dans un Layer ou "couche" qui dans l'API Map est un MapLayer (control herite de Panel )...
    C'est dans l'event Load du MapLayer dans le DataTemplate que l'AdornerMapPolygon est initialise convenablement pour chaque MapPolygon ...et voila....!!!

    3eme probleme à resoudre est inherent à ta definition du class Location:il te faut un class CustLocation herite du class Location et qui implemente INotifyPropertyChanged pour le Binding car le class Location d'origine n'est pas pourvu de cette interface exigible e MVVM....

    Moyennant cela on peut afficher les noms des sommets ou Locations grace à un MapItemsControl(encore un autre !!!) "injecte directement " dans le DataTemplate Principal à la suite du MapPolygon et binde aux Locations....Note comment dans l'ItemTemplate la prop attachee Position du MapLayer est bindee grace à "la syntaxe Path=." pour positioner le TextBlock .....

    Bref voici le 2eme code pour BingMap (la zone geographique de l'exemple est l'algerie ):

    code .cs revu des Data :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Maps.MapControl.WPF;
    using System.ComponentModel;
    using System.Collections.ObjectModel;
    namespace WPFTestApplication
    {
     
        class CustLocation:Location,  INotifyPropertyChanged
        {
            private string cityName;
            public string CityName
           {
                get { return cityName; }
                set {
                    cityName = value; RaisePropertyChanged("CityName");
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            private void RaisePropertyChanged(string propName)
            {
                PropertyChangedEventHandler h = PropertyChanged;
                if (h != null)
                    h(this, new PropertyChangedEventArgs(propName));
            }
        }
     
        public class Area : INotifyPropertyChanged
        {
            public Area()
            {
                this.NameArea = string.Empty;
                this.Locations = new LocationCollection();
            }
            private string nameArea;
            public string NameArea
           {
                get { return nameArea; }
                set {
                    nameArea = value; RaisePropertyChanged("NameArea");
                }
            }
            private LocationCollection locations;
            public LocationCollection Locations
            {
                get { return locations; }
                set
                {
                    locations = value; RaisePropertyChanged("Locations");
                }
            }
     
     
            public event PropertyChangedEventHandler PropertyChanged;
            private void RaisePropertyChanged(string propName)
            {
                PropertyChangedEventHandler h = PropertyChanged;
                if (h != null)
                    h(this, new PropertyChangedEventArgs(propName));
            }
        }
     
        public class Areas :ObservableCollection<Area>
        {
            private Area a;
            public Areas()
            {
                LoadAreas();
     
            }
            private void LoadAreas()
            {
                a = new Area();
                a.NameArea = "Cne-Mila-Eulma";
                a.Locations = new LocationCollection(){
                new CustLocation() { CityName="City1", Latitude = 36.351716  , Longitude = 6.603069 },    
                new CustLocation() { CityName="City2",Latitude = 36.451020 , Longitude = 6.264303  },
                new CustLocation() { CityName="City3",Latitude = 36.151480, Longitude = 5.683351 }
                };
                this.Add(a);
     
                a = new Area();
                a.NameArea = "Setif-BBA-msila2";
                a.Locations = new LocationCollection(){
                new CustLocation() { CityName="City4", Latitude = 36.191113 , Longitude =5.414615 },
                new CustLocation() { CityName="City5", Latitude = 36.072180 ,  Longitude = 4.758790 },
                new CustLocation() { CityName="City6",Latitude = 35.703471 , Longitude = 4.547725 } 
                 };
                this.Add(a);
            }
        }
    }
    code .cs du AdornerMapPolygon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Documents;
    using System.Windows;
    using System.Windows.Controls.Primitives;
    using Microsoft.Maps.MapControl.WPF;
    using System.Collections;
    using System.Windows.Media;
     
    namespace WPFTestApplication
    {
        public class AdornerMapPolygon:Adorner
        {
            private Thumb theThumb;
            private MapPolygon  thePolygon;
            private VisualCollection children;
            private Map map;
            public AdornerMapPolygon(UIElement adornedElement)
                : base(adornedElement)
            {
                children = new VisualCollection(this);
     
                thePolygon = (MapPolygon)adornedElement;
                map =(Map)  thePolygon.Tag ;
     
                // event necessaire pour actualiser les coords geographiques 
                // quand la fenetre Viewport change(panning ou zooming)  
     
                map.ViewChangeOnFrame += new EventHandler<MapEventArgs>(map_ViewChangeOnFrame);
                for (int i = 0; i < thePolygon.Locations.Count; i++)
                {
                    theThumb = new Thumb();
                    theThumb.DragDelta += new DragDeltaEventHandler(theThumb_DragDelta);
                    theThumb.MouseEnter += new System.Windows.Input.MouseEventHandler(theThumb_MouseEnter);
                    theThumb.MouseLeave += new System.Windows.Input.MouseEventHandler(theThumb_MouseLeave);
                    BuildAdornerCorner(theThumb);
                }
            }
     
     
     
     
            #region handlers
            void theThumb_DragDelta(object sender, DragDeltaEventArgs args)
            {
                FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
     
                Thumb hitThumb = sender as Thumb;
     
     
                if (adornedElement == null || hitThumb == null) return;
     
                // Ensure that the Width and Height are properly initialized after the resize.
     
                EnforceSize(adornedElement);
     
                // Deplace le point du Polygon
                int i = children.IndexOf(hitThumb);
                Point p = map.LocationToViewportPoint(thePolygon.Locations[i]);
     
                p.X += args.HorizontalChange;
                p.Y += args.VerticalChange;
     
                thePolygon.Locations[i] = map.ViewportPointToLocation(p);
     
                //invocation de la passe arrange car les coords geo ont changes
                this.InvalidateVisual();
     
                // Maj du Size du Polygon 
                // utiliser ActualWidt & ActualHeight du polygon( bogus dans exemple MSDN
                adornedElement.Width = Math.Max(
                    adornedElement.ActualWidth + args.HorizontalChange,
                    hitThumb.ActualWidth);
     
                adornedElement.Height = Math.Max(
                    adornedElement.ActualHeight + args.VerticalChange,
                    hitThumb.ActualHeight);
     
     
            }
     
     
            void theThumb_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
            {
                foreach (Thumb item in children)
                {
                    item.Opacity = 1.0;
                }
            }
            void theThumb_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
            {
                foreach (Thumb item in children)
                {
                    item.Opacity = 0.0;
                }
            }
     
            void map_ViewChangeOnFrame(object sender, MapEventArgs e)
            {
                this.InvalidateVisual();
            }
     
     
            #endregion
     
            #region Overrides
     
            protected override Visual GetVisualChild(int index)
            {
                return children[index];
            }
            protected override int VisualChildrenCount
            {
                get
                {
                    return children.Count;
                }
            }
            protected override Size ArrangeOverride(Size finalSize)
            {
                // adornerWidth & adornerHeight are used for placement as well.
     
                Double adornerWidth   = this.DesiredSize.Width;
                Double adornerHeight  = this.DesiredSize.Height;
                UIElement child;
                for (int i = 0; i < children.Count;i++ )
                {
                    child = children[i] as UIElement ;
                    Point point = map.LocationToViewportPoint(thePolygon.Locations[i]);
     
                    child.Arrange(
                        new Rect(point.X - adornerWidth / 2, point.Y - adornerHeight / 2,
                            adornerWidth, adornerHeight));
                }
     
                //  Return the final size.
                return finalSize;
     
            }
     
            #endregion
     
     
            #region Private Methods
     
            private void BuildAdornerCorner(Thumb cornerThumb)
            {
                cornerThumb.Height = 20;
                cornerThumb.Width = 20;
                cornerThumb.Opacity = 0.0;
                cornerThumb.Background = new SolidColorBrush(Colors.MediumBlue  );
                children.Add(cornerThumb);
            }
     
     
     
            private void EnforceSize(FrameworkElement adornedElement)
            {
                if (adornedElement.Width.Equals(Double.NaN)) 
                      adornedElement.Width = adornedElement.DesiredSize.Width ;
     
                if (adornedElement.Height.Equals(Double.NaN)) 
                adornedElement.Height = adornedElement.DesiredSize.Height;
     
                FrameworkElement parent   = adornedElement.Parent as  FrameworkElement;
                if (parent != null)
                {
                        adornedElement.MaxHeight = parent.ActualHeight;
                        adornedElement.MaxWidth = parent.ActualWidth;
                }
     
     
            }
     
     
            #endregion  
        }
    }
    code xaml du UserControl ControlAdorner.xaml:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    <UserControl x:Class="WPFTestApplication.ControlAdorner"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:map="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
                 xmlns:local="clr-namespace:WPFTestApplication" 
     
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <UserControl.Resources>
            <local:Areas x:Key="myAreas" />
            <!--notre ancre-->
            <DataTemplate
                x:Key="PolygonTemplate"
                DataType="{x:Type local:Area}">
                <map:MapLayer 
                    x:Name="mapLayer"
                    Loaded="mapLayer_Loaded">
                    <map:MapPolygon 
                        x:Name="polygon"
                        Fill="Red" Stroke="DarkBlue" StrokeThickness="2.0"
                        Locations="{Binding Locations}"
                        >
                    </map:MapPolygon>
                    <map:MapItemsControl
                        ItemsSource="{Binding Locations}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate DataType="{x:Type map:Location}">
                                <TextBlock 
                                   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                                    FontSize="8"
                                    Background="Aquamarine"
                                    map:MapLayer.Position="{Binding Path=.}"
                                    Text="{Binding Path=CityName}"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
     
                    </map:MapItemsControl>
     
                </map:MapLayer>
     
            </DataTemplate>
        </UserControl.Resources>
        <Grid>
            <map:Map 
                x:Name="myMap"
                Center="36.351716,6.603069" ZoomLevel="8"
                CredentialsProvider="blabla"
                >
                <map:MapItemsControl    
                    ItemsSource="{Binding Source={StaticResource myAreas}}"
                    ItemTemplate="{StaticResource PolygonTemplate}">
                </map:MapItemsControl>
            </map:Map>
        </Grid>
    </UserControl>
    code behind .cs du UserControl ControlAdorner.xaml:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    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 Microsoft.Maps.MapControl.WPF;
     
    namespace WPFTestApplication
    {
        /// <summary>
        /// Logique d'interaction pour ControlAdorner.xaml
        /// </summary>
        public partial class ControlAdorner : UserControl
        {
            private AdornerLayer myAdornerLayer;
            public ControlAdorner()
            {
                InitializeComponent();
            }
     
            private void mapLayer_Loaded(object sender, RoutedEventArgs e)
            {
                MapLayer panel = sender as MapLayer;
                myAdornerLayer = AdornerLayer.GetAdornerLayer(panel);
                foreach (FrameworkElement  item in panel.Children)
                {
                    if (item.GetType()  != typeof(MapPolygon))continue  ;
     
                    // ON "PIQUE" LA REFERENCE AU MAPCONTROL 
                    item.Tag = this.myMap;
                    myAdornerLayer.Add(new AdornerMapPolygon(item));
                }
            }
        }
    }
    et simplistic code xaml du winform utilisateur(attention les adorners sont "surgissants" comme tu le veux et n'apparraissent qu'à l'execution au survol d'un sommet car ils ont la Prop Opacity=0.0 à l'etat normal...pour deplacer un sommet selectionner ,appuyer et deplacer la souris...Pour voir les adorners en mode Design dans le form,il faut mettre Opacity=1.0 dans BuilAdorner() )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <Window x:Class="WPFTestApplication.WinControlAdorner"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WPFTestApplication" 
            Title="WinControlAdorner" Height="300" Width="300">
        <Grid>
            <local:ControlAdorner></local:ControlAdorner>
        </Grid>
    </Window>
    & Run !!! pour voir les adorners à l'oeuvre !!!
    bon code.....

Discussions similaires

  1. [WD18] Metre une colonne d'une Table sur une ligne d'une autre Table
    Par Totophe2 dans le forum WinDev
    Réponses: 2
    Dernier message: 22/11/2013, 12h58
  2. Réponses: 1
    Dernier message: 07/03/2007, 11h05
  3. Réponses: 5
    Dernier message: 18/07/2006, 15h32
  4. Réponses: 29
    Dernier message: 03/11/2005, 10h37
  5. Afficher un bouton appartenant à une classe sur une form
    Par Julien_riquelme dans le forum Composants VCL
    Réponses: 2
    Dernier message: 05/09/2005, 13h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo