我正在画布背景上绘制网格。在此画布上,我标记了在画布背景上绘制的网格的垂直线。然后在同一画布中,我有ItemsSource,其Panel是另一个Canvas,并且在该画布上,我使用Points绘制Line对象。最初,程序在运行,网格的垂直线与Line对象的点对齐。网格的垂直位置在第30个位置绘制。并且线上的每个点都与网格的垂直线完全对齐。触发“鼠标滚轮”事件后,我要放大线对象。我为此使用ScaleTransform。在事件处理程序中,我正在更改画布宽度。假设我在ScaleX等于4的情况下使用Scale变换。这意味着新的画布宽度将等于初始宽度* 4。现在,在画布x轴上位于1的点将位于画布x轴上的位置4。因此,我的第7点将位于位置28。众所周知,网格的垂直线是在位置30处绘制的。而我的第8点将在位置32处绘制。现在我毫无头绪。我无法在运行时选择网格垂直线的位置。如果最初选择30,则必须保留30。在放大的同时,随着我增加画布的宽度,将绘制新的Grid。最大放大条件是1个矩形中仅存在1个点。这意味着垂直线将在位置30处绘制,因此在第30个位置应显示该线的第一个点。
namespace CanvasWidthChecker
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
double scaleFactor = 1;
double deltaDistance = 1;
ulong totalSamples;
const double maximumDeltaDistance = 30;
double maximumScale = maximumDeltaDistance;
List<Line> verticalLines = new List<Line>();
private double initialWidth;
public double InitialWidth
{
get { return initialWidth; }
set { initialWidth = value; }
}
private double myWidth= 60;
public double MyWidth
{
get { return myWidth; }
set
{
myWidth = value;
OnPropertyChanged("MyWidth");
}
}
private void Line_Loaded(object sender, RoutedEventArgs e)
{
Line line = sender as Line;
if (line.Y1 != line.Y2)
{
verticalLines.Add(line);
}
}
private ObservableCollection<Graph> lines;
public ObservableCollection<Graph> Lines
{
get { return lines; }
set { lines = value; }
}
private ObservableCollection<MyLabel> myList;
public ObservableCollection<MyLabel> MyList
{
get { return myList; }
set
{
myList = value;
OnPropertyChanged("MyList");
}
}
private ulong samplecount;
public ulong Samplecount
{
get { return samplecount; }
set { samplecount = value; }
}
public MainWindow()
{
InitializeComponent();
this.Samplecount = 60;
this.InitialWidth = Samplecount;
MyList = new ObservableCollection<MyLabel>();
MyList.Add(new MyLabel() { ContentData = "0" });
MyList.Add(new MyLabel() { ContentData = "30" });
Lines = new ObservableCollection<Graph>();
Lines.Add(new Graph() { From = new Point(0,22), To = new Point (18,22) });
Lines.Add(new Graph() { From = new Point(18-0.5, 22), To = new Point(18-0.5, 7) });
Lines.Add(new Graph() { From = new Point(18, 7), To = new Point(24, 7) });
Lines.Add(new Graph() { From = new Point(24-0.5, 7), To = new Point(24-0.5, 22) });
Lines.Add(new Graph() { From = new Point(24, 22), To = new Point(60, 22) }); // Samplecount was 60
DataContext = this;
}
private void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
Canvas canvas = (Canvas)sender;
e.Handled = true;
double deltaValue = (e.Delta > 0) ? 1 : -1;
deltaDistance += deltaValue;
if(deltaDistance<2)
{
deltaDistance = 1;
}
ScaleTransform scaleTransform = new ScaleTransform(deltaDistance, 1);
canvas.RenderTransform = scaleTransform;
verticalLines.ForEach(x => {
x.RenderTransformOrigin = new Point(1, 1);
x.RenderTransform = new ScaleTransform(1 / scaleTransform.ScaleX, 1 / scaleTransform.ScaleY);
});
canvas.Width = 60 * deltaDistance;
MyWidth = canvas.Width;
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
}
public class Graph
{
private Point from;
public Point From
{
get { return from; }
set { from = value; }
}
private Point to;
public Point To
{
get { return to; }
set { to = value; }
}
}
public class MyLabel
{
public string ContentData { get; set; }
}
}
<ScrollViewer Name="scrollViewer" HorizontalScrollBarVisibility="Auto" Margin="10,10,0,10" Padding="0,0,10,0"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualHeight}" >
<Canvas x:Name="back_canvas" Width="{Binding MyWidth}" Height="60"
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="30,30,10,20" >
<Canvas.Background>
<DrawingBrush TileMode="Tile" Viewport="0,0,30,30" ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,30,30"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Gray" Thickness="1"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Canvas.Background>
<ItemsControl ItemsSource="{Binding MyList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Name="horizontalLabels" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ContentData}" Canvas.Left="10" Canvas.Top="0"
Width="27"
Height="30" FontSize="12"
Margin="0,0,3,0">
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl ItemsSource="{Binding Lines}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Height="30" Margin="0,30,0,0" Background="Transparent" Name="front_canvas" ClipToBounds="True"
PreviewMouseWheel="OnPreviewMouseWheel"
Width="{Binding MyWidth, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line X1="{Binding From.X , Mode=TwoWay}" Y1="{Binding From.Y, Mode=TwoWay}" Stretch="None"
X2="{Binding To.X, Mode=TwoWay}" Y2="{Binding To.Y, Mode=TwoWay}"
Stroke="OrangeRed" StrokeThickness="1"
Loaded="Line_Loaded"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
</ScrollViewer>
</Window>