Question

J'utilise Silverlight 5 avec MVVM.

J'ai un ViewModel qui est un Singleton . Le ViewModel expose une PointCollection que j'utilise pour dessiner un Polyline dans un de mes vues.

Si j'essaie de tirer la même Polyline dans une seconde vue, par liaison de données à la PointCollection à nouveau, je reçois une « valeur ne tombe pas dans la plage attendue » exception.

Pour autant que je pouvais trouver (avec ma connaissance Silverlight limitée), cela est causé par le fait que PointCollections ne sont pas partageables.

Y at-il une solution de contournement? Comment puis-je obtenir un deuxième polyligne qui est identique attiré au premier? Je veux DataBind deux polylignes à un PointCollection en même temps.

Edit: Je n'ai pas trouvé une solution, mais quelqu'un avec le même problème ici . Selon Microsoft:

Cette page MSDN mentionne que certains objets ne sont pas partageables et seront genereate une « valeur hors de portée » exception. http://msdn.microsoft.com/en-us/library/system.windows.resourcedictionary(VS.95).aspx

La page PointCollection mentionne également que ce n'est pas partageable. http://msdn.microsoft.com/en-us/library/system.windows.media.pointcollection(VS.95).aspx

À l'heure actuelle, c'est par le comportement de la conception. Cependant, nous évaluons ce pour voir si nous pouvons soit modifier le comportement ou tout au moins le texte d'exception.

Était-ce utile?

La solution

Jetez un oeil à cette question: Pourquoi pas ce travail de liaison de données

Et celui-ci aussi: temps 2 se liant à ne pas être PointCollection rendu

Comme vous avez donné des petits détails que je ne suis pas tout à fait sûr ce qui se passe, mais ces postes pourraient aider. Sinon, s'il vous plaît envoyer votre code.

Je l'ai fait quelques tests et la meilleure solution que je peux penser est ceci:

using System.ComponentModel;
using System.Windows;
using System.Windows.Media;

namespace SilverlightApplication6
{
    public class DemoVM : INotifyPropertyChanged
    {
        #region PointsClone Property
        private PointCollection _pointsClone;
        public PointCollection PointsClone
        {
            get
            {
                return _pointsClone;
            }
            set
            {
                if (_pointsClone != value)
                {
                    _pointsClone = value;
                    OnPropertyChanged("PointsClone");
                }
            }
        }
        #endregion

        #region Points Property
        private PointCollection _points;
        public PointCollection Points
        {
            get
            {
                return _points;
            }
            set
            {
                if (_points != value)
                {
                    _points = value;
                    PointsClone.Clear();
                    foreach (var point in _points)
                    {
                        PointsClone.Add(point);
                    }
                    OnPropertyChanged("Points");
                }
            }
        }
        #endregion

        public DemoVM()
        {
            PointsClone = new PointCollection();
            Points = new PointCollection();
        }

        public void AddPoint(Point point)
        {
            Points.Add(point);
            PointsClone.Add(point);
        }

        public void ClearPoints()
        {
            Points.Clear();
            PointsClone.Clear();
        }


        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            var p = PropertyChanged;
            if (p != null)
            {
                p(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

Bind un PolyLine.Points aux points et les autres PolyLine.Points à PointsClone.

Il est un peu laid, car il se brisera lorsque vous utilisez vm.Points.Add (point) au lieu de vm.AddPoint (point). En appliquant l'encapsulation appropriée, vous pourriez être en mesure de résoudre cela.

Autres conseils

J'ai trouvé une solution . Dupliquer le PointCollection dans le getter

    private PointCollection sourcePoints;
    public PointCollection SourcePoints
    {
        get
        {
            // create a new instance of PointCollection for binding
            PointCollection newPoints = new PointCollection();
            foreach (Point p in sourcePoints)
            {
                newPoints.Add(p);
            }
            return newPoints;
        }

Peut-être votre PointCollection est congèle et que ça fait la peine.

MSDN:

Freezable Caractéristiques: Parce qu'il hérite de la classe Freezable, la classe PointCollection offre plusieurs caractéristiques particulières: les objets PointCollection peuvent être déclarés comme des ressources, partagées entre plusieurs objets, en lecture seule pour améliorer les performances, cloné et fait thread-safe . Pour plus d'informations sur les différentes fonctionnalités fournies par des objets Freezable, consultez Freezable objets Vue d'ensemble.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top