第三方自定義控件
<UserControl x:Class="Painter.RadarControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Painter"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Canvas x:Name="CanvasPanel" HorizontalAlignment="Center" VerticalAlignment="Center" Background="Gray">
</Canvas>
</Grid>
</UserControl>
/// <summary>
/// RadarControl.xaml 的交互邏輯
/// </summary>
public partial class RadarControl : UserControl
{
public RadarControl()
{
InitializeComponent();
}
#region 屬性
/// <summary>
/// 數值區域填充色
/// </summary>
public Brush AreaBrush
{
get { return (Brush)GetValue(AreaBrushProperty); }
set { SetValue(AreaBrushProperty, value); }
}
public static readonly DependencyProperty AreaBrushProperty = DependencyProperty.Register("AreaBrush", typeof(Brush),
typeof(RadarControl), new PropertyMetadata(Brushes.Black));
/// <summary>
/// 數值區域點填充色
/// </summary>
public Brush AreaPointBrush
{
get { return (Brush)GetValue(AreaPointBrushProperty); }
set { SetValue(AreaPointBrushProperty, value); }
}
public static readonly DependencyProperty AreaPointBrushProperty = DependencyProperty.Register("AreaPointBrush", typeof(Brush),
typeof(RadarControl), new PropertyMetadata(Brushes.Black));
/// <summary>
/// 雷達網格線填充充色
/// </summary>
public Brush RadarNetBrush
{
get { return (Brush)GetValue(RadarNetBrushProperty); }
set { SetValue(RadarNetBrushProperty, value); }
}
public static readonly DependencyProperty RadarNetBrushProperty = DependencyProperty.Register("RadarNetBrush", typeof(Brush),
typeof(RadarControl), new PropertyMetadata(Brushes.Black));
/// <summary>
/// 雷達網格線寬度
/// </summary>
public double RadarNetThickness
{
get { return (double)GetValue(RadarNetThicknessProperty); }
set { SetValue(RadarNetThicknessProperty, value); }
}
public static readonly DependencyProperty RadarNetThicknessProperty = DependencyProperty.Register("RadarNetThickness", typeof(double),
typeof(RadarControl), new PropertyMetadata(1.0));
/// <summary>
/// 數值點高寬度,0爲不顯示
/// </summary>
public double AreaPointSize
{
get { return (double)GetValue(AreaPointSizeProperty); }
set { SetValue(AreaPointSizeProperty, value); }
}
public static readonly DependencyProperty AreaPointSizeProperty = DependencyProperty.Register("AreaPointSize", typeof(double),
typeof(RadarControl), new PropertyMetadata(10.0));
/// <summary>
/// 緯線數量
/// </summary>
public int LatitudeCount
{
get { return (int)GetValue(LatitudeCountProperty); }
set { SetValue(LatitudeCountProperty, value); }
}
public static readonly DependencyProperty LatitudeCountProperty = DependencyProperty.Register("LatitudeCount", typeof(int),
typeof(RadarControl), new PropertyMetadata(5));
/// <summary>
/// 網格圖停靠間距
/// </summary>
public int RadarNetMargin
{
get { return (int)GetValue(RadarNetMarginProperty); }
set { SetValue(RadarNetMarginProperty, value); }
}
public static readonly DependencyProperty RadarNetMarginProperty = DependencyProperty.Register("RadarNetMargin", typeof(int),
typeof(RadarControl), new PropertyMetadata(50));
/// <summary>
/// 顯示值標註
/// </summary>
public bool ShowValuesLabel
{
get { return (bool)GetValue(ShowValuesLabelProperty); }
set { SetValue(ShowValuesLabelProperty, value); }
}
public static readonly DependencyProperty ShowValuesLabelProperty = DependencyProperty.Register("ShowValuesLabel", typeof(bool),
typeof(RadarControl), new PropertyMetadata(true));
/// <summary>
/// 顯示組標籤
/// </summary>
public bool ShowGroupsLabel
{
get { return (bool)GetValue(ShowGroupsLabelProperty); }
set { SetValue(ShowGroupsLabelProperty, value); }
}
public static readonly DependencyProperty ShowGroupsLabelProperty = DependencyProperty.Register("ShowGroupsLabel", typeof(bool),
typeof(RadarControl), new PropertyMetadata(true));
/// <summary>
/// 是否爲多重繪圖模式(默認否)
/// </summary>
public bool MoreGraphics
{
get { return (bool)GetValue(MoreGraphicsProperty); }
set { SetValue(MoreGraphicsProperty, value); }
}
public static readonly DependencyProperty MoreGraphicsProperty = DependencyProperty.Register("MoreGraphics", typeof(bool),
typeof(RadarControl), new PropertyMetadata(false));
/// <summary>
/// 分隔角度
/// </summary>
private double Angle
{
get
{
int count = MoreGraphics ? MoreDatas[0].Count : Datas.Count;
double angle = 360 / count;
return angle;
}
}
/// <summary>
/// 數據
/// </summary>
public List<RadarObj> Datas
{
get { return (List<RadarObj>)GetValue(DatasProperty); }
set { SetValue(DatasProperty, value); }
}
public static readonly DependencyProperty DatasProperty = DependencyProperty.Register("Datas", typeof(List<RadarObj>),
typeof(RadarControl), new PropertyMetadata(new List<RadarObj>()));
/// <summary>
/// 多元數據
/// </summary>
public List<RadarObj>[] MoreDatas
{
get { return (List<RadarObj>[])GetValue(MoreDatasProperty); }
set { SetValue(MoreDatasProperty, value); }
}
public static readonly DependencyProperty MoreDatasProperty = DependencyProperty.Register("MoreDatas", typeof(List<RadarObj>[]),
typeof(RadarControl), new PropertyMetadata(new List<RadarObj>[2]));
/// <summary>
/// 多元數據畫筆
/// </summary>
public List<Brush> RadarNetBrushes
{
get { return (List<Brush>)GetValue(RadarNetBrushesProperty); }
set { SetValue(RadarNetBrushesProperty, value); }
}
public static readonly DependencyProperty RadarNetBrushesProperty = DependencyProperty.Register("RadarNetBrushes", typeof(List<Brush>),
typeof(RadarControl), new PropertyMetadata(new List<Brush>()));
/// <summary>
/// 當前繪製大區域
/// </summary>
private double MaxSize
{
get
{
var par = this.Parent as FrameworkElement;
return par.ActualHeight > par.ActualWidth ? par.ActualWidth : par.ActualHeight;
}
}
#endregion 屬性
private void RadarControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (!MoreGraphics)
InitalData();
else
InitalMoreData();
}
/// <summary>
/// 設置標註
/// </summary>
/// <param name="obj"></param>
/// <param name="location"></param>
/// <param name="isGroupLabel"></param>
private void SetLabel(RadarObj obj, Point location, bool isGroupLabel)
{
//計算偏移量
bool x = true;
bool y = true;
if (location.X < 0)
x = false;
if (location.Y < 0)
y = false;
TextBlock txb = new TextBlock() { Text = isGroupLabel ? obj.Name : obj.DataValue.ToString(), Foreground = this.Foreground, FontSize = this.FontSize };
Size s = ControlSizeUtils.GetTextAreaSize(txb.Text,this.FontSize);
CanvasPanel.Children.Add(txb);
if (location.X > -5 && location.X < 5)
Canvas.SetLeft(txb, location.X - (s.Width / 2));
else
Canvas.SetLeft(txb, location.X + (x ? 0 : -(s.Width)));
if (location.Y > -5 && location.Y < 5)
Canvas.SetTop(txb, location.Y - (s.Height / 2));
else
Canvas.SetTop(txb, location.Y + (y ? 0 : -(s.Height)));
}
/// <summary>
/// 設置數據顯示
/// </summary>
private void InitalData()
{
CanvasPanel.Children.Clear();
if (Datas != null && Datas.Count > 0)
{
this.CanvasPanel.Width = this.CanvasPanel.Height = 0;
//計算比例尺
var scale = ((MaxSize / 2) - RadarNetMargin) / Datas.Max(i => i.DataValue);
//計算實際半徑
for (int i = 0; i < Datas.Count; i++)
{
Datas[i].DataRaidus = Datas[i].DataValue * scale;
}
//獲取最大數值
double maxData = Datas.Max(i => i.DataRaidus);
//計算緯線間距半徑
double length = maxData / LatitudeCount;
for (int index = 1; index < LatitudeCount + 1; index++)
{
//多邊形半徑
var r = length * index;
Polygon polygonBorder = new Polygon() { Fill = Brushes.Transparent, Stroke = RadarNetBrush, StrokeThickness = RadarNetThickness };
//繪製多邊形
for (int currentIndex = 0; currentIndex < Datas.Count; currentIndex++)
{
double angle = ((Angle * currentIndex + 90) / 360) * 2 * Math.PI;
polygonBorder.Points.Add(new Point(r * Math.Cos(angle), r * Math.Sin(angle)));
}
CanvasPanel.Children.Add(polygonBorder);
}
//數值區域多邊形
Polygon polygonArea = new Polygon() { Fill = AreaBrush, Opacity = 0.5, Stroke = AreaPointBrush, StrokeThickness = 5 };
//經線長度
var maxRadius = LatitudeCount * length;
List<Ellipse> ellipselst = new List<Ellipse>();
Dictionary<RadarObj, Point> valuesLabelLocations = new Dictionary<RadarObj, Point>();
Dictionary<RadarObj, Point> groupLabelLocations = new Dictionary<RadarObj, Point>();
//繪製數據多邊形
for (int Index = 0; Index < Datas.Count; Index++)
{
//計算角度
double angle = ((Angle * Index + 90) / 360) * 2 * Math.PI;
//計算距離值
var cou = Datas[Index].DataRaidus / length; //計算倍距
var rac = Datas[Index].DataRaidus % length;//計算餘距
double Radius = cou * length + rac;
//超過最大半徑則設置爲最大半徑
if (Radius > maxRadius)
{
Radius = maxRadius;
}
Point pt = new Point(Radius * Math.Cos(angle), Radius * Math.Sin(angle));
polygonArea.Points.Add(pt);
valuesLabelLocations.Add(Datas[Index], new Point((Radius) * Math.Cos(angle), (Radius) * Math.Sin(angle)));//記錄點位標註標識
//設置數值點,如果數值點尺寸大於0則繪製
if (AreaPointSize > 0)
{
var ellipse = new Ellipse() { Width = AreaPointSize, Height = AreaPointSize, Fill = AreaPointBrush };
//var ellipse = new Ellipse() { Width = AreaPointSize, Height = AreaPointSize, Fill = Datas[Index].Fill }; AreaPointBrush
Canvas.SetLeft(ellipse, pt.X - (AreaPointSize / 2));
Canvas.SetTop(ellipse, pt.Y - (AreaPointSize / 2));
ellipselst.Add(ellipse);
}
Point ptMax = new Point(maxRadius * Math.Cos(angle), maxRadius * Math.Sin(angle));
//記錄組點位標註標識
groupLabelLocations.Add(Datas[Index], new Point((maxRadius + 20) * Math.Cos(angle), (maxRadius + 20) * Math.Sin(angle)));
//繪製經線
Path pth = new Path() { Stroke = RadarNetBrush, StrokeThickness = RadarNetThickness };
// Path pth = new Path() { Stroke = Datas[Index].Stroke, StrokeThickness = RadarNetThickness };
pth.Data = (Geometry)new GeometryConverter().ConvertFromString(String.Format("M0,0 {0},{1}", ptMax.X.ToString(), ptMax.Y.ToString()));
CanvasPanel.Children.Add(pth);
}
CanvasPanel.Children.Add(polygonArea);
//繪點
foreach (var elc in ellipselst)
CanvasPanel.Children.Add(elc);
//標註值標籤
if (ShowValuesLabel)
{
foreach (var item in valuesLabelLocations)
{
// SetLabel(item.Key, item.Value, false);
}
}
//標註組標籤
if (ShowGroupsLabel)
{
foreach (var item in groupLabelLocations)
SetLabel(item.Key, item.Value, true);
}
this.SizeChanged -= RadarControl_SizeChanged;
this.SizeChanged += RadarControl_SizeChanged;
}
}
/// <summary>
/// 設置數據顯示
/// </summary>
private void InitalMoreData()
{
CanvasPanel.Children.Clear();
if (this.MoreDatas != null && MoreDatas.Length > 0)
{
this.CanvasPanel.Width = this.CanvasPanel.Height = 0;
//計算比例尺
var max = 0.00;
foreach (var item in MoreDatas)
if (item.Max(i => i.DataValue) > max)
max = item.Max(i => i.DataValue);
var scale = ((MaxSize / 2) - RadarNetMargin) / max;
//計算實際半徑
for (int index = 0; index < MoreDatas.Length; index++)
for (int i = 0; i < MoreDatas[index].Count; i++)
MoreDatas[index][i].DataRaidus = MoreDatas[index][i].DataValue * scale;
//獲取最大數值
double maxData = 0.000;
foreach (var item in MoreDatas)
if (item.Max(i => i.DataRaidus) > maxData)
maxData = item.Max(i => i.DataRaidus);
//計算緯線間距半徑
double length = maxData / LatitudeCount;
for (int index = 1; index < LatitudeCount + 1; index++)
{
//多邊形半徑
var r = length * index;//RadarNetBrush
Polygon polygonBorder = new Polygon() { Fill = Brushes.Transparent, Stroke = RadarNetBrush, StrokeThickness = RadarNetThickness };
//繪製多邊形
for (int currentIndex = 0; currentIndex < MoreDatas[0].Count; currentIndex++)
{
double angle = ((Angle * currentIndex + 90) / 360) * 2 * Math.PI;
polygonBorder.Points.Add(new Point(r * Math.Cos(angle), r * Math.Sin(angle)));
}
CanvasPanel.Children.Add(polygonBorder);
}
//數值區域多邊形
List<Polygon> polygonAreaList = new List<Polygon>();
for (int index = 0; index < this.MoreDatas.Length; index++)
polygonAreaList.Add(new Polygon() { Fill = RadarNetBrushes[index], Opacity = 0.5, Stroke = Brushes.LightGreen, StrokeThickness = 3 });
//經線長度
var maxRadius = LatitudeCount * length;
List<Ellipse> ellipselst = new List<Ellipse>();
Dictionary<RadarObj, Point> valuesLabelLocations = new Dictionary<RadarObj, Point>();
Dictionary<RadarObj, Point> groupLabelLocations = new Dictionary<RadarObj, Point>();
//繪製數據多邊形
for (int Index = 0; Index < MoreDatas[0].Count; Index++)
{
//計算角度
double angle = ((Angle * Index + 90) / 360) * 2 * Math.PI;
//逐步生成每類數據的各組實際數據:例如A、B、C、D的交通數據數據
for (int dataIndex = 0; dataIndex < MoreDatas.Length; dataIndex++)
{
//計算距離值
var cou = MoreDatas[dataIndex][Index].DataRaidus / length; //計算倍距
var rac = MoreDatas[dataIndex][Index].DataRaidus % length;//計算餘距
double Radius = cou * length + rac;
//超過最大半徑則設置爲最大半徑
if (Radius > maxRadius)
{
Radius = maxRadius;
}
Point pt = new Point(Radius * Math.Cos(angle), Radius * Math.Sin(angle));
polygonAreaList[dataIndex].Points.Add(pt);
//valuesLabelLocations.Add(Datas[Index], new Point((Radius) * Math.Cos(angle), (Radius) * Math.Sin(angle)));//記錄點位標註標識
//設置數值點,如果數值點尺寸大於0則繪製
if (AreaPointSize > 0)
{
var ellipse = new Ellipse() { Width = AreaPointSize / 2, Height = AreaPointSize / 2, Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString(ChartColorPool.ColorStrings[Index])) };
Canvas.SetLeft(ellipse, pt.X - (AreaPointSize / 4));
Canvas.SetTop(ellipse, pt.Y - (AreaPointSize / 4));
ellipselst.Add(ellipse);
}
}
Point ptMax = new Point(maxRadius * Math.Cos(angle), maxRadius * Math.Sin(angle));
//記錄組點位標註標識
groupLabelLocations.Add(MoreDatas[0][Index], new Point((maxRadius + 20) * Math.Cos(angle), (maxRadius + 20) * Math.Sin(angle)));
//繪製經線 RadarNetBrush
Path pth = new Path() { Stroke = RadarNetBrush, StrokeThickness = RadarNetThickness };
pth.Data = (Geometry)new GeometryConverter().ConvertFromString(String.Format("M0,0 {0},{1}", ptMax.X.ToString(), ptMax.Y.ToString()));
CanvasPanel.Children.Add(pth);
}
foreach (var polygonArea in polygonAreaList)
CanvasPanel.Children.Add(polygonArea);
//繪點
foreach (var elc in ellipselst)
CanvasPanel.Children.Add(elc);
//標註組標籤
if (ShowGroupsLabel)
{
foreach (var item in groupLabelLocations)
SetLabel(item.Key, item.Value, true);
}
this.SizeChanged -= RadarControl_SizeChanged;
this.SizeChanged += RadarControl_SizeChanged;
}
}
public void InitalControl()
{
}
/// <summary>
/// 加載數據
/// </summary>
/// <param name="dataobj"></param>
public void SetData(object dataobj)
{
if (!MoreGraphics)
{
this.Datas = (dataobj) as List<RadarObj>;
this.InitalData();
}
else
{
this.MoreDatas = (dataobj) as List<RadarObj>[];
InitalMoreData();
}
}
private Brush _stroke = Brushes.Yellow;
/// <summary>
/// Series stroke
/// </summary>
public Brush Stroke
{
get
{
return _stroke;
}
set
{
_stroke = value;
}
}
private Brush _fill = Brushes.Yellow;
/// <summary>
/// Series Fill
/// </summary>
public Brush Fill
{
get
{
return _fill;
}
set
{
_fill = value;
}
}
}
界面:
<Grid Grid.Column="0"
Name="Grid_radar">
</Grid>
後臺賦值:
RadarControl rdc = new RadarControl()
{
MoreGraphics = true,
AreaBrush = ThemeBrush,//Brushes.Green,
RadarNetBrush = new SolidColorBrush(Color.FromRgb(157, 215, 231)),
AreaPointBrush = Brushes.Red,
BorderBrush = Brushes.Blue,
RadarNetBrushes = new List<Brush> { Brushes.LightSkyBlue, Brushes.Violet }
};
private void RadarsShow()
{
try
{
int[] array = new int[] { 65, 10, 11, 9, 6, 4 };
this.Grid_radar.Children.Clear();
this.Grid_radar.Children.Add(rdc);
List<RadarObj>[] lst = { CrData(array) };
rdc.SetData(lst);
}
catch (Exception ex)
{
AppLog.Write(ex.ToString(), LogMessageType.Error);
}
}