我在 Silverlight 中创建Path
,并在鼠标事件上添加元素。但是,虽然元素存在于内存中,但屏幕不会更新,直到其他内容导致屏幕重绘发生。
这是相关的代码 - 我正在响应鼠标事件,并且我保留了我正在编辑的路径的类成员。
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
事件不会触发。不过,这是一块垃圾。
有没有其他人以这种方式玩过路径?我想如果我同时在屏幕上放置其他图形元素这不会是一个问题,所以它可能不会影响人们,但是知道是否有更正确的方法可以做到这一点会很好
答案 0 :(得分:1)
我需要一些非常相似的东西,但是使用新的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的功能正如您所期望的那样。可能会帮助别人,我希望...
答案 1 :(得分:0)
您的布局根是什么类型的元素?我复制了你的代码,并使用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方法,该方法什么都不做。当我点击屏幕时,我得到新的线条画到我点击的位置。