Я рисую сетку на фоне холста.На этом холсте я размечаю вертикальные линии сетки, которая рисуется на фоне холста.Затем на том же холсте у меня есть ItemsSource, Panel которого является еще одним холстом, и на этом холсте я рисую объект Line с использованием точек.Изначально в программе запускаются вертикальные линии сетки, выровненные по точкам объекта Линия.Вертикальная позиция сетки отображается на 30-й позиции.И каждая точка на линии полностью выровнена по вертикальной линии сетки.Когда происходит событие колесика мыши, я хочу увеличить объект линии.Я использую ScaleTransform для этой цели.В обработчике событий я меняю ширину холста.Предположим, я использую преобразование Scale с ScaleX, равным 4. Это означает, что новая ширина холста будет равна начальной ширине * 4.Точка, расположенная в 1 на оси x холста, теперь будет находиться в позиции 4 на оси X холста.Итак, моя седьмая точка будет в позиции 28. Поскольку мы знаем, что вертикальная линия сетки проведена в позиции 30. А моя восьмая точка будет в позиции 32. Теперь я не в курсе.Я не могу выбрать положение вертикальной линии сетки во время выполнения.Если изначально выбрано значение 30, оно должно остаться равным 30. При увеличении по мере увеличения ширины холста рисуются новые сетки. Условие максимального увеличения состоит в том, что существует только 1 точка в 1 прямоугольнике сетки.Это означает, что вертикальная линия будет проведена в позиции 30, поэтому в 30-й позиции должна появиться 1-ая точка линии.
C #
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; }
}
}
XAML
<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>