WPF渲染事件不绘制任何东西
我试图将一些WinForm代码转换为WPF管道网络绘图应用程序。我一直立足而过这种涂料的应用文章:WPF渲染事件不绘制任何东西
http://www.codeproject.com/Articles/22776/WPF-DrawTools
这是我在WinForms和我试图把它转换了,因为我们需要更加个性化的窗口。我需要做到以下几点:
a)单击画布绘制节点 b)单击并拖动上述节点 C)将鼠标悬停在和突出节点 d)与链路连接节点
我有以下代码在画布上绘制矩形,但在渲染渲染时画布上不会显示任何内容。我相对确定它被解雇了,因为在其中放置一个消息框会导致程序崩溃。
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Colors.LimeGreen;
Pen myPen = new Pen(Brushes.Blue, 10);
Rect myRect = new Rect(50, 50, 500, 500);
drawingContext.DrawRectangle(mySolidColorBrush, myPen, myRect);
}
private void myCanvas_MouseDown(object sender, MouseButtonEventArgs e)
{
System.Windows.Forms.MessageBox.Show("click event fired");
DrawingVisual vs = new DrawingVisual();
DrawingContext dc = vs.RenderOpen();
OnRender(dc);
}
“被激活”消息框就在那里,以确保点击事件触发,并且确实如此。 XML:
<TabItem Header="View Results">
<Canvas Background="WhiteSmoke" Name="myCanvas" MouseDown="myCanvas_MouseDown" >
</Canvas>
</TabItem>
什么给了?文章中的家伙使用用户控件...这就是为什么我有问题吗? WPF让我感到疯狂......我觉得我正在做一些完全错误的事情,但是我可以在这个主题上找到很少的文档。
看,这是一个简单的例子,我在20分钟内做出:
XAML:
<Window x:Class="NodesEditor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:NodesEditor"
Title="Window1" Height="800" Width="800" x:Name="view">
<Grid Margin="10">
<Grid.Resources>
<!-- This CompositeCollection basically Concatenates the Nodes and Connectors in a single one -->
<CompositeCollection x:Key="Col">
<CollectionContainer Collection="{Binding DataContext.Connectors,Source={x:Reference view}}"/>
<CollectionContainer Collection="{Binding DataContext.Nodes,Source={x:Reference view}}"/>
</CompositeCollection>
<!-- This is the DataTemplate that will be used to render the Node class -->
<DataTemplate DataType="{x:Type local:Node}">
<Thumb DragDelta="Thumb_Drag">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Ellipse Height="10" Width="10" Stroke="Black" StrokeThickness="1" Fill="Blue"
Margin="-5,-5,5,5" x:Name="Ellipse"/>
<ControlTemplate.Triggers>
<Trigger Property="IsDragging" Value="True">
<Setter TargetName="Ellipse" Property="Fill" Value="Yellow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</DataTemplate>
<!-- This is the DataTemplate that will be used to render the Connector class -->
<DataTemplate DataType="{x:Type local:Connector}">
<Line Stroke="Black" StrokeThickness="1"
X1="{Binding Start.X}" Y1="{Binding Start.Y}"
X2="{Binding End.X}" Y2="{Binding End.Y}"/>
</DataTemplate>
</Grid.Resources>
<!-- This Border serves as a background and the VisualBrush used to paint its background serves as the "Snapping Grid" -->
<!-- The "Snapping" Actually occurs in the Node class (see Node.X and Node.Y properties), it has nothing to do with any UI Elements -->
<Border>
<Border.Background>
<VisualBrush TileMode="Tile"
Viewport="0,0,50,50" ViewportUnits="Absolute"
Viewbox="0,0,50,50" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Rectangle Stroke="Darkgray" StrokeThickness="1" Height="50" Width="50"
StrokeDashArray="5 3"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.Background>
</Border>
<ItemsControl>
<ItemsControl.ItemsSource>
<StaticResource ResourceKey="Col"/>
</ItemsControl.ItemsSource>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
</Window>
代码背后:
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls.Primitives;
namespace NodesEditor
{
public partial class MainWindow : Window
{
public List<Node> Nodes { get; set; }
public List<Connector> Connectors { get; set; }
public MainWindow()
{
InitializeComponent();
Nodes = NodesDataSource.GetRandomNodes().ToList();
Connectors = NodesDataSource.GetRandomConnectors(Nodes).ToList();
DataContext = this;
}
private void Thumb_Drag(object sender, DragDeltaEventArgs e)
{
var thumb = sender as Thumb;
if (thumb == null)
return;
var data = thumb.DataContext as Node;
if (data == null)
return;
data.X += e.HorizontalChange;
data.Y += e.VerticalChange;
}
}
}
数据模型:
public class Node: INotifyPropertyChanged
{
private double _x;
public double X
{
get { return _x; }
set
{
//"Grid Snapping"
//this actually "rounds" the value so that it will always be a multiple of 50.
_x = (Math.Round(value/50.0)) * 50;
OnPropertyChanged("X");
}
}
private double _y;
public double Y
{
get { return _y; }
set
{
//"Grid Snapping"
//this actually "rounds" the value so that it will always be a multiple of 50.
_y = (Math.Round(value/50.0)) * 50;
OnPropertyChanged("Y");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Connector
{
public Node Start { get; set; }
public Node End { get; set; }
}
随机数据来源(填补实例东西mple)
using System;
using System.Collections.Generic;
using System.Linq;
namespace NodesEditor
{
public static class NodesDataSource
{
public static Random random = new Random();
public static Node GetRandomNode()
{
return new Node
{
X = random.Next(0,500),
Y = random.Next(0,500)
};
}
public static IEnumerable<Node> GetRandomNodes()
{
return Enumerable.Range(5, random.Next(6, 10)).Select(x => GetRandomNode());
}
public static Connector GetRandomConnector(IEnumerable<Node> nodes)
{
return new Connector { Start = nodes.FirstOrDefault(), End = nodes.Skip(1).FirstOrDefault() };
}
public static IEnumerable<Connector> GetRandomConnectors(List<Node> nodes)
{
var result = new List<Connector>();
for (int i = 0; i < nodes.Count() - 1; i++)
{
result.Add(new Connector() {Start = nodes[i], End = nodes[i + 1]});
}
return result;
}
}
}
这就是它看起来像在我的电脑:
+1。你应该修改你的'WinForms方法到WPF'的默认策略:)。因为否则你提供很好的建设性的答案(我已经看到至少有两个完整的例子给你,以帮助OP),这是非常有启发性的。我知道,因为我曾经犯过一次错误的结局。不过在主题上,我试图让自己做一个WPF应用程序,但由于我的可怜的WPF sw was声而无法完成。将看看你的应用程序。谢谢。 – nakiya 2013-03-15 02:27:00
如果OP有要求在用户双击某个位置时将节点插入此网格又该怎么办?我应该如何去实现这个呢? – nakiya 2013-03-15 02:48:01
嗯,通过处理'Grid'的OnMouseRightButtonUp事件来实现这个工作。尽管在Grid中找不到双击事件。 – nakiya 2013-03-15 03:10:01
你显然每个鼠标按下事件创建一个新的DrawingVisual - 是你的实际代码? – ChrisF 2013-03-14 23:03:33
'WPF让我疯狂......' - 那是因为你使用WPF以winforms的方式。为什么在这个世界上你会搞乱'OnRender()'??。请张贴你需要的截图,我们可以给你一个正确的方法来在XAML中做到这一点。还记得我告诉过你不要在代码中操纵UI元素吗?还记得我还告诉过你,你需要“以一种抽象的方式来思考你的UI”吗? – 2013-03-14 23:03:45
更新...我认为主要适用于更新菜单。我有很多麻烦理解如何不... – 2013-03-14 23:11:56