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

Contribuez .NET Discussion :

Propriété attachée - FlowDocument WPF [Dvp.NET|A intégrer]


Sujet :

Contribuez .NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de yonpo
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2010
    Messages
    617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 617
    Par défaut Propriété attachée - FlowDocument WPF
    Salut,

    Je propose une nouvelle classe à ajouter (je l'espère ) au projet dvp.net :
    Elle permet, via une propriété attachée, de binder la propriété Blocks d'un FlowDocument à une collection (List<Block> par exemple).

    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
    /// <summary>
        /// Permet d'effectuer une liaison de données sur la propriété Blocks d'un FlowDocument
        /// </summary>
        public static class FlowDocumentBehavior
        {
            /// <summary>
            /// Obtient la valeur de la propriété attachée BindableBlocks pour l'objet spécifié
            /// </summary>
            /// <param name="obj">Objet dont on souhaite obtenir la valeur de la propriété</param>
            /// <returns></returns>
            public static IEnumerable<Block> GetBindableBlocks(DependencyObject obj)
            {
                return (IEnumerable<Block>)obj.GetValue(BindableBlocksProperty);
            }
     
            /// <summary>
            /// Définit la valeur de la propriété attachée BindableBlocks pour l'objet spécifié
            /// </summary>
            /// <param name="obj">Objet dont on souhaite définir la valeur de la propriété</param>
            /// <param name="value">Valeur de la propriété de dépendance spécifiée</param>
            public static void SetBindableBlocks(DependencyObject obj, IEnumerable<Block> value)
            {
                obj.SetValue(BindableBlocksProperty, value);
            }
     
            /// <summary>
            /// Propriété attachée BindableBlocks
            /// </summary>
            public static readonly DependencyProperty BindableBlocksProperty =
                DependencyProperty.RegisterAttached("BindableBlocks",
                typeof(IEnumerable<Block>), typeof(FlowDocumentBehavior), new UIPropertyMetadata(null, BindableBlocksChanged));
     
            private static void BindableBlocksChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
            {
                if (dependencyObject is FlowDocument)
                {
                    var obj = dependencyObject as FlowDocument;
                    obj.Blocks.Clear();
                    if (e.NewValue != null)
                    {
                        foreach (var block in (IEnumerable<Block>)e.NewValue)
                        {
                            obj.Blocks.Add(block);
                        }
                    }
                }
            }
        }

  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 : 43
    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
    Par défaut
    Bonne idée

    Juste une petite remarque : ce serait bien de gérer le cas où la collection bindée implémente INotifyCollectionChanged, de façon à ce que les éléments ajoutés ensuite à la collection soient ajoutés au FlowDocument

  3. #3
    Membre émérite Avatar de yonpo
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2010
    Messages
    617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 617
    Par défaut
    Voici la classe modifiée :

    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
    /// <summary>
        /// Permet d'effectuer une liaison de données sur la propriété Blocks d'un FlowDocument
        /// </summary>
        public static class FlowDocumentBehavior
        {
            private static FlowDocument _flowDocument;
     
            /// <summary>
            /// Obtient la valeur de la propriété attachée BindableBlocks pour l'objet spécifié
            /// </summary>
            /// <param name="obj">Objet dont on souhaite obtenir la valeur de la propriété</param>
            /// <returns></returns>
            public static IEnumerable<Block> GetBindableBlocks(DependencyObject obj)
            {
                return (IEnumerable<Block>)obj.GetValue(BindableBlocksProperty);
            }
     
            /// <summary>
            /// Définit la valeur de la propriété attachée BindableBlocks pour l'objet spécifié
            /// </summary>
            /// <param name="obj">Objet dont on souhaite définir la valeur de la propriété</param>
            /// <param name="value">Valeur de la propriété de dépendance spécifiée</param>
            public static void SetBindableBlocks(DependencyObject obj, IEnumerable<Block> value)
            {
                obj.SetValue(BindableBlocksProperty, value);
            }
     
            /// <summary>
            /// Propriété attachée BindableBlocks
            /// </summary>
            public static readonly DependencyProperty BindableBlocksProperty =
                DependencyProperty.RegisterAttached("BindableBlocks",
                typeof(IEnumerable<Block>), typeof(FlowDocumentBehavior), new UIPropertyMetadata(null, BindableBlocksChanged));
     
            private static void BindableBlocksChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
            {
                _flowDocument = dependencyObject as FlowDocument;
     
                if (_flowDocument == null) return;
     
                _flowDocument.Blocks.Clear();
                if (e.NewValue != null)
                {
                    var newValue = (IEnumerable<Block>)e.NewValue;
                    foreach (var block in newValue)
                    {
                        _flowDocument.Blocks.Add(block);
                    }
     
                    var observableList = newValue as INotifyCollectionChanged;
                    if (observableList != null) observableList.CollectionChanged += BlocksCollectionChanged;
                }
            }
     
            private static void BlocksCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.OldItems != null)
                {
                    foreach (Block item in e.OldItems)
                    {
                        _flowDocument.Blocks.Remove(item);
                    }
                }
     
                if (e.NewItems != null)
                {
                    foreach (Block item in e.NewItems)
                    {
                        _flowDocument.Blocks.Add(item);
                    }
                }
            }
        }

  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 : 43
    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
    Par défaut
    Bah non, tu peux pas faire comme ça... si tu stockes le FlowDocument dans un champ statique de la classe, ça fait que tu ne peux jamais utiliser plus d'un FlowDocument dans ton programme. Il faut trouver une autre solution...

    Une possibilité est de créer une classe spécifique pour gérer la "synchronisation" entre la collection et le FlowDocument, et de stocker un objet de cette classe dans une autre propriété attachée (privée et en lecture seule), pour l'associer au FlowDocument.

  5. #5
    Membre émérite Avatar de yonpo
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2010
    Messages
    617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 617
    Par défaut
    Ah oui... Bien vue !

    Je regarderai ça.

  6. #6
    Membre émérite Avatar de yonpo
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2010
    Messages
    617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 617
    Par défaut
    J'ai corrigé le code en m'aspirant de tes remarques :

    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
    /// <summary>
        /// Permet d'effectuer une liaison de données sur la propriété Blocks d'un FlowDocument
        /// </summary>
        public static class FlowDocumentBehavior
        {
            /// <summary>
            /// Obtient la valeur de la propriété attachée BindableBlocks pour l'objet spécifié
            /// </summary>
            /// <param name="obj">Objet dont on souhaite obtenir la valeur de la propriété</param>
            /// <returns></returns>
            public static IEnumerable<Block> GetBindableBlocks(DependencyObject obj)
            {
                return (IEnumerable<Block>)obj.GetValue(BindableBlocksProperty);
            }
     
            /// <summary>
            /// Définit la valeur de la propriété attachée BindableBlocks pour l'objet spécifié
            /// </summary>
            /// <param name="obj">Objet dont on souhaite définir la valeur de la propriété</param>
            /// <param name="value">Valeur de la propriété de dépendance spécifiée</param>
            public static void SetBindableBlocks(DependencyObject obj, IEnumerable<Block> value)
            {
                obj.SetValue(BindableBlocksProperty, value);
            }
     
            /// <summary>
            /// Propriété attachée BindableBlocks
            /// </summary>
            public static readonly DependencyProperty BindableBlocksProperty =
                DependencyProperty.RegisterAttached("BindableBlocks",
                typeof(IEnumerable<Block>), typeof(FlowDocumentBehavior), new UIPropertyMetadata(null, BindableBlocksChanged));
     
            private static void BindableBlocksChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
            {
                var flowDocument = dependencyObject as FlowDocument;
     
                if (flowDocument == null) return;
     
                if (e.NewValue != null)
                {
                    var sync = new FlowDocumentSync(flowDocument, (IEnumerable<Block>)e.NewValue);
                    SetFlowDocumentSync(flowDocument, sync);
                }
            }
     
            private static FlowDocumentSync GetFlowDocumentSync(DependencyObject obj)
            {
                return (FlowDocumentSync)obj.GetValue(_flowDocumentSyncPropertyKey.DependencyProperty);
            }
     
            private static void SetFlowDocumentSync(DependencyObject obj, FlowDocumentSync value)
            {
                obj.SetValue(_flowDocumentSyncPropertyKey, value);
            }
     
            private static readonly DependencyPropertyKey _flowDocumentSyncPropertyKey =
                DependencyProperty.RegisterAttachedReadOnly("flowDocumentSync",
                typeof(FlowDocumentSync), typeof(FlowDocumentBehavior), new UIPropertyMetadata(null));
        }
     
        internal class FlowDocumentSync
        {
            private FlowDocument _flowDocument;
            private IEnumerable<Block> _blocks;
     
            public FlowDocumentSync(FlowDocument flowDocument, IEnumerable<Block> blocks)
            {
                _flowDocument = flowDocument;
                _blocks = blocks;
     
                _flowDocument.Blocks.Clear();
     
                foreach (var block in _blocks)
                {
                    _flowDocument.Blocks.Add(block);
                }
     
                var observableList = _blocks as INotifyCollectionChanged;
                if (observableList != null) observableList.CollectionChanged += BlocksCollectionChanged;
            }
     
            private void BlocksCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.OldItems != null)
                {
                    foreach (Block item in e.OldItems)
                    {
                        _flowDocument.Blocks.Remove(item);
                    }
                }
     
                if (e.NewItems != null)
                {
                    foreach (Block item in e.NewItems)
                    {
                        _flowDocument.Blocks.Add(item);
                    }
                }
            }
        }

    J'ai testé avec deux collections bindés sur deux FlowDocument et ça fonctionne (ajout, suppression d'éléments).

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

Discussions similaires

  1. ResourceLoader propriétés attachées
    Par Fabiani dans le forum WinRT
    Réponses: 2
    Dernier message: 10/07/2014, 16h45
  2. Syntaxe binding d'une propriété attachée
    Par Deesmon dans le forum Windows Presentation Foundation
    Réponses: 1
    Dernier message: 09/01/2014, 01h16
  3. Créer dynamiquement une propriété attachable
    Par NejNej dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 16/11/2011, 16h41
  4. Fenêtre de propriété des controls WPF
    Par amandinerenard dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 25/03/2008, 14h52
  5. Réponses: 12
    Dernier message: 12/12/2004, 14h25

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