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

Dotnet Discussion :

[XAMARIN] View générée dynamiquement en Xaml ou MVVM


Sujet :

Dotnet

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2005
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 121
    Points : 65
    Points
    65
    Par défaut [XAMARIN] View générée dynamiquement en Xaml ou MVVM
    Bonjour,

    j'ai un projet Xamarin qui implémente le pattern MVVM.

    Je souhaite réaliser la chose suivante :

    je dispose d'une base d'articles (application à petite échelle, pas plus d'une 15 ou 20aine d'articles), articles que je veux vendre.
    Pour les vendre je souhaite afficher à l'écran, un bouton par article (le principe : quand je clique sur le bouton, ça incrémente le nombre de ventes de l'article correspondant, un peu à la manière des applis "cashier" ou type tpe).
    Je veux que l'affichage soit donc dynamique comme ceci par exemple :
    si j'ai 12 articles, je veux que ça dispose 3 lignes de 4 boutons (façon grid c'est donc 3 rows et 4 columns)
    si j'ai 15 articles je veux que ça fasse 3 lignes de 4 boutons et une ligne de 3 boutons.
    Je souhaite un maximum de 4 boutons par ligne.
    Avec ces éléments-là, est-il possible de faire en sorte que cette disposition de boutons soit générée dynamiquement, soit directement via le xaml (à l'aide du viewmodel et du binding), soit dans le viewmodel uniquement (si ce n'est pas faisable en xaml), mais en tous les cas sans code-behind dans le xaml.cs.
    Si c'est possible, quelle view utiliser pour ça ? Dans l'idéal, le bouton contiendrait uniquement le libellé de l'article (un bouton avec libellé "Café, un avec libellé "Sandwich", etc.) ou éventuellement en plus l'image (si j'arrive à dév la fonctionnalité de prise de photo XD).

    Merci de vos retours, bonne journée.

    Guillaume

  2. #2
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    794
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 794
    Points : 987
    Points
    987
    Par défaut
    Citation Envoyé par Thanor Voir le message
    Bonjour,

    j'ai un projet Xamarin qui implémente le pattern MVVM.

    Je souhaite réaliser la chose suivante :

    je dispose d'une base d'articles (application à petite échelle, pas plus d'une 15 ou 20aine d'articles), articles que je veux vendre.
    Pour les vendre je souhaite afficher à l'écran, un bouton par article (le principe : quand je clique sur le bouton, ça incrémente le nombre de ventes de l'article correspondant, un peu à la manière des applis "cashier" ou type tpe).
    Je veux que l'affichage soit donc dynamique comme ceci par exemple :
    si j'ai 12 articles, je veux que ça dispose 3 lignes de 4 boutons (façon grid c'est donc 3 rows et 4 columns)
    si j'ai 15 articles je veux que ça fasse 3 lignes de 4 boutons et une ligne de 3 boutons.
    Je souhaite un maximum de 4 boutons par ligne.
    Avec ces éléments-là, est-il possible de faire en sorte que cette disposition de boutons soit générée dynamiquement, soit directement via le xaml (à l'aide du viewmodel et du binding), soit dans le viewmodel uniquement (si ce n'est pas faisable en xaml), mais en tous les cas sans code-behind dans le xaml.cs.
    Si c'est possible, quelle view utiliser pour ça ? Dans l'idéal, le bouton contiendrait uniquement le libellé de l'article (un bouton avec libellé "Café, un avec libellé "Sandwich", etc.) ou éventuellement en plus l'image (si j'arrive à dév la fonctionnalité de prise de photo XD).

    Merci de vos retours, bonne journée.

    Guillaume
    Tu peux faire un inline grid layout :


    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
    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
      /// <summary>
        /// A layout that create lines / rows.
        /// </summary>
        /// <seealso cref="Xamarin.Forms.Layout{Xamarin.Forms.View}" />
        /// <autogeneratedoc />
        public class InlineWrapLayout : Layout<View>
        {
            private readonly Dictionary<Size, LayoutData> layoutDataCache = new Dictionary<Size, LayoutData>();
     
            public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create(
                "ColumnSpacing",
                typeof(double),
                typeof(InlineWrapLayout),
                5.0,
                propertyChanged: (bindable, oldvalue, newvalue) =>
                {
                    ((InlineWrapLayout)bindable).InvalidateLayout();
                });
     
            public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create(
                "RowSpacing",
                typeof(double),
                typeof(InlineWrapLayout),
                5.0,
                propertyChanged: (bindable, oldvalue, newvalue) =>
                {
                    ((InlineWrapLayout)bindable).InvalidateLayout();
                });
     
            /// <summary>
            /// Gets or sets the column spacing.
            /// </summary>
            /// <value>
            /// The column spacing.
            /// </value>
            /// <autogeneratedoc />
            public double ColumnSpacing
            {
                set { SetValue(ColumnSpacingProperty, value); }
                get { return (double)GetValue(ColumnSpacingProperty); }
            }
     
            /// <summary>
            /// Gets or sets the row spacing.
            /// </summary>
            /// <value>
            /// The row spacing.
            /// </value>
            /// <autogeneratedoc />
            public double RowSpacing
            {
                set { SetValue(RowSpacingProperty, value); }
                get { return (double)GetValue(RowSpacingProperty); }
            }
     
            protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
            {
                var layoutData = GetLayoutData(widthConstraint, heightConstraint);
                if (layoutData.VisibleChildCount == 0)
                {
                    return new SizeRequest();
                }
     
                return new SizeRequest(layoutData.Size);
            }
     
            /// <summary>
            /// Positions and sizes the children of a Layout.
            /// </summary>
            /// <param name="x">A value representing the x coordinate of the child region bounding box.</param>
            /// <param name="y">A value representing the y coordinate of the child region bounding box.</param>
            /// <param name="width">A value representing the width of the child region bounding box.</param>
            /// <param name="height">A value representing the height of the child region bounding box.</param>
            /// <remarks>
            /// Implementors wishing to change the default behavior of a Layout should override this method. It is suggested to still call the base method and modify its calculated results.
            /// </remarks>
            /// <autogeneratedoc />
            protected override void LayoutChildren(double x, double y, double width, double height)
            {
                var layoutData = GetLayoutData(width, height);
     
                if (layoutData.VisibleChildCount == 0)
                {
                    return;
                }
     
                double xChild = x;
                double yChild = y;
                int row = 0;
                int column = 0;
                foreach (var child in Children)
                {
                    if (!child.IsVisible)
                    {
                        continue;
                    }
     
                    LayoutChildIntoBoundingRegion(child, new Rectangle(new Point(xChild, yChild), layoutData.ChildrenSizesRows[row][column]));
     
                    if (column >= layoutData.ChildrenSizesRows[row].Count - 1)
                    {
                        xChild = x;
                        yChild += RowSpacing + layoutData.ChildrenSizesRows[row].Max(s => s.Height);
                        row++;
                        column = 0;
                    }
                    else
                    {
                        xChild += ColumnSpacing + layoutData.ChildrenSizesRows[row][column].Width;
                        column++;
                    }
                }
            }
     
            private LayoutData GetLayoutData(double width, double height)
            {
                var size = new Size(width, height);
     
                // Check if cached information is available.
                if (layoutDataCache.ContainsKey(size))
                {
                    return layoutDataCache[size];
                }
     
                int visibleChildCount = 0;
                var currentChildrenSizesRow = new List<Size>();
                var childrenSizesRows = new List<List<Size>> { currentChildrenSizesRow };
                // Enumerate through all the children.
                foreach (View child in Children)
                {
                    // Skip invisible children.
                    if (!child.IsVisible)
                        continue;
     
                    // Count the visible children.
                    visibleChildCount++;
     
                    // Get the child's requested size.
                    var childSizeRequest = child.Measure(Double.PositiveInfinity, Double.PositiveInfinity);
     
                    if (childSizeRequest.Minimum.Width > width)
                        throw new Exception($"L'element {child.GetType()} est trop large {childSizeRequest.Request.Width} vs {width} demandés");
     
                    // la vue ne tient pas -> passer à la suivante (on utilise la taille minimum)
                    if (currentChildrenSizesRow.Sum(s => s.Width + ColumnSpacing) + childSizeRequest.Request.Width > width && currentChildrenSizesRow.Count > 0)
                    {
                        currentChildrenSizesRow = new List<Size>();
                        childrenSizesRows.Add(currentChildrenSizesRow);
                    };
                    if (childSizeRequest.Request.Width <= width)
                        currentChildrenSizesRow.Add(childSizeRequest.Request);
                    else
                        currentChildrenSizesRow.Add(new Size(width, childSizeRequest.Request.Height));
                }
     
                double totalWidth = 0;
                double totalHeight = 0;
                if (visibleChildCount != 0)
                {
                    // Calculate the number of rows and columns.
                    if (Double.IsPositiveInfinity(width))
                    {
                        childrenSizesRows = new List<List<Size>>
                        {
                            new List<Size>(childrenSizesRows.SelectMany(r => r))
                        };
                    }
                    totalWidth = Math.Max(0, childrenSizesRows.Max(r => r.Sum(s => s.Width + ColumnSpacing) - ColumnSpacing));
                    totalHeight = Math.Max(0, childrenSizesRows.Sum(r => r.Count > 0 ? r.Max(s => s.Height) + RowSpacing : 0) - RowSpacing);
                }
     
                var totalSize = new Size(totalWidth, totalHeight);
     
                var layoutData = new LayoutData(visibleChildCount, childrenSizesRows, totalSize);
     
                layoutDataCache.Add(size, layoutData);
                return layoutData;
            }
     
            /// <summary>
            /// Invalidates the current layout.
            /// </summary>
            /// <remarks>
            /// Calling this method will invalidate the measure and triggers a new layout cycle.
            /// </remarks>
            /// <autogeneratedoc />
            protected override void InvalidateLayout()
            {
                base.InvalidateLayout();
     
                // Discard all layout information for children added or removed.
                layoutDataCache.Clear();
            }
     
            /// <summary>
            /// Invoked whenever a child of the layout has emitted <see cref="E:Xamarin.Forms.VisualElement.MeaureInvalidated" />. Implement this method to add class handling for this event.
            /// </summary>
            /// <autogeneratedoc />
            protected override void OnChildMeasureInvalidated()
            {
                base.OnChildMeasureInvalidated();
     
                // Discard all layout information for child size changed.
                layoutDataCache.Clear();
            }
     
            private struct LayoutData
            {
                public int VisibleChildCount { get; private set; }
                public Size Size { get; private set; }
                public List<List<Size>> ChildrenSizesRows { get; private set; }
                public LayoutData(int visibleChildCount, List<List<Size>> childrenSizesRows, Size size) : this()
                {
                    ChildrenSizesRows = childrenSizesRows;
                    VisibleChildCount = visibleChildCount;
                    Size = size;
                }
                public Size CellSize { get; private set; }
                public int Rows { get; private set; }
                public int Columns { get; private set; }
                public LayoutData(int visibleChildCount, Size cellSize, int rows, int columns) : this()
                {
                    VisibleChildCount = visibleChildCount;
                    CellSize = cellSize;
                    Rows = rows;
                    Columns = columns;
                }
            }
        }
    ça va mettre les éléments en ligne/colonne en fonction de leur nombre faudra p'tete ajuster un peu à ton cas

Discussions similaires

  1. [JS-PHP] Liste déroulante générée dynamiquement
    Par Sytchev3 dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 18/09/2007, 17h43
  2. Image clickable générées dynamiquement
    Par Azephel dans le forum ASP.NET
    Réponses: 8
    Dernier message: 26/04/2007, 17h13
  3. [AJAX] Code source d'une page générée dynamiquement
    Par Amnesiak dans le forum Langage
    Réponses: 3
    Dernier message: 20/02/2007, 18h06
  4. Réponses: 2
    Dernier message: 31/08/2006, 14h11
  5. Fixer une constante dans une fonction générée dynamiquement ?
    Par XecTech dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 07/08/2006, 20h59

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