您的解决方法是正确的,我使用您的代码作为指导。
所以,这里的第一个是提供您想要的结果的代码,
这将转到 MainWindow xaml:
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="20" />
<RowDefinition />
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="Button" HorizontalAlignment="Left" Click="GenerateGraphBtn_Click" />
<Canvas Grid.Row="2" x:Name="GrpahArea" Margin="40" />
</Grid>
</Window>
这会进入 MainWindow 的代码隐藏
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private Point[] GenerateGraphPoints(int minimumX, int maximumX, int minimumY, int maximumY)
{
var result = new List<Point>();
var rnd = new Random();
for (var x = minimumX; x < maximumX; x++)
result.Add(new Point(x, rnd.Next(minimumY, maximumY)));
return result.ToArray();
}
private void PlotXAxes(Panel drawArea, int minimumX, int maximumX, int step, int miniLineExtent)
{
var geometryGroup = new GeometryGroup();
var axePositionY = drawArea.ActualHeight;
geometryGroup.Children.Add(new LineGeometry(new Point(0, axePositionY), new Point(drawArea.ActualWidth, axePositionY)));
var factorX = drawArea.ActualWidth / (maximumX - minimumX);
for (var i = minimumX; i < maximumX; i++)
if (i % step == 0)
{
geometryGroup.Children.Add(new LineGeometry(
new Point(i * factorX, axePositionY - miniLineExtent),
new Point(i * factorX, axePositionY + miniLineExtent)));
drawArea.Children.Add(new Label
{
Margin = new Thickness(i*factorX, axePositionY + miniLineExtent, 0, 0),
Content = i,
Foreground = Brushes.Black
});
}
var path = new Path
{
StrokeThickness = 2,
Stroke = Brushes.DarkRed,
Data = geometryGroup
};
drawArea.Children.Add(path);
}
private void PlotYAxes(Panel drawArea, int minimumY, int maximumY, int step, int miniLineExtent)
{
var labelSize = new Size(30, 26);
var geometryGroup = new GeometryGroup();
var axePositionX = 0;
geometryGroup.Children.Add(new LineGeometry(new Point(axePositionX, 0), new Point(axePositionX, drawArea.ActualHeight)));
var factorY = drawArea.ActualHeight / (maximumY - minimumY);
for (var i = minimumY; i < maximumY; i++)
if (i % step == 0)
{
geometryGroup.Children.Add(new LineGeometry(
new Point(axePositionX - miniLineExtent, (maximumY-i) * factorY),
new Point(axePositionX + miniLineExtent, (maximumY-i) * factorY)));
drawArea.Children.Add(new Label
{
Width = labelSize.Width,
Height = labelSize.Height,
Margin = new Thickness(
axePositionX - miniLineExtent - labelSize.Width,
(maximumY - i) * factorY - (labelSize.Height / 2), 0, 0),
Content = i,
Foreground = Brushes.Black
});
}
var path = new Path
{
StrokeThickness = 2,
Stroke = Brushes.DarkRed,
Data = geometryGroup
};
drawArea.Children.Add(path);
}
private void PlotGraph(Point[] points, Panel drawArea, int minimumX, int maximumX, int minimumY, int maximumY)
{
var factorX = drawArea.ActualWidth / (maximumX-minimumX);
var factorY = drawArea.ActualHeight / (maximumY-minimumY);
for (var i = 0; i < points.Length; i++)
{
points[i].X *= factorX;
//points[i].Y *= factorY;
points[i].Y = (maximumY - points[i].Y) * factorY; //since zero of Y should be in bottom we "swap" the Y value.
}
Polyline polyline = new Polyline();
polyline.StrokeThickness = 2;
polyline.Stroke = Brushes.Blue;
polyline.Points = new PointCollection(points);
drawArea.Children.Add(polyline);
}
private void GenerateGraphBtn_Click(object sender, RoutedEventArgs e)
{
//Step 1: define the data limits and generate the data, this has nothing to do with the view.
const int xmin = 0, xmax = 12;
const int ymin = 0, ymax = 800;
var graphPoints = GenerateGraphPoints(xmin, xmax, ymin, ymax);
//Step 2: Draw yAxes
PlotYAxes(GrpahArea, ymin, ymax, 100, 2);
//Step 3: Draw xAxes
PlotXAxes(GrpahArea, xmin, xmax, 1, 2);
//Step 4: Plot Grpah
var plotPoints = new Point[graphPoints.Length]; //graphPoints is our model, we usually wish to keep the original value of model.
graphPoints.CopyTo(plotPoints,0); //plotPoints is what we going to scale and adjust to the view.
PlotGraph(plotPoints, GrpahArea, xmin, xmax, ymin, ymax);
}
}
}
现在到我回答的第二部分,构建图形组件并不是那么简单的任务,主要是因为图形通常被开发为许多应用程序的通用,所以允许的定制量需要很大,这就是其他人的原因正确地将您引导到一个现成的图书馆。
另外,我在答案中为您提供的代码不是 MVVM 样式,它与您提供的代码非常接近。这是因为以 MVVM 样式编写将需要创建一组视图模型类并将它们绑定到视图,考虑到自定义,与您要求解决的问题相比,这是相当大的努力。
但我希望提供的代码可以帮助您做任何您想做的事情。
更新,添加标签:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private Point[] GenerateGraphPoints(int minimumX, int maximumX, int minimumY, int maximumY)
{
var result = new List<Point>();
var rnd = new Random();
for (var x = minimumX; x < maximumX; x++)
result.Add(new Point(x, rnd.Next(minimumY, maximumY)));
return result.ToArray();
}
private void PlotXAxes(Panel drawArea, int minimumX, int maximumX, int step, int miniLineExtent, string title)
{
var geometryGroup = new GeometryGroup();
var axePositionY = drawArea.ActualHeight;
geometryGroup.Children.Add(new LineGeometry(new Point(0, axePositionY), new Point(drawArea.ActualWidth, axePositionY)));
var factorX = drawArea.ActualWidth / (maximumX - minimumX);
for (var i = minimumX; i < maximumX; i++)
if (i % step == 0)
{
geometryGroup.Children.Add(new LineGeometry(
new Point(i * factorX, axePositionY - miniLineExtent),
new Point(i * factorX, axePositionY + miniLineExtent)));
drawArea.Children.Add(new Label
{
Margin = new Thickness(i*factorX, axePositionY + miniLineExtent, 0, 0),
Content = i,
Foreground = Brushes.Black
});
}
var path = new Path
{
StrokeThickness = 2,
Stroke = Brushes.DarkRed,
Data = geometryGroup
};
drawArea.Children.Add(path);
var titleLabel = new Label
{
Margin = new Thickness(drawArea.ActualWidth - 50, drawArea.ActualHeight - 20, 0, 0),
Content = title
};
drawArea.Children.Add(titleLabel);
}
private void PlotYAxes(Panel drawArea, int minimumY, int maximumY, int step, int miniLineExtent, string title)
{
var labelSize = new Size(30, 26);
var geometryGroup = new GeometryGroup();
var axePositionX = 0;
geometryGroup.Children.Add(new LineGeometry(new Point(axePositionX, 0), new Point(axePositionX, drawArea.ActualHeight)));
var factorY = drawArea.ActualHeight / (maximumY - minimumY);
for (var i = minimumY; i < maximumY; i++)
if (i % step == 0)
{
geometryGroup.Children.Add(new LineGeometry(
new Point(axePositionX - miniLineExtent, (maximumY-i) * factorY),
new Point(axePositionX + miniLineExtent, (maximumY-i) * factorY)));
drawArea.Children.Add(new Label
{
Width = labelSize.Width,
Height = labelSize.Height,
Margin = new Thickness(
axePositionX - miniLineExtent - labelSize.Width,
(maximumY - i) * factorY - (labelSize.Height / 2), 0, 0),
Content = i,
Foreground = Brushes.Black
});
}
var path = new Path
{
StrokeThickness = 2,
Stroke = Brushes.DarkRed,
Data = geometryGroup
};
drawArea.Children.Add(path);
var titleLabel = new Label
{
Margin = new Thickness(0, 0, 0, 0),
Content = title
};
drawArea.Children.Add(titleLabel);
}
private void PlotGraph(Point[] points, Panel drawArea, int minimumX, int maximumX, int minimumY, int maximumY)
{
var factorX = drawArea.ActualWidth / (maximumX-minimumX);
var factorY = drawArea.ActualHeight / (maximumY-minimumY);
for (var i = 0; i < points.Length; i++)
{
points[i].X *= factorX;
//points[i].Y *= factorY;
points[i].Y = (maximumY - points[i].Y) * factorY; //since zero of Y should be in bottom we "swap" the Y value.
}
Polyline polyline = new Polyline();
polyline.StrokeThickness = 2;
polyline.Stroke = Brushes.Blue;
polyline.Points = new PointCollection(points);
drawArea.Children.Add(polyline);
}
private void GenerateGraphBtn_Click(object sender, RoutedEventArgs e)
{
//Step 1: define the data limits and generate the data, this has nothing to do with the view.
const int xmin = 0, xmax = 12;
const int ymin = 0, ymax = 800;
var graphPoints = GenerateGraphPoints(xmin, xmax, ymin, ymax);
GrpahArea.Children.Add(new Label
{
Content = "Profits over months",
Margin = new Thickness(GrpahArea.ActualWidth / 2 - 100, -50, 0, 0)
});
//Step 2: Draw yAxes
PlotYAxes(GrpahArea, ymin, ymax, 100, 2, "Profits");
//Step 3: Draw xAxes
PlotXAxes(GrpahArea, xmin, xmax, 1, 2, "Months");
//Step 4: Plot Grpah
var plotPoints = new Point[graphPoints.Length]; //graphPoints is our model, we usually wish to keep the original value of model.
graphPoints.CopyTo(plotPoints,0); //plotPoints is what we going to scale and adjust to the view.
PlotGraph(plotPoints, GrpahArea, xmin, xmax, ymin, ymax);
}
}
}