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 :

Modifier un StreamGeometry.


Sujet :

Windows Presentation Foundation

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 537
    Points : 369
    Points
    369
    Par défaut Modifier un StreamGeometry.
    Bonjour.

    J'ai un Canvas qui possède une propriété Clip, qui visiblement représente un StreamGeometry.
    Je voudrais appliquer une opération sur chaque point de ce StreamGeometry.
    Mais je ne trouve pas le moyen.

    J'ai d'abord essayé par code, mais je ne trouve pas le moyen de lister les points comme avec un PathGeometry :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    foreach (System.Windows.Media.PathFigure face in imageData.Figures)
                {
                    foreach (LineSegment segment in face.Segments)
                    {
                        segment.Point = new Point(segment.Point.X - 331, segment.Point.Y - 750);
                    }
                }
    Même en utilisant un StreamGeometryContext je ne vois pas comment parcourir les points.

    J'ai donc essayé de modifier directement la valeur récupérée via un ToString() du Clip.
    Mais je ne vois pas comment repasser ce string au Clip une fois modifié.

    Donc voilà je bloque.

    Quelqu'un saurait il comment parcourir et modifier les points d'un StreamGeometry?

    ou

    Quelqu'un saurait il comment modifier directement en la valeur en string du nœud Clip de mon Canvas?

    Merci.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    un StreamGeometry n'est pas modifiable :

    Citation Envoyé par MSDN
    Defines a geometric shape, described using a StreamGeometryContext. This geometry is light-weight alternative to PathGeometry: it does not support data binding, animation, or modification.
    Il faut que tu utilises un autre type de Geometry

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 537
    Points : 369
    Points
    369
    Par défaut
    Aouch!
    Le problème c'est que le type de Geometry de départ ne dépend pas de moi.

    Et directement en modifiant le node xaml du canvas?
    Car je récupère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    string clipString = monCanvas.Clip.ToString();
    Puis j'effectue les changements sur clipString.
    Il faudrait que j'arrive à modifier la valeur de l'attribut clip en parsant mon canvas comme un Xaml.

    Ça devrait marcher ça non?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    C'est pas toi qui définis le Clip en XAML au départ ? Parce que Clip ça vaut null par défaut...

  5. #5
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut modifier ou remplacer un streamgeometry
    bonjour NejNej
    Comme l'as dit TomLev,modifier un streamgeometry qui n'est pas un element UIElement est plutot une gageure(c'est ce que appelle microsoft un element "freezable ou "fige").
    Mais remplacer le "geometry" clippee oui......
    Neamoins on peut iterer sur les figures et connaitre leurs points "approximatifs" grace à Geometry.GetFlattenedPathGeometry().
    Le PathGeometry restitue par GetFlattenedPathGeometry() comme son nom l'indique remplace -helas une ellipse "originale" par un ligne polygonale approximee car les composants de la collection Figures sont des Segments.......(voir facteur de tolerance de GetFlattenedPathGeometry).....
    L' iteration sur les figures permet de connaitre le type "segment" par le nom d'API.....
    L'exemple de code suivant permet d'iterer sur les segments constitutifs de chaque figure -reduite à approximation polygonale pour l'ellipse- et de remplacer la liste de figures par une nouvelle liste......
    Puis l'ajout d'une figure ellipse pour tester le changement de clipping....du canvas....

    code behind:

    Code c# : 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
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
     
    using System;
    using System.Collections.Generic;
    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.Shapes;
     
    namespace WpfStreamGeometryCSharp
    {
        /// <summary>
        /// Logique d'interaction pour Window3.xaml
        /// </summary>
        public partial class Window3 : Window
        {
            private Geometry myGeom;
            Path tempPath ;
            public Window3()
            {
                InitializeComponent();
            }
     
            private void btnDisplaySegements_Click(object sender, RoutedEventArgs e)
            {
     
                // clear textbox
                this.txtGeometry.Clear();
     
                //  recupere le geometry du clip
                myGeom = this.mainCanvas.Clip;
     
                // obtient le "flatten" PathGeometry du clip
                PathGeometry flattenGeometry = myGeom.GetFlattenedPathGeometry();
                // enumere simplement  figures composants "flatten" PathGeometry 
                foreach (System.Windows.Media.PathFigure fig in flattenGeometry.Figures)
                {
     
                    foreach (PathSegment seg in fig.Segments)
                    {
                        this.txtGeometry.Text = this.txtGeometry.Text + seg.ToString() + Environment.NewLine;
                        //il faut switcher sur les elements suivant le 
                        //nom API pour identification
                        switch (seg.ToString())
                        {
                            case "System.Windows.Media.LineSegment":
                                this.txtGeometry.Text = this.txtGeometry.Text + seg.ToString() + Environment.NewLine;
                                LineSegment segLine = (LineSegment)seg;
                                this.txtGeometry.Text = this.txtGeometry.Text +
                                   segLine.Point.X.ToString() + "," + segLine.Point.Y.ToString() + Environment.NewLine;
     
                                break;
                            case "System.Windows.Media.PolyBezierSegment":
                                break;
                            case "System.Windows.Media.PolyLineSegment":
                                this.txtGeometry.Text = this.txtGeometry.Text +
                                   seg.ToString() + " :" + Environment.NewLine;
     
                                PolyLineSegment segPoly = (PolyLineSegment)seg;
                                foreach (Point ptItem in segPoly.Points)
                                {
                                    this.txtGeometry.Text = this.txtGeometry.Text +
                                         ptItem.X.ToString() + "," + ptItem.Y.ToString() + Environment.NewLine;
                                }
     
                                break;
                            case "System.Windows.Media.ArcSegment":
                                break;
                            default:
                                this.txtGeometry.Text = "entite geometry inconnue...et autres PolyQuadraticBezierSegment,QuadraticBezierSegment  etc...";
                                break;
                        }
                    }
                }
            }
     
             private void btnModifyGeomClip_Click(object sender, RoutedEventArgs e)
             {
                 // clear textbox
                 this.txtGeometry.Clear();
                 //  recupere le geometry du clip
                 myGeom = this.mainCanvas.Clip;
     
                 //  erase le  geometry clip existant
                 this.mainCanvas.Clip = null;
     
                 // obtient le "flatten" PathGeometry du clip
                 PathGeometry flattenGeometry = myGeom.GetFlattenedPathGeometry();
     
                 // necessaire pir storer les figures de remplacement
                 // car enumerator collection ne permet pas de modifier 
                 // la collection
                 PathFigure newFigure;
                 PathFigureCollection  newListFigures =new  PathFigureCollection ();
     
     
                 // parcours  "flatten" PathGeometry et enumere les 
                 //ses composantes  : "PolyLineSegmentChose..." 
                 foreach (System.Windows.Media.PathFigure fig in flattenGeometry.Figures)
                 {
                     newFigure = new PathFigure();
                     foreach (PathSegment seg in fig.Segments)
                     {
                         //this.txtGeometry.Text = this.txtGeometry.Text + seg.ToString() + Environment.NewLine;
                         //il faut switcher sur les elements suivant le 
                         //nom API pour identification
                         switch (seg.ToString())
                         {
                             case "System.Windows.Media.LineSegment":
                                 this.txtGeometry.Text = this.txtGeometry.Text+
                                     seg.ToString() + " :" + Environment.NewLine; 
     
                                 LineSegment segLine = (LineSegment)seg;
                                 this.txtGeometry.Text = this.txtGeometry.Text +
                                    segLine.Point.X.ToString() + "," + segLine.Point.Y.ToString() + Environment.NewLine;
     
                                 //note le new 
                                 segLine = new LineSegment();
                                 Point pt = new Point(40, 40);
                                 segLine.Point = pt;
                                 segLine.IsStroked = true;
                                 newFigure.Segments.Add(segLine);
                                 newListFigures.Add(newFigure);
                                 break;
                             case "System.Windows.Media.PolyBezierSegment":
                                 this.txtGeometry.Text = this.txtGeometry.Text +
                                     seg.ToString() + " :" + Environment.NewLine;
     
                                 PolyBezierSegment segPolyBezier = (PolyBezierSegment)seg;
                                 foreach (Point ptItem in segPolyBezier.Points)
                                 {
                                     this.txtGeometry.Text = this.txtGeometry.Text + 
                                        ptItem.X.ToString() + "," + ptItem.Y.ToString() + Environment.NewLine;
                                 }
                                 //note le new 
                                 segPolyBezier =new PolyBezierSegment();
                                 segPolyBezier.Points.Add(new Point(40, 40));
                                 segPolyBezier.Points.Add(new Point(100, 40));
                                 segPolyBezier.Points.Add(new Point(150, 80));
                                 segPolyBezier.Points.Add(new Point(40, 80));
                                 segPolyBezier.Points.Add(new Point(40, 40));
                                 segPolyBezier.IsStroked = true;
                                 newFigure.Segments.Add(segPolyBezier);
                                 newListFigures.Add(newFigure);
     
                                 break;
                             case "System.Windows.Media.PolyLineSegment":
                                 this.txtGeometry.Text = this.txtGeometry.Text +
                                    seg.ToString() + " :" + Environment.NewLine; 
     
                                 PolyLineSegment segPoly = (PolyLineSegment)seg;
                                 foreach (Point ptItem in segPoly.Points)
                                 {
                                  this.txtGeometry.Text = this.txtGeometry.Text + 
                                       ptItem.X.ToString() + "," + ptItem.Y.ToString() + Environment.NewLine;
                                 }
                                 //note le new 
                                 segPoly =new PolyLineSegment();
                                 segPoly.Points.Add(new Point(40, 40));
                                 segPoly.Points.Add(new Point(100, 40));
                                 segPoly.Points.Add(new Point(150, 80));
                                 segPoly.Points.Add(new Point(40, 80));
                                 segPoly.Points.Add(new Point(40, 40));
                                 segPoly.IsStroked = true;
                                 newFigure.Segments.Add(segPoly);
                                 newListFigures.Add(newFigure);
                                 break;
                             case "System.Windows.Media.ArcSegment":
                                 this.txtGeometry.Text = this.txtGeometry.Text +
                                    seg.ToString() + " :" + Environment.NewLine; 
     
                                 ArcSegment segArc = (ArcSegment)seg;
                                 this.txtGeometry.Text = this.txtGeometry.Text +
                                     segArc.Point.X.ToString() + "," + segArc.Point.Y.ToString()
                                    + " Size :" + segArc.Size.Width.ToString() + "," + segArc.Size.Height.ToString() + Environment.NewLine;
                                 //note le new 
                                 segArc =new ArcSegment();
                                 segArc.Size = new Size(30, 30);
                                 segArc.Point = new Point(60, 60);
                                 segArc.IsLargeArc = true;
                                 segArc.IsStroked = true;
                                 newFigure.Segments.Add(segArc);
                                 newListFigures.Add(newFigure);
                                 break;
                             default:
                                 this.txtGeometry.Text = "entite geometry inconnue...et autres PolyQuadraticBezierSegment,QuadraticBezierSegment  etc...";
                                 break;
                         }
                     }
     
     
                 }
                 // Clear old figures
                 flattenGeometry.Figures.Clear();
                 // ajoute nouvelle collection figures à  flattenGeometry
                 flattenGeometry.Figures = newListFigures;
                 //cree un nouveau path à partir du flattenGeometry
                 //modifie  Fill ,Brush et Stroke du  nouveau path
                 tempPath = new Path();
                 flattenGeometry.FillRule = FillRule.EvenOdd;
                 tempPath.Data = flattenGeometry;
     
                 tempPath.Fill = Brushes.Yellow;
                 tempPath.Stroke = Brushes.Black;
                 tempPath.StrokeThickness = 2.0;
                 //Canvas.SetLeft(tempPath, 0);
                 //Canvas.SetTop(tempPath, 0);
                 //this.mainCanvas.Children.Add(tempPath);
                 this.mainCanvas.Clip = tempPath.Data;
             }
     
             //ajoute un shape Ellipse pour voir l'effet de la modification du clip
             private void btnAddFigure_Click(object sender, RoutedEventArgs e)
             {
                 Ellipse myCircle = new Ellipse();
                 myCircle.Fill = Brushes.HotPink;
                 myCircle.Stroke = Brushes.Black;
                 myCircle.StrokeThickness = 4.0;
                 myCircle.Width = 100;
                 myCircle.Height = 100;
     
                 Canvas.SetLeft(myCircle, 50);
                 Canvas.SetTop(myCircle, 50);
                 this.mainCanvas.Children.Add(myCircle);
             }
     
     
     
     
        }
    }
    code xaml
    Code xaml : 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
     
    <Window x:Class="WpfStreamGeometryCSharp.Window3"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window3" Height="300" Width="300">
        <Window.Resources>
            <!--  le composite shape Path utilise dans le geometry clip canvas pour information uniquement . -->
            <Path x:Key="compositeGeometry"  
                  Stroke="Blue" 
                  StrokeThickness="2"
                  Fill="Yellow">
                <Path.Data>
                    <!-- Creates a composite shape from three geometries. -->
                    <GeometryGroup FillRule="EvenOdd">
                        <LineGeometry 
                            StartPoint="40,70" EndPoint="70,60" />
                        <EllipseGeometry 
                            Center="40,70" 
                            RadiusX="30" 
                            RadiusY="30" />
                        <RectangleGeometry 
                            Rect="30,55 100 30" />
                    </GeometryGroup> 
                </Path.Data>
            </Path>
        </Window.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" MinHeight="200"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <ScrollViewer
                Grid.Row="0"
                Grid.Column="2"
                HorizontalScrollBarVisibility="Visible"
                VerticalScrollBarVisibility="Visible">
                <TextBox
                    Name="txtGeometry" 
                    Text="" >
                </TextBox>
            </ScrollViewer>
            <Canvas 
                Grid.Row="0"
                Grid.ColumnSpan="2"
                Name="mainCanvas"
                Background="Red">
                <Canvas.Clip>
                    <!-- clip geometry du Canvas cree en xaml -->
                    <!-- Creates a composite shape from three geometries. -->
                    <GeometryGroup FillRule="EvenOdd">
                        <LineGeometry 
                            StartPoint="40,70" EndPoint="70,60" />
                       <!--mets en commentaire  EllipseGeometry  pour voir la difference de restitution des coord. des points 
                        du LineGeometry  et du RectangleGeometry 
                        La restitution  de l'ellipse est une approximation 
                        en ligne polygonale--> 
                        <EllipseGeometry 
                            Center="40,70" 
                            RadiusX="30" 
                            RadiusY="30" />
                        <RectangleGeometry 
                            Rect="30,55 100 30" />
                    </GeometryGroup>
                </Canvas.Clip>
            </Canvas>
            <!--liste les segements du Geometry du Clip canvas existant-->
            <Button 
                Grid.Row="1"
                Grid.Column="0"
                Name="btnDisplaySegements" 
                Content="DisplaySegements"
                Click="btnDisplaySegements_Click">
            </Button>
            <!--modifie le Geometry du Clip canvas existant-->
            <!--en le remplacant par de nouveaux Segments-->
            <Button 
                Grid.Row="1"
                Grid.Column="1"
                Name="btnModifyGeomClip" 
                Content="ModifyGeomClip"
                Click="btnModifyGeomClip_Click">
            </Button>
            <Button 
                Grid.Row="1"
                Grid.Column="2"
                Name="btnAddFigure" 
                Content="AddFigure"
                Click="btnAddFigure_Click">
     
            </Button>
        </Grid>
    </Window>
    Bon code et bonne soiree.............

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 537
    Points : 369
    Points
    369
    Par défaut
    Citation Envoyé par tomlev Voir le message
    C'est pas toi qui définis le Clip en XAML au départ ? Parce que Clip ça vaut null par défaut...
    Non.
    Je charge un fichier Xps.


    Merci Mabrouki.
    Je suis obligé de mettre ça de côté pour le moment mais je me pencherais sur ta solution dés que j'aurais le temps.

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par NejNej Voir le message
    Je charge un fichier Xps.
    Ah ouais, ça facilite pas vraiment les choses...

    Bah à la limite, vu que le "mini-langage" pour décrire un StreamGeometry est très simple, tu peux envisager de le parser toi-même

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 537
    Points : 369
    Points
    369
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Ah ouais, ça facilite pas vraiment les choses...

    Bah à la limite, vu que le "mini-langage" pour décrire un StreamGeometry est très simple, tu peux envisager de le parser toi-même
    Je le fais :
    Citation Envoyé par NejNej Voir le message
    Et directement en modifiant le node xaml du canvas?
    Car je récupère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    string clipString = monCanvas.Clip.ToString();
    Puis j'effectue les changements sur clipString.

    Le truc c'est qu'une fois que j'ai mon string parcouru et modifié je ne sais pas comment préciser à mon clip d'utiliser ce string.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par NejNej Voir le message
    Je le fais :



    Le truc c'est qu'une fois que j'ai mon string parcouru et modifié je ne sais pas comment préciser à mon clip d'utiliser ce string.
    Ah bah c'est bon alors !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monCanvas.Clip = Geometry.Parse(taNouvelleString);
    (Geometry.Parse crée un StreamGeometry)

  10. #10
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut GeometryConverter un meconnu Api WPF
    Rebonjour NejNej
    En complement au code base sur l'iteration sur les figures qui est en fait inapproprie dans notre cas (utile surtout pour la creation de figures).
    Vu ton souci je reposte cette fois ci avec un outil bien plus efficace crois moi.

    Geometry.Parse est bon mais l'inconnu et peu documente GeometryConverter est bien plus Redoutable .
    Un vrai "Razoir d'Occam" pour le graphisme avec des objets Geometry.
    Il prend un geometry et illico presto restitue une chaine en mini-language xaml.
    En sens inverse donnez lui une chaine en mini-language il vous restitue un geometry.

    Dans le cas du Clip canvas voici comment operer "interactivement":

    1/ le Clip.GetFlattenedPathGeometry est converti en chaine mini dans un Textbox.
    2/La chaine restitue peut etre "bindee"(liee) à la propriete d'un Path.Data moyennant un simple textbox grace à un converter (merci UniversalValueConverter egalement).

    3/Modifier interactivement la chaine affiche et le path est modifie illico presto grace au binding dans un 2eme canvas d'apercu.

    4/la chaine mini est applique au canvas original.

    Bref voici d'abord le code behind du classe UniversalValueConverter à adjoindre au projet Winform :
    Code c# : 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
     
    //Wouldn’t it be great to have a single value converter that has the same flexibility as the XAML parser
     
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ComponentModel;
    using System.Windows.Data;
    using System.Globalization;
    namespace WpfStreamGeometryCSharp
    {
        public class UniversalValueConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                // obtain the conveter for the target type
                TypeConverter converter = TypeDescriptor.GetConverter(targetType);
     
                try
                {
                    // determine if the supplied value is of a suitable type
                    if (converter.CanConvertFrom(value.GetType()))
                    {
                        // return the converted value
                        return converter.ConvertFrom(value);
                    }
                    else
                    {
                        // try to convert from the string representation
                        return converter.ConvertFrom(value.ToString());
                    }
                }
                catch (Exception)
                {
                    return value;
                }
     
            }
     
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    }
    Code xml : 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
     
    // Exemple d'utilisation de ce converter
    //
    //You can see this converter in action below where a range of type conversions are demonstrated:
     
    //<TextBlock Text="Converting String to Brush ...."/>
    //<Rectangle Fill="{Binding ElementName=colorTextBox, Path=Text, Converter={StaticResource UniversalValueConverter}}"/>
    //<TextBox x:Name="colorTextBox"
    //             Text="Red"/>
     
    //<TextBlock Text="Converting String to Geometry ...."/>
    //<Path Data="{Binding ElementName=geometryText, Path=Text, Converter={StaticResource UniversalValueConverter}}"/>
    //<TextBox x:Name="geometryText"                  
    //             Text="M 10,20 C 10,2.5 40,35 40,17 H 28"/>
     
    //<TextBlock Text="Converting String to DoubleCollection (stroke dash) ...."/>
    //<Line StrokeDashArray="{Binding ElementName=dashText, Path=Text, Converter={StaticResource UniversalValueConverter}}"/>
    //<TextBox x:Name="dashText"                  
    //            Text="2 2 4 5"/>

    code behind du winform (peu de code 2 boutons,les 2 derniers boutons ne sont pas absolument necessaires - juste pour une eventuelle sauvergarde dans un file xam en format mini) :
    Code c# : 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
     
    //merci à GeometryConverter et UniversalValueConverter
    //qui nous evite d'ecrire des converters Color,Double,Integer etc...
    //à tout bout de champ..............
    using System;
    using System.Collections.Generic;
    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.Shapes;
     
    //needed pour Directory.GetCurrentDirectory
    using System.IO;
     
    //needed pour XmlTextWriter
    using System.Xml;
     
    //needed pour xamlwriter
    using System.Windows.Markup;
     
    //needed pour UTF8Encoding
    using System.Text;
    namespace WpfStreamGeometryCSharp
    {
        /// <summary>
        /// Logique d'interaction pour WinDisplayClipMini.xaml
        /// </summary>
        public partial class WinDisplayClipMini : Window
        {
            private GeometryConverter  geomConverter  = new GeometryConverter();
            private String stringMini= String.Empty;
            public WinDisplayClipMini()
            {
                InitializeComponent();
            }
            // convertit en mini le geometry du clip et 
            // affiche dans  textbox pour modif.
            // Apercu instantane dans CanvasApercu dans un Path de travail 
            // bindee au textbox .Merci à UniversalValueConverter
            //
            private void geomConvertToMini_Click(object sender, RoutedEventArgs e)
            {
                // fois width sinon tronque
                this.PathFromMiniApercu.Width = 2 * this.CanvasOriginal.Clip.Bounds.Width;
    		    this.PathFromMiniApercu.Height = 2 * this.CanvasOriginal.Clip.Bounds.Height;
     
                // NB: utilise ConvertToInvariantString pour avoir le point decimal english exigee dans mini
                stringMini = geomConverter.ConvertToInvariantString(this.CanvasOriginal.Clip.GetFlattenedPathGeometry());
    		    this.txtDisplayMiniPath.Text = stringMini;
            }
            // Permet d'appliquer le geometry modifie à  canvasOriginal
            // nb:il faut  que tu prevois d'enjoliver le Path interactivement.
     
            private void applyMiniToCanvasOriginal_Click(object sender, RoutedEventArgs e)
            {
                this.CanvasOriginal.Clip = (Geometry)geomConverter.ConvertFromInvariantString(this.txtDisplayMiniPath.Text);
     
            }
            //
            // 2 boutons ne sont absolument necessaires 
            // juste pour illustrer sauvegarde dans un file 
            // un geometry en xaml avec la syntaxe mini language
            // Enregistre le Geometry Clip Canvas en format Xaml mini-language
            //
            String strPath = System.IO.Directory.GetCurrentDirectory() + @"\MyTest.xml";
            private void saveClipToFile_Click(object sender, RoutedEventArgs e)
            {
                XmlTextWriter writer   = new XmlTextWriter(strPath, new UTF8Encoding());
    		    writer.Formatting = Formatting.Indented;
    		    writer.Indentation = 1;
                writer.IndentChar = '\t'; 
                XamlWriter.Save(this.CanvasOriginal.Clip, writer);
    		    writer.Close();
            }
            //
            // Charge  Geometry Clip Canvas sauve dans CanvaApercu
            // moyennant un path 
            //
            private void loadClipFromFile_Click(object sender, RoutedEventArgs e)
            {
     
            // Enjoliver dans un path 
            // car  streamgeometry n'est pas un visual
            // get the object geometry
            Geometry objGeom = ImportXaml(strPath); 
     
            // use path to display it
     
            System.Windows.Shapes.Path yourPath = new System.Windows.Shapes.Path();
    		yourPath.Fill = Brushes.Pink;
    		yourPath.Stroke = Brushes.SeaGreen;
    		yourPath.StrokeThickness = 2.0;
    		yourPath.Data = objGeom;
    		this.CanvasApercu.Children.Add(yourPath);
     
            // subtilite ou piege: en sortie  seule la prop clip est sauve 
            // pas le contenu clippe du canvas.
            }
            private Geometry ImportXaml(string pathFile)
            { 
                if(pathFile == String.Empty) 
                {
                    return null;
                } 
                //Lit le file comme un stream binaire .
    		    System.IO.StreamReader myStreamReader= new System.IO.StreamReader(pathFile, true);
     
                //Recupere le contenu comme un stringReader.
                System.IO.StringReader stringClipCanvas = new System.IO.StringReader(myStreamReader.ReadToEnd());
     
    		    //Lit le fichier xml
    		    XmlReader xmlReader   = XmlReader.Create(stringClipCanvas);
     
                //Convertit le xml en objet Geometry
    		    Geometry  readerGeom  = (Geometry)XamlReader.Load(xmlReader);
    		    myStreamReader.Close();
    		    return readerGeom;
     
            }
        }
    }

    code xaml du winform:
    Code xaml : 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
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
     
    <Window x:Class="WpfStreamGeometryCSharp.WinDisplayClipMini"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfStreamGeometryCSharp"
        Title="Display and Modify Clip as Mini Xaml" Height="300" Width="300" >
        <Window.Resources>
            <!--classe qui permet de binder le markup mini 
            au path d'apercu--> 
            <local:UniversalValueConverter 
                    x:Key="UniversalConverter">
            </local:UniversalValueConverter>
        </Window.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="64"></RowDefinition>
                <RowDefinition Height="*" MinHeight="400"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <!-- TextBox  donne 2 apercus  du geometry mini language recupere  :-->
            <!-- forme "texte"-->
            <!-- forme "graphique" en bindant(eh oui un string) à  -->
            <!-- la prop Data du path "PathFromMiniApercu" du "canvasApercu"-->
     
            <ScrollViewer
                Grid.Row="0"
                Grid.ColumnSpan="4"
                HorizontalScrollBarVisibility="Auto"
                VerticalScrollBarVisibility="Auto">
                <TextBlock 
                    x:Name="txtDisplayMiniPath"
                    FontSize="14"
                    TextAlignment="Justify"
                    FontFamily="Arial"
                    FontWeight="Bold">
                </TextBlock>
            </ScrollViewer>
            <!--CanvasOriginal est le canvas--> 
            <!--dont on recupere le Geometry Clip-->
            <Border 
                Grid.Row="1"
                Grid.ColumnSpan="2"
                BorderBrush="DarkGreen"
                BorderThickness="2">
                <ScrollViewer 
                    HorizontalScrollBarVisibility="Auto"
                    VerticalScrollBarVisibility="Auto">
                    <Canvas 
                        x:Name="CanvasOriginal"
                        Background="Blue"
                        ClipToBounds="True"
                        Height="500"
                        Width="500"
                        ScrollViewer.HorizontalScrollBarVisibility="Visible"
                        ScrollViewer.VerticalScrollBarVisibility="Visible">
                        <Canvas.Clip>
                            <CombinedGeometry  GeometryCombineMode="Xor">
                                <CombinedGeometry.Geometry1>
                                    <EllipseGeometry 
                                            Center="300,200" 
                                            RadiusX="150" 
                                            RadiusY="100"/>
                                </CombinedGeometry.Geometry1>
                                <CombinedGeometry.Geometry2>
                                    <PathGeometry >
                                        <PathFigure StartPoint="150,200">
                                            <PolyLineSegment  
                                                    IsStroked="True"  
                                                    Points ="450,200 300,100" 
                                                    IsSmoothJoin="True" >
                                            </PolyLineSegment>
                                        </PathFigure>
                                    </PathGeometry>
                                </CombinedGeometry.Geometry2>
                            </CombinedGeometry>
                        </Canvas.Clip>
                        <Path 
                            x:Name="segmentsPathRectangle"
                            StrokeThickness="4" 
                            Stroke="Yellow"
                            Fill="red">
                            <Path.Data>
                                <CombinedGeometry GeometryCombineMode="Exclude">
                                    <CombinedGeometry.Geometry1>
                                        <RectangleGeometry 
                                            RadiusX="5"
                                            RadiusY="5"
                                            Rect="150,150, 200,100"/>
                                    </CombinedGeometry.Geometry1>
                                    <CombinedGeometry.Geometry2>
                                        <PathGeometry >
                                            <PathFigure StartPoint="150,150">
                                                <PolyLineSegment  
                                                    IsStroked="True"  
                                                    Points ="250,200 450,100" 
                                                    IsSmoothJoin="True" >
                                                </PolyLineSegment>
                                            </PathFigure>
                                        </PathGeometry>
                                    </CombinedGeometry.Geometry2>
                                </CombinedGeometry>
                            </Path.Data>
                        </Path>
                        <TextBox 
                            Canvas.Left="0"
                            Canvas.Top="0"
                            FontSize="14"
                            Text="Canvas Original">
                        </TextBox>
                    </Canvas>
                </ScrollViewer>
            </Border>
            <!--CanvasApercu donne un apercu sous forme path -->
            <!--du geometry recupere depuis le  Clip-->
            <Border 
                Grid.Row="1"
                Grid.Column="2"
                Grid.ColumnSpan="2"
                BorderBrush="CornflowerBlue"
                BorderThickness="2">
                <ScrollViewer 
                    HorizontalScrollBarVisibility="Auto"
                    VerticalScrollBarVisibility="Auto">
                    <Canvas 
                        x:Name="CanvasApercu"
                        Background="WhiteSmoke"
                        ClipToBounds="True" 
                        Height="500"
                        Width="500"
                        ScrollViewer.HorizontalScrollBarVisibility="Auto"
                        ScrollViewer.VerticalScrollBarVisibility="Auto">
                        <TextBox 
                            Canvas.Left="0"
                            Canvas.Top="0"
                            FontSize="14"
                            Text="Canvas Apercu">
                        </TextBox>
                        <Path 
                            x:Name="PathFromMiniApercu"
                            Fill="YellowGreen"
                            Stroke="Red"
                            StrokeThickness="2"
                            Data="{Binding ElementName=txtDisplayMiniPath,Path=Text, Converter={StaticResource UniversalConverter},StringFormat='{}{0:N2}'}"/>
                    </Canvas>
                </ScrollViewer>
            </Border>
     
            <!--ici ce que tu cherches:-->
            <!--le "Razoir d'Occam" i.e Classe GeometryConverter(en culture invariant ou neutre pour  point decimal english)-->
            <!--convertit le GeometryStream du Clip Canvas en donnees au format mini-language xaml-->
            <!--et l'affiche pour modif. eventuelle(voir txtDisplayMiniPath-->
            <Button
                Grid.Row="2"
                Grid.Column="0"
                x:Name="geomConvertToMini"
                FontSize="12"
                Background="Red"
                Foreground="White"
                Content="ConvertToMini"
                Click="geomConvertToMini_Click">
            </Button>
             <!--applique au clip le geometry string mini modifie-->
            <Button
                Grid.Row="2"
                Grid.Column="1"
                x:Name="applyMiniToCanvasOriginal"
                FontSize="12"
                Background="Red"
                Foreground="White"
                Content="applyToCanvasOriginal"
                Click="applyMiniToCanvasOriginal_Click">
            </Button>
     
            <!-- Enregistre le Geometry Clip Canvas en format Xaml mini-language-->
            <!-- pour info.seulement -->
            <Button
                Grid.Row="2"
                Grid.Column="2"
                x:Name="saveClipToFile"
                FontSize="12"
                Background="WhiteSmoke"
                Content="saveClipToFile"
                Click="saveClipToFile_Click">
            </Button>
            <!-- Charge  Geometry Clip Canvas sauve dans CanvaApercu-->
            <!-- pour info.seulement -->
            <Button  
                Grid.Row="2"
                Grid.Column="3"
                x:Name="loadClipFromFile"
                FontSize="12"
                Background="WhiteSmoke"
                Content="loadClipFromFile"
                Click="loadClipFromFile_Click">
            </Button>
        </Grid>
    </Window>

    NB: la doc MSDN est etrangement avare sur cet objet.
    En esperant qu'il reponde à ta problematique........

    Bon code.....................

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 27/11/2002, 14h08
  2. [VB6] Zone de liste modifiable basée sur un champ
    Par pepper dans le forum VB 6 et antérieur
    Réponses: 13
    Dernier message: 27/11/2002, 13h41
  3. [VB6] Modifier la clé d'un élément d'une collection
    Par Ricou13 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 21/11/2002, 14h49
  4. [VB6] [MDI] Modifier form en MDIform
    Par fikou dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 12/09/2002, 13h48
  5. Réponses: 5
    Dernier message: 06/08/2002, 20h08

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