Почему мой путь не отображается, когда я программно добавляю сегменты к пути в Silverlight 2?

Я создаю Path в Silverlight и добавляю к нему элементы при событиях мыши. Но, хотя элементы находятся в памяти, экран не обновляется, пока что-то еще не вызовет перерисовку экрана.

Вот соответствующий код - я отвечаю на событие мыши, и я сохраняю член класса пути, который редактирую.

Path path = null;

private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Point thisPoint = e.GetPosition(LayoutRoot);
    if (path == null)
    {
        CreateNewPath(thisPoint);
        path.LayoutUpdated += new EventHandler(path_LayoutUpdated);
    }
    else
    {
        path.AddLineElement(thisPoint);
    }
}

private void CreateNewPath(Point startPoint)
{
    path = new Path();
    PathGeometry geometry = new PathGeometry();
    path.Data = geometry;
    PathFigureCollection figures = new PathFigureCollection();
    geometry.Figures = figures;
    PathFigure figure = new PathFigure();
    figures.Add(figure);
    figure.StartPoint = startPoint;
    figure.Segments = new PathSegmentCollection();
    path.Stroke = new SolidColorBrush(Colors.Red);
    path.StrokeThickness = 2;
    path.Stretch = Stretch.None;
    LayoutRoot.Children.Add(path);
}

AddLineElement - это метод расширения класса пути для упрощения:

public static class PathHelper
{
    public static void AddLineElement(this Path thePath, Point newPoint)
    {
        PathGeometry geometry = thePath.Data as PathGeometry;
        geometry.Figures[0].Segments.Add(new LineSegment { Point = newPoint });
    }
}

Это минимум, необходимый для воспроизведения проблемы. Если вы запустите этот код в полном приложении WPF, все будет работать должным образом. Щелчки мышью добавляют линейные элементы, которые появляются немедленно. Однако в Silverlight дело обстоит иначе. Кажется, что щелчки ничего не делают, хотя пошаговое выполнение кода показывает, что данные добавляются. Но если щелкнуть несколько раз, то измените размер браузера, например, появятся элементы пути. Если у вас есть кнопка на странице, и вы наведите указатель мыши на нее, появится путь.

Я пробовал все очевидные вещи, например, вызывать InvalidateMeasure и InvalidateArrange на Path (и в родительской сетке), но безрезультатно.

Единственный обходной путь, который у меня есть, - это изменить свойство на пути, а затем вернуть его обратно, что, кажется, достаточно, чтобы заставить механизм рендеринга рисовать новые элементы пути. Пользуюсь Opacity. Вы должны установить другое значение, иначе (я полагаю) событие PropertyChanged не сработает. Однако это лабиринт.

Кто-нибудь еще так играл с путями? Думаю, если бы я одновременно размещал на экране другие графические элементы, это не было бы проблемой, так что, вероятно, это не то, что повлияет на людей, но было бы хорошо знать, есть ли более правильный способ сделать это. .

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
2 153
2

Ответы 2

Какой элемент является корнем вашего макета? Я скопировал ваш код и использовал Canvas в качестве корня макета, и он отлично работает как в IE, так и в Firefox.

<UserControl x:Class = "SilverlightTesting.Page"
    xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
    Width = "400" Height = "300">
        <Canvas x:Name = "LayoutRoot" Background = "White" Width = "400" Height = "300" MouseLeftButtonDown = "LayoutRoot_MouseLeftButtonDown"/>
</UserControl>

Я скопировал весь ваш код и создал новый метод path_LayoutUpdated, который ничего не делает. Когда я нажимаю на экран, я рисую новые линии до точки, по которой я щелкнул.

Мой исходный контейнер - это сетка, но холст дает мне тот же эффект. Это очень странно.

Jim Lynn 30.10.2008 22:01

Мне нужно было что-то очень похожее, но использующее новый Silverlight VE Map Control. Ваш код, приведенный выше, работал нормально, без каких-либо изменений в других свойствах для «принудительной перерисовки». Код здесь для справки:

using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.VirtualEarth.MapControl;

namespace MapInfo
{
    public partial class Page : UserControl
    {
        /// <summary>
        /// Sample drawing a polyline on a Virtual Earth map
        /// </summary>
        public Page()
        {
            InitializeComponent();
            VEMap.MouseLeftButtonUp += new MouseButtonEventHandler(VEMap_MouseLeftButtonDown);
            VEMap.MouseLeave += new MouseEventHandler(VEMap_MouseLeave);
        }

        MapPolyline polyline = null;

        /// <summary>
        /// Ends drawing the current polyline
        /// </summary>
        void VEMap_MouseLeave(object sender, MouseEventArgs e)
        {
            polyline = null;
        }
        /// <summary>
        /// Start or add-to a polyline
        /// </summary>
        private void VEMap_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Map m = (Map)sender;

            Location l = m.ViewportPointToLocation(e.GetPosition(m));

            if (polyline == null)
            {
                CreateNewPolyline(l);
            }
            else
            {
                polyline.Locations.Add(l);
            }
        }
        /// <summary>
        /// Create a new MapPolyline
        /// </summary>
        /// <param name = "startPoint">starting Location</param>
        private void CreateNewPolyline(Location startPoint)
        {
            polyline = new MapPolyline();
            polyline.Stroke = new SolidColorBrush(Colors.Red);
            polyline.StrokeThickness = 2;
            var lc = new LocationCollection();
            lc.Add(startPoint);
            polyline.Locations = lc;
            VEMap.Children.Add(polyline);
        }
    }
}

Это не помогает вашему непосредственному сценарию, но показывает, что другие компоненты Silverlight работают так, как вы ожидаете. Надеюсь, может помочь кому-то еще ...

Интересно, хотя MapPolyline работает иначе, чем стандартный элемент Polyline. Внутренне, каждый раз, когда вы добавляете новое местоположение в коллекцию, он должен перестраивать PointCollection (преобразовывая все местоположения в масштабированные координаты элемента), чего, я полагаю, достаточно для принудительного обновления ломаной линии. Тем не менее, спасибо за обновление. Я должен попробовать это в Silverlight 3, чтобы увидеть, не изменится ли он.

Jim Lynn 12.05.2009 17:42

Другие вопросы по теме