添加项目文件。

This commit is contained in:
wang-yin1
2025-07-14 21:08:46 +08:00
parent f4133fc5e9
commit 6deb8d089f
58 changed files with 5593 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
<b:NodeBase x:Class="ImageCapture.FolderImageNode"
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:ImageCapture"
xmlns:b="clr-namespace:VisionFrame.Base;assembly=VisionFrame.Base"
xmlns:c="clr-namespace:VisionFrame.Base.Converter;assembly=VisionFrame.Base"
mc:Ignorable="d"
d:DesignHeight="34" d:DesignWidth="140">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
<c:BoolToBrushConverter x:Key="b2c"/>
</UserControl.Resources>
<Grid Name="grid">
<!--选中状态提醒-->
<Rectangle Stroke="#999" StrokeThickness="1"
StrokeDashArray="3,5"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}"/>
<Border CornerRadius="6" Background="White" Margin="3"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}">
<Border.Effect>
<DropShadowEffect BlurRadius="10"
Color="Gray"
ShadowDepth="0"
Opacity="0.4"/>
</Border.Effect>
</Border>
<Border CornerRadius="5" Background="White"
Margin="3" BorderBrush="#771f71e5" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="18"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="#771f71e5" CornerRadius="4,0,0,4">
<Ellipse Width="8" Height="8" Fill="{Binding IsRunning,Converter={StaticResource b2c}}"/>
</Border>
<TextBlock Text="图像加载(F)" Grid.Column="1"
VerticalAlignment="Center" Margin="5,0"
Foreground="#555"/>
<TextBlock Text="{Binding Duration,StringFormat=\{0\}ms}" Grid.Column="1" FontSize="9"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5,0" Foreground="#888"/>
</Grid>
</Border>
<Grid Visibility="{Binding ElementName=grid,Path=IsMouseOver,Converter={StaticResource b2v}}">
<!--锚点对象-->
<!--上-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Top"
Stroke="#CCC" StrokeThickness="1"
Margin="0,-5,0,0"
Visibility="{Binding ShowAnchorT,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="T"/>
<!--下-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Bottom"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,0,-5"
Visibility="{Binding ShowAnchorB,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="B"/>
<!--左-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Left"
Stroke="#CCC" StrokeThickness="1"
Margin="-5,0,0,0"
Visibility="{Binding ShowAnchorL,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="L"/>
<!--右-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Right"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,-5,0"
Visibility="{Binding ShowAnchorR,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="R"/>
</Grid>
<Button Width="16" Height="16"
HorizontalAlignment="Right"
Content="&#xe660;"
Margin="10,0"
Background="#9F00"
Foreground="#FFF"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource DeleteElementButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
Command="{Binding DataContext.DeleteElementCommand,RelativeSource={RelativeSource AncestorType=ItemsControl,Mode=FindAncestor}}"
CommandParameter="{Binding}"/>
<ToggleButton Width="16" Height="16"
Tag="8"
Grid.Column="1"
HorizontalAlignment="Right"
Margin="28,0"
Content="&#xe7db;"
Foreground="White"
Background="#156FEE"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource ElementArgsButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
IsChecked="{Binding IsShowProperties}"/>
</Grid>
</b:NodeBase>

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VisionFrame.Base;
namespace ImageCapture
{
/// <summary>
/// FolderImageNode.xaml 的交互逻辑
/// </summary>
public partial class FolderImageNode : NodeBase
{
public FolderImageNode()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VisionFrame.Base;
namespace ImageCapture
{
/// <summary>
/// 通信目录进行图像加载
/// </summary>
public class FolderImageNodeModel : NodeModelBase
{
public FolderImageNodeModel()
{
this.NodeName = "图像加载(F)";
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "图像目录",
ArgType = "String",
Direction = "输入",
ValueMode = 2
});
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "图像Handle",
ArgType = "IntPtr",
Direction = "输出"
});
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "测试",
ArgType = "IntPtr",
Direction = "输出",
ValueMode = 1
});
}
int index = 0;
public override void Execute(IFlowContext flowContext)
{
// 对接输入参数
if (this.Arguments[0].ArgValue == null)
throw new Exception("图像目录参数未配置");
if (this.Arguments[1].ArgValue == null)
throw new Exception("图像Handle参数未配置");
string folder = this.Arguments[0].ArgValue.ToString();
if (!Directory.Exists(folder))
throw new Exception("图像目录未找到");
string[] files = Directory.GetFiles(folder, "*.bmp");
if (files.Length == 0)
throw new Exception("未发现图像文件");
IntPtr handle = new Bitmap(files[index]).GetHbitmap();
// 对接输入参数 --- FlowTab中的参数名称
//this.Arguments[1].ArgValue
var am = flowContext.ArgumentList
.FirstOrDefault(a => a.ArgName == this.Arguments[1].ArgValue.ToString());
if (am.ArgType != this.Arguments[1].ArgType)
throw new Exception("参数配置异常!类型不匹配");
am.Value = handle;
index++;
if (index >= files.Length)
index = 0;
}
}
}

View File

@@ -0,0 +1,100 @@
<b:NodeBase x:Class="ImageCapture.HalconImageNode"
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:ImageCapture"
xmlns:b="clr-namespace:VisionFrame.Base;assembly=VisionFrame.Base"
mc:Ignorable="d"
d:DesignHeight="34" d:DesignWidth="140">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
</UserControl.Resources>
<Grid x:Name="grid">
<!--选中状态提醒-->
<Rectangle Stroke="#999" StrokeThickness="1"
StrokeDashArray="3,5"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}"/>
<Border CornerRadius="6" Background="White" Margin="3"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}">
<Border.Effect>
<DropShadowEffect BlurRadius="10"
Color="Gray"
ShadowDepth="0"
Opacity="0.4"/>
</Border.Effect>
</Border>
<Border CornerRadius="5" Background="White"
Margin="3" BorderBrush="#771f71e5" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="18"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="#771f71e5" CornerRadius="4,0,0,4">
<Ellipse Width="8" Height="8" Fill="LawnGreen"/>
</Border>
<TextBlock Text="图像采集(H)" Grid.Column="1"
VerticalAlignment="Center" Margin="5,0"
Foreground="#555"/>
<TextBlock Text="0ms" Grid.Column="1" FontSize="9"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5,0" Foreground="#888"/>
</Grid>
</Border>
<Grid Visibility="{Binding ElementName=grid,Path=IsMouseOver,Converter={StaticResource b2v}}">
<!--锚点对象-->
<!--上-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Top"
Stroke="#CCC" StrokeThickness="1"
Margin="0,-5,0,0"
Visibility="{Binding ShowAnchorT,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="T"/>
<!--下-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Bottom"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,0,-5"
Visibility="{Binding ShowAnchorB,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="B"/>
<!--左-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Left"
Stroke="#CCC" StrokeThickness="1"
Margin="-5,0,0,0"
Visibility="{Binding ShowAnchorL,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="L"/>
<!--右-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Right"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,-5,0"
Visibility="{Binding ShowAnchorR,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="R"/>
</Grid>
<Button Width="16" Height="16"
HorizontalAlignment="Right"
Content="&#xe660;"
Margin="10,0"
Background="#9F00"
Foreground="#FFF"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource DeleteElementButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
Command="{Binding DataContext.DeleteElementCommand,RelativeSource={RelativeSource AncestorType=ItemsControl,Mode=FindAncestor}}"
CommandParameter="{Binding}"/>
</Grid>
</b:NodeBase>

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VisionFrame.Base;
namespace ImageCapture
{
/// <summary>
/// HalconImageNode.xaml 的交互逻辑
/// </summary>
public partial class HalconImageNode : NodeBase
{
public HalconImageNode()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VisionFrame.Base;
namespace ImageCapture
{
public class HalconImageNodeModel : NodeModelBase
{
public override void Execute(IFlowContext flowContext)
{
base.Execute(flowContext);
}
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy $(TargetPath) $(SolutionDir)VisionFrame\bin\Debug\net9.0-windows\Activities\$(TargetFileName) /y" />
</Target>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VisionFrame.Base\VisionFrame.Base.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VisionFrame.Base\VisionFrame.Base.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy $(TargetPath) $(SolutionDir)VisionFrame\bin\Debug\net9.0-windows\Activities\$(TargetFileName) /y" />
</Target>
</Project>

View File

@@ -0,0 +1,117 @@
<b:NodeBase x:Class="ImageProcess.ImageShowNode"
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:ImageProcess"
xmlns:b="clr-namespace:VisionFrame.Base;assembly=VisionFrame.Base"
mc:Ignorable="d"
d:DesignHeight="34" d:DesignWidth="140">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
</UserControl.Resources>
<Grid Name="grid">
<!--选中状态提醒-->
<Rectangle Stroke="#999" StrokeThickness="1"
StrokeDashArray="3,5"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}"/>
<Border CornerRadius="6" Background="White" Margin="3"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}">
<Border.Effect>
<DropShadowEffect BlurRadius="10"
Color="Gray"
ShadowDepth="0"
Opacity="0.4"/>
</Border.Effect>
</Border>
<Border CornerRadius="5" Background="White"
Margin="3" BorderBrush="#771f71e5" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="18"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="#771f71e5" CornerRadius="4,0,0,4">
<Ellipse Width="8" Height="8" Fill="LawnGreen"/>
</Border>
<TextBlock Text="图像显示" Grid.Column="1"
VerticalAlignment="Center" Margin="5,0"
Foreground="#555"/>
<TextBlock Text="0ms" Grid.Column="1" FontSize="9"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5,0" Foreground="#888"/>
</Grid>
</Border>
<Grid Visibility="{Binding ElementName=grid,Path=IsMouseOver,Converter={StaticResource b2v}}">
<!--锚点对象-->
<!--上-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Top"
Stroke="#CCC" StrokeThickness="1"
Margin="0,-5,0,0"
Visibility="{Binding ShowAnchorT,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="T"/>
<!--下-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Bottom"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,0,-5"
Visibility="{Binding ShowAnchorB,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="B"/>
<!--左-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Left"
Stroke="#CCC" StrokeThickness="1"
Margin="-5,0,0,0"
Visibility="{Binding ShowAnchorL,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="L"/>
<!--右-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Right"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,-5,0"
Visibility="{Binding ShowAnchorR,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="R"/>
</Grid>
<Button Width="16" Height="16"
HorizontalAlignment="Right"
Content="&#xe660;"
Margin="10,0"
Background="#9F00"
Foreground="#FFF"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource DeleteElementButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
Command="{Binding DataContext.DeleteElementCommand,RelativeSource={RelativeSource AncestorType=ItemsControl,Mode=FindAncestor}}"
CommandParameter="{Binding}"/>
<ToggleButton Width="16" Height="16"
Tag="8"
Grid.Column="1"
HorizontalAlignment="Right"
Margin="28,0"
Content="&#xe7db;"
Foreground="White"
Background="#156FEE"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource ElementArgsButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
IsChecked="{Binding IsShowProperties}"/>
</Grid>
</b:NodeBase>

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VisionFrame.Base;
namespace ImageProcess
{
/// <summary>
/// ImageShowNode.xaml 的交互逻辑
/// </summary>
public partial class ImageShowNode : NodeBase
{
public ImageShowNode()
{
InitializeComponent();
}
//public ICommand AnchorDownCommand { get; set; }
//public ICommand AnchorUpCommand { get; set; }
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.AnchorDownCommand?.Execute(
(this.DataContext as NodeModelBase).NodeId + ";" + (sender as Ellipse).Tag.ToString()
);
e.Handled = true;
}
private void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.AnchorUpCommand?.Execute(
(this.DataContext as NodeModelBase).NodeId + ";" + (sender as Ellipse).Tag.ToString()
);
e.Handled = true;
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VisionFrame.Base;
namespace ImageProcess
{
public class ImageShowNodeModel : NodeModelBase
{
public ImageShowNodeModel()
{
this.NodeName = "图像显示";
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "图像Handle",
ArgType = "IntPtr",
Direction = "输入",
ValueMode = 0
});
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "图像宽",
ArgType = "Int",
Direction = "输出",
ValueMode = 0
});
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "图像高",
ArgType = "Int",
Direction = "输出",
ValueMode = 0
});
}
public override void Execute(IFlowContext flowContext)
{
if (this.Arguments[0].ArgValue == null)
throw new Exception("图像Handle参数未配置");
var am = flowContext.ArgumentList
.FirstOrDefault(a => a.ArgName == this.Arguments[0].ArgValue.ToString());
if (am.ArgType != this.Arguments[0].ArgType)
throw new Exception("参数配置异常!类型不匹配");
if (IntPtr.TryParse(am.Value.ToString(), out IntPtr img_handler))
{
//
//Bitmap bitmap = Bitmap.FromHbitmap(img_handler);
//bitmap.Width
//bitmap.Height
flowContext.ShowImage(img_handler);
}
else
throw new Exception("图像Handle数据无效");
}
}
}

119
LogicControl/AddNode.xaml Normal file
View File

@@ -0,0 +1,119 @@
<b:NodeBase x:Class="LogicControl.AddNode"
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:b="clr-namespace:VisionFrame.Base;assembly=VisionFrame.Base"
xmlns:c="clr-namespace:VisionFrame.Base.Converter;assembly=VisionFrame.Base"
xmlns:local="clr-namespace:LogicControl"
mc:Ignorable="d"
d:DesignHeight="34" d:DesignWidth="140">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
<c:BoolToBrushConverter x:Key="b2c"/>
</UserControl.Resources>
<Grid Name="grid">
<!--选中状态提醒-->
<Rectangle Stroke="#999" StrokeThickness="1"
StrokeDashArray="3,5"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}"/>
<Border CornerRadius="6" Background="White" Margin="3"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}">
<Border.Effect>
<DropShadowEffect BlurRadius="10"
Color="Gray"
ShadowDepth="0"
Opacity="0.4"/>
</Border.Effect>
</Border>
<Border CornerRadius="5" Background="White"
Margin="3" BorderBrush="#771f71e5" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="18"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="#771f71e5" CornerRadius="4,0,0,4">
<Ellipse Width="8" Height="8" Fill="{Binding IsRunning,Converter={StaticResource b2c}}"/>
</Border>
<TextBlock Text="加法" Grid.Column="1"
VerticalAlignment="Center" Margin="5,0"
Foreground="#555"/>
<TextBlock Text="{Binding Duration,StringFormat=\{0\}ms}" Grid.Column="1" FontSize="9"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5,0" Foreground="#888"/>
</Grid>
</Border>
<Grid Visibility="{Binding ElementName=grid,Path=IsMouseOver,Converter={StaticResource b2v}}">
<!--锚点对象-->
<!--上-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Top"
Stroke="#CCC" StrokeThickness="1"
Margin="0,-5,0,0"
Visibility="{Binding ShowAnchorT,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="T"/>
<!--下-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Bottom"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,0,-5"
Visibility="{Binding ShowAnchorB,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="B"/>
<!--左-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Left"
Stroke="#CCC" StrokeThickness="1"
Margin="-5,0,0,0"
Visibility="{Binding ShowAnchorL,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="L"/>
<!--右-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Right"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,-5,0"
Visibility="{Binding ShowAnchorR,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="R"/>
</Grid>
<Button Width="16" Height="16"
HorizontalAlignment="Right"
Content="&#xe660;"
Margin="10,0"
Background="#9F00"
Foreground="#FFF"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource DeleteElementButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
Command="{Binding DataContext.DeleteElementCommand,RelativeSource={RelativeSource AncestorType=ItemsControl,Mode=FindAncestor}}"
CommandParameter="{Binding}"/>
<ToggleButton Width="16" Height="16"
Tag="8"
Grid.Column="1"
HorizontalAlignment="Right"
Margin="28,0"
Content="&#xe7db;"
Foreground="White"
Background="#156FEE"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource ElementArgsButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
IsChecked="{Binding IsShowProperties}"/>
</Grid>
</b:NodeBase>

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VisionFrame.Base;
namespace LogicControl
{
/// <summary>
/// AddNode.xaml 的交互逻辑
/// </summary>
public partial class AddNode : NodeBase
{
public AddNode()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VisionFrame.Base;
namespace LogicControl
{
public class AddNodeModel : NodeModelBase
{
public AddNodeModel()
{
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "加数",
ArgType = "Any",
Direction = "输入"
});
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "累加值",
ArgType = "Any",
Direction = "输入",
ValueMode = 1
});
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "结果",
ArgType = "Any",
Direction = "输出"
});
}
public override void Execute(IFlowContext flowContext)
{
if (this.Arguments[0].ArgValue == null)
throw new Exception("参数未配置");
if (this.Arguments[1].ArgValue == null)
throw new Exception("参数未配置");
if (this.Arguments[2].ArgValue == null)
throw new Exception("参数未配置");
// 手动输入/下拉选择的差别处理
string org_value = this.Arguments[0].ArgValue.ToString();
if (this.Arguments[0].ValueMode == 0)
{
var am = flowContext.ArgumentList
.FirstOrDefault(a => a.ArgName == this.Arguments[0].ArgValue.ToString());
if (am != null)
org_value = (am.Value ?? 0).ToString();
}
// 累加值
string add_value = this.Arguments[1].ArgValue.ToString();
if (this.Arguments[1].ValueMode == 0)
{
var am = flowContext.ArgumentList
.FirstOrDefault(a => a.ArgName == this.Arguments[1].ArgValue.ToString());
if (am != null)
add_value = (am.Value ?? 0).ToString();
}
// 加法结果
string compare = org_value + "+" + add_value;
object result = new DataTable().Compute(compare, "");
var rm = flowContext.ArgumentList
.FirstOrDefault(a => a.ArgName == this.Arguments[2].ArgValue.ToString());
if (rm != null)
rm.Value = result;
}
}
}

View File

@@ -0,0 +1,88 @@
<b:NodeBase x:Class="LogicControl.DecisionNode"
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:LogicControl"
xmlns:b="clr-namespace:VisionFrame.Base;assembly=VisionFrame.Base"
xmlns:c="clr-namespace:VisionFrame.Base.Converter;assembly=VisionFrame.Base"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="100">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
<c:BoolToBrushConverter x:Key="b2c"/>
</UserControl.Resources>
<Grid Name="grid">
<!--选中状态提醒-->
<Rectangle Stroke="#999" StrokeThickness="1"
StrokeDashArray="3,5"
Visibility="{Binding IsSelected,Converter={StaticResource b2v}}"/>
<Path Data="M619.787898 44.781759l359.427055 359.500183a152.473125 152.473125 0 0 1 0 215.583104L619.787898 979.292101a152.473125 152.473125 0 0 1-215.656232 0L44.704611 619.791918a152.473125 152.473125 0 0 1 0-215.583104L404.204794 44.781759a152.473125 152.473125 0 0 1 215.656233 0z"
Fill="#AA1f71e5" Stretch="Fill" Margin="3"
Stroke="#1f71e5" StrokeThickness="1"/>
<TextBlock Text="判断" VerticalAlignment="Center" HorizontalAlignment="Center"
Foreground="#FFF"/>
<TextBlock Text="F" FontSize="10" VerticalAlignment="Center" HorizontalAlignment="Left"
Margin="15,0" Foreground="#FFF"/>
<TextBlock Text="T" FontSize="10" VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="15,0" Foreground="#FFF"/>
<Grid Visibility="{Binding ElementName=grid,Path=IsMouseOver,Converter={StaticResource b2v}}">
<!--锚点对象-->
<!--上-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Top"
Stroke="#CCC" StrokeThickness="1"
Margin="0,-5,0,0"
Visibility="{Binding ShowAnchorT,Converter={StaticResource b2v}}"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
Tag="T"/>
<!--左-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Left"
Stroke="#CCC" StrokeThickness="1"
Margin="-5,0,0,0"
Visibility="{Binding ShowAnchorL,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
Tag="L;F"/>
<!--右-->
<Ellipse Width="12" Height="12" Fill="#9FFF"
HorizontalAlignment="Right"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,-5,0"
Visibility="{Binding ShowAnchorR,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
Tag="R;T"/>
</Grid>
<Button Width="16" Height="16"
HorizontalAlignment="Center" VerticalAlignment="Bottom"
Content="&#xe660;"
Margin="20,0,0,0"
Background="#9F00"
Foreground="#FFF"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource DeleteElementButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
Command="{Binding DataContext.DeleteElementCommand,RelativeSource={RelativeSource AncestorType=ItemsControl,Mode=FindAncestor}}"
CommandParameter="{Binding}"/>
<ToggleButton Width="16" Height="16"
Tag="8"
Grid.Column="1"
HorizontalAlignment="Center" VerticalAlignment="Bottom"
Margin="0,0,20,0"
Content="&#xe7db;"
Foreground="White"
Background="#156FEE"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource ElementArgsButtonStyle}"
Visibility="{Binding ElementName=grid,
Path=IsMouseOver,
Converter={StaticResource b2v}}"
IsChecked="{Binding IsShowProperties}"/>
</Grid>
</b:NodeBase>

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VisionFrame.Base;
namespace LogicControl
{
/// <summary>
/// DecisionNode.xaml 的交互逻辑
/// </summary>
public partial class DecisionNode : NodeBase
{
public DecisionNode()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,68 @@
using System.Data;
using VisionFrame.Base;
namespace LogicControl
{
public class DecisionNodeModel : DecisionNodeModelBase
{
public DecisionNodeModel()
{
// 某个变量值 == 什么值 > < >= <= != 关系运算符
//
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "判断目标",
ArgType = "Any",
Direction = "输入"
});
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "判断方式",
ArgType = "String",
Direction = "输入",
ValueMode = 3
});
this.Arguments.Add(new VisionFrame.Base.Models.NodeArgModel
{
ArgName = "判断值",
ArgType = "Any",
Direction = "输入",
ValueMode = 1
});
}
public override bool Decision(IFlowContext context)
{
//int temp = 1;
//return new DataTable().Compute("1<=2", "").ToString() == "True";
if (this.Arguments[0].ArgValue == null)
throw new Exception("判断目标参数未配置");
if (this.Arguments[1].ArgValue == null)
throw new Exception("判断方式参数未配置");
if (this.Arguments[2].ArgValue == null)
throw new Exception("判断值参数未配置");
string org_value = "";
var am = context.ArgumentList
.FirstOrDefault(a => a.ArgName == this.Arguments[0].ArgValue.ToString());
if (am != null)
org_value = am.Value.ToString();
string value = this.Arguments[2].ArgValue.ToString();
if (this.Arguments[2].ValueMode == 0)
{
am = context.ArgumentList
.FirstOrDefault(a => a.ArgName == this.Arguments[0].ArgValue.ToString());
if (am != null)
value = am.Value.ToString();
}
string compare = org_value + this.Arguments[1].ArgValue.ToString() + value;
// "0x5235443==32432"
// "1==2"
return new DataTable().Compute(compare, "").ToString() == "True";
}
}
}

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\VisionFrame.Base\VisionFrame.Base.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy $(TargetPath) $(SolutionDir)VisionFrame\bin\Debug\net9.0-windows\Activities\$(TargetFileName) /y" />
</Target>
</Project>

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;
namespace VisionFrame.Base.Converter
{
public class BoolToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (bool.Parse(value.ToString()))
return Brushes.LawnGreen;
else return Brushes.ForestGreen;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace VisionFrame.Base.Converter
{
public class LocationConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double.TryParse(values[0].ToString(), out double w);
double.TryParse(values[1].ToString(), out double h);
double w1 = w * 2;
double h1 = h * 2;
return new Thickness((w - w1) / 2, (h - h1) / 2, 0, 0);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace VisionFrame.Base.Converter
{
public class NodeJsonConverter : JsonConverter<NodeModelBase>
{
class TypeInfoTemp
{
public string TypeInfo { get; set; }
}
// 字符串到对象实例的转换过程
public override NodeModelBase? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string json = reader.GetString();// 包含程序信息
TypeInfoTemp ti = System.Text.Json.JsonSerializer.Deserialize<TypeInfoTemp>(json);
string[] type_info = ti.TypeInfo.Split(";");
Assembly assembly = Assembly.GetEntryAssembly();// 取当前执行的程序集
if (assembly.GetName().Name != type_info[0])
{
assembly = Assembly.LoadFile(Environment.CurrentDirectory + "/Activities/" + type_info[0] + ".dll");
}
// 最终要执的节点Model
Type type = assembly.GetType(type_info[1]);
NodeModelBase node = (NodeModelBase)System.Text.Json.JsonSerializer.Deserialize(json, type);
return node;
}
// 对象到Json字符串的转换过程
public override void Write(Utf8JsonWriter writer, NodeModelBase value, JsonSerializerOptions options)
{
// value--->Json
// writer--写
// 准备类型的记录
string type = value.GetType().FullName;
string assembly = value.GetType().Assembly.GetName().Name;
value.TypeInfo = assembly + ";" + type;
// 如果直接放value 会循环触发这个方法
// 用一个动态变量接收,
dynamic temp = value;
string json = System.Text.Json.JsonSerializer.Serialize(temp);
writer.WriteStringValue(json);
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace VisionFrame.Base.Converter
{
public class SizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double r = 2;
if (parameter != null)
{
double.TryParse(parameter.ToString(), out r);
}
// 实际的宽高值
// 将这个值乘2返回出去
if (value != null && double.TryParse(value.ToString(), out double new_value))
return new_value * r;
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace VisionFrame.Base.Converter
{
public class StringToNodeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string[] _info = value.ToString().Split(";");
Assembly assembly = Assembly.GetEntryAssembly();
Type type = assembly.GetType(_info[0]);
if (_info.Length == 2)
{
assembly =
Assembly.LoadFile(Environment.CurrentDirectory + "/Activities/" + _info[0] + ".dll");
if (assembly == null) return null;
type = assembly.GetType(_info[1]);
if (type == null) return null;
}
object instance = Activator.CreateInstance(type);
Binding binding = new Binding("DataContext.AnchorDownCommand");
binding.RelativeSource = new RelativeSource() { AncestorType = typeof(ItemsControl) };
(instance as NodeBase).SetBinding(NodeBase.AnchorDownCommandProperty, binding);
binding = new Binding("DataContext.AnchorUpCommand");
binding.RelativeSource = new RelativeSource() { AncestorType = typeof(ItemsControl) };
(instance as NodeBase).SetBinding(NodeBase.AnchorUpCommandProperty, binding);
return instance;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisionFrame.Base
{
public class DecisionNodeModelBase : NodeModelBase
{
public virtual bool Decision(IFlowContext context) { return false; }
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VisionFrame.Base.Models;
namespace VisionFrame.Base
{
public interface IFlowContext
{
public ObservableCollection<FlowArgModel> ArgumentList { get; set; }
void ShowImage(IntPtr imagePtr);
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisionFrame.Base.Models
{
public class FlowArgModel
{
public string ArgName { get; set; }
public string ArgType { get; set; }
public object Value { get; set; }
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisionFrame.Base.Models
{
public class NodeArgModel : INotifyPropertyChanged
{
public string ArgName { get; set; }
public string ArgType { get; set; }
public string Direction { get; set; }
private object _argValue;
public object ArgValue
{
get { return _argValue; }
set
{
_argValue = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ArgValue"));
}
}
// 数据的获取方式
// 0:选择流程参数,下拉列表
// 1输入框
// 2选择目录
public int ValueMode { get; set; } = 0;
public event PropertyChangedEventHandler? PropertyChanged;
}
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Shapes;
namespace VisionFrame.Base
{
public class NodeBase : UserControl
{
//public ICommand AnchorDownCommand { get; set; }
//public ICommand AnchorUpCommand { get; set; }
public ICommand AnchorDownCommand
{
get { return (ICommand)GetValue(AnchorDownCommandProperty); }
set { SetValue(AnchorDownCommandProperty, value); }
}
public static readonly DependencyProperty AnchorDownCommandProperty =
DependencyProperty.Register("AnchorDownCommand",
typeof(ICommand), typeof(NodeBase), new PropertyMetadata(null));
public ICommand AnchorUpCommand
{
get { return (ICommand)GetValue(AnchorUpCommandProperty); }
set { SetValue(AnchorUpCommandProperty, value); }
}
public static readonly DependencyProperty AnchorUpCommandProperty =
DependencyProperty.Register("AnchorUpCommand",
typeof(ICommand), typeof(NodeBase), new PropertyMetadata(null));
public void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.AnchorDownCommand?.Execute(
(this.DataContext as NodeModelBase).NodeId + ";" + (sender as Ellipse).Tag.ToString()
);
e.Handled = true;
}
public void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.AnchorUpCommand?.Execute(
(this.DataContext as NodeModelBase).NodeId + ";" + (sender as Ellipse).Tag.ToString()
);
e.Handled = true;
}
}
}

View File

@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Windows.Input;
using VisionFrame.Base.Converter;
using VisionFrame.Base.Models;
namespace VisionFrame.Base
{
// 解决序列化时多态对象的类型区分
//[JsonPolymorphic(UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)]
//[JsonDerivedType(typeof(DecisionNodeModelBase), typeDiscriminator: "decision")]
// 对这类对象进么Json序列的时候 会执行Converter中的相关方法
[JsonConverter(typeof(NodeJsonConverter))]
public class NodeModelBase : INotifyPropertyChanged
{
public string TypeInfo { get; set; }
public List<int> FlowLevel { get; set; } = new List<int>();
// 每个节点实例 唯一编号
public string NodeId { get; set; }
public NodeModelBase()
{
NodeId = Guid.NewGuid().ToString();
}
public string NodeName { get; set; }
public string TargetNodeObject { get; set; }
public bool IsStart { get; set; } = false;
public bool IsDecision { get; set; } = false;
private double _x;
public double X
{
get { return _x; }
set
{
_x = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(X)));
}
}
private double _y;
public double Y
{
get { return _y; }
set
{
_y = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Y)));
}
}
public double W { get; set; }
public double H { get; set; }
private bool _isSelected = false;
public event PropertyChangedEventHandler? PropertyChanged;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSelected)));
}
}
private bool _isShowProperties;
public bool IsShowProperties
{
get { return _isShowProperties; }
set
{
if (!IsSelected) return;
_isShowProperties = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsShowProperties)));
}
}
private bool _isRunning;
public bool IsRunning
{
get { return _isRunning; }
set
{
_isRunning = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRunning)));
}
}
private long _duration;
public long Duration
{
get { return _duration; }
set
{
_duration = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Duration)));
}
}
public List<NodeArgModel> Arguments { get; set; } = new List<NodeArgModel>();
public bool ShowAnchorT { get; set; } = true;
public bool ShowAnchorB { get; set; } = true;
public bool ShowAnchorL { get; set; } = true;
public bool ShowAnchorR { get; set; } = true;
public void SetAnchorShow(string anchor, bool show)
{
PropertyInfo pi = this.GetType().GetProperty("ShowAnchor" + anchor);
if (pi != null)
{
pi.SetValue(this, show);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ShowAnchor" + anchor));
}
}
//public List<>
public virtual void Execute(IFlowContext flowContext) { }
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using VisionFrame.Base.Models;
namespace VisionFrame.Base.TemplateSelector
{
public class NodeArgTemplateSelector : DataTemplateSelector
{
public DataTemplate DropdownTempalte { get; set; }
public DataTemplate TextBoxTempalte { get; set; }
public DataTemplate SelectFolderTempalte { get; set; }
public DataTemplate CompareOpratorTempalte { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var model = item as NodeArgModel;
if (model.ValueMode == 0)
return DropdownTempalte;
else if (model.ValueMode == 1)
return TextBoxTempalte;
else if (model.ValueMode == 2)
return SelectFolderTempalte;
else if (model.ValueMode == 3)
return CompareOpratorTempalte;
return null;
}
}
}

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>

51
VisionFrame.sln Normal file
View File

@@ -0,0 +1,51 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35527.113
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisionFrame", "VisionFrame\VisionFrame.csproj", "{35EB08A7-6C9B-495F-97B1-031CF800D3F6}"
ProjectSection(ProjectDependencies) = postProject
{103F3E6D-0F03-4AD7-A971-6296FB243500} = {103F3E6D-0F03-4AD7-A971-6296FB243500}
{193F9B5C-0452-44B9-9F36-C75D44A52735} = {193F9B5C-0452-44B9-9F36-C75D44A52735}
{19BEA527-EDC6-4A18-A361-017EE14784C1} = {19BEA527-EDC6-4A18-A361-017EE14784C1}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageCapture", "ImageCapture\ImageCapture.csproj", "{19BEA527-EDC6-4A18-A361-017EE14784C1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisionFrame.Base", "VisionFrame.Base\VisionFrame.Base.csproj", "{11D768D7-9668-4916-835A-1CCAA7F38AED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcess", "ImageProcess\ImageProcess.csproj", "{193F9B5C-0452-44B9-9F36-C75D44A52735}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogicControl", "LogicControl\LogicControl.csproj", "{103F3E6D-0F03-4AD7-A971-6296FB243500}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{35EB08A7-6C9B-495F-97B1-031CF800D3F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{35EB08A7-6C9B-495F-97B1-031CF800D3F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{35EB08A7-6C9B-495F-97B1-031CF800D3F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{35EB08A7-6C9B-495F-97B1-031CF800D3F6}.Release|Any CPU.Build.0 = Release|Any CPU
{19BEA527-EDC6-4A18-A361-017EE14784C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19BEA527-EDC6-4A18-A361-017EE14784C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19BEA527-EDC6-4A18-A361-017EE14784C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19BEA527-EDC6-4A18-A361-017EE14784C1}.Release|Any CPU.Build.0 = Release|Any CPU
{11D768D7-9668-4916-835A-1CCAA7F38AED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11D768D7-9668-4916-835A-1CCAA7F38AED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11D768D7-9668-4916-835A-1CCAA7F38AED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11D768D7-9668-4916-835A-1CCAA7F38AED}.Release|Any CPU.Build.0 = Release|Any CPU
{193F9B5C-0452-44B9-9F36-C75D44A52735}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{193F9B5C-0452-44B9-9F36-C75D44A52735}.Debug|Any CPU.Build.0 = Debug|Any CPU
{193F9B5C-0452-44B9-9F36-C75D44A52735}.Release|Any CPU.ActiveCfg = Release|Any CPU
{193F9B5C-0452-44B9-9F36-C75D44A52735}.Release|Any CPU.Build.0 = Release|Any CPU
{103F3E6D-0F03-4AD7-A971-6296FB243500}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{103F3E6D-0F03-4AD7-A971-6296FB243500}.Debug|Any CPU.Build.0 = Debug|Any CPU
{103F3E6D-0F03-4AD7-A971-6296FB243500}.Release|Any CPU.ActiveCfg = Release|Any CPU
{103F3E6D-0F03-4AD7-A971-6296FB243500}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

28
VisionFrame/App.xaml Normal file
View File

@@ -0,0 +1,28 @@
<Application x:Class="VisionFrame.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VisionFrame"
StartupUri="Views/MainView.xaml">
<Application.Resources>
<ResourceDictionary>
<FontFamily x:Key="Iconfont">./Assets/Fonts/#iconfont</FontFamily>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0" x:Key="lgb">
<GradientStop Color="#bbd7ff" Offset="0"/>
<GradientStop Color="#0FFF" Offset="1"/>
</LinearGradientBrush>
<DropShadowEffect BlurRadius="10" ShadowDepth="0" Direction="0" Color="#409EFE" Opacity="0.5"
x:Key="dse"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="./Assets/Styles/ButtonStyles.xaml"/>
<ResourceDictionary Source="./Assets/Styles/TabControlStyles.xaml"/>
<ResourceDictionary Source="./Assets/Styles/ComboBoxStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

14
VisionFrame/App.xaml.cs Normal file
View File

@@ -0,0 +1,14 @@
using System.Configuration;
using System.Data;
using System.Windows;
namespace VisionFrame
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,121 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button">
<Setter Property="Width" Value="50"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#1777FF"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="5">
<Border Background="Transparent" Name="bor">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center" Margin="10,5"/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bor" Property="Background" Value="#1000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button" x:Key="TitleButtonStyle">
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
<Setter Property="Margin" Value="0,5"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="FontFamily" Value="{DynamicResource Iconfont}"/>
<Setter Property="Foreground" Value="#888"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center" Margin="10,5"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1000"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="Button" x:Key="DeleteElementButtonStyle">
<Setter Property="Background" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="20">
<Border Background="Transparent" Name="border" CornerRadius="20">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#2000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button" x:Key="ToolButtonStyle">
<Setter Property="Margin" Value="3,2"/>
<Setter Property="Width" Value="24"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontFamily" Value="{DynamicResource Iconfont}"/>
<Setter Property="Foreground" Value="#888"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="5">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#4FFF"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="ToggleButton" x:Key="ElementArgsButtonStyle">
<Setter Property="Background" Value="#156FEE"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Background="{TemplateBinding Background}" CornerRadius="20">
<Border Background="Transparent" Name="border" CornerRadius="20">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#2000"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="border" Property="Background" Value="#2000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,158 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="TextBox.Static.Background" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="ComboBox.Static.Border" Color="#FFACACAC"/>
<SolidColorBrush x:Key="ComboBox.Static.Glyph" Color="#FF606060"/>
<Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="ClickMode" Value="Press"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="templateRoot"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="#DDDDDD"
CornerRadius="3">
<Border x:Name="splitBorder" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"
SnapsToDevicePixels="true" Margin="0" HorizontalAlignment="Right"
BorderThickness="1" BorderBrush="Transparent">
<Path Data="M0 0 4 4 8 0" Stroke="#CCC" StrokeThickness="1"
VerticalAlignment="Center" Name="path"
Width="8" HorizontalAlignment="Center"
RenderTransformOrigin="0.5,0.5"/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="templateRoot" Value="green"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="templateRoot" Value="green"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="path" Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="180"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="ComboBoxTemplate" TargetType="{x:Type ComboBox}">
<Grid x:Name="templateRoot" SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
</Grid.ColumnDefinitions>
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2"
IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}"
Placement="Bottom" VerticalOffset="1">
<Border x:Name="dropDownBorder"
BorderBrush="#DDD"
BorderThickness="1" CornerRadius="5"
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
<ScrollViewer x:Name="DropDownScrollViewer"
Background="Transparent" BorderThickness="0">
<Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}"
Height="{Binding ActualHeight, ElementName=dropDownBorder}"
Width="{Binding ActualWidth, ElementName=dropDownBorder}"
RadiusX="7" RadiusY="7"/>
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="3"/>
</Grid>
</ScrollViewer>
</Border>
</Popup>
<ToggleButton x:Name="toggleButton" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="White" Grid.ColumnSpan="2"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ComboBoxToggleButton}"/>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Content="{TemplateBinding SelectionBoxItem}"
ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
IsHitTestVisible="false" Margin="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<!--<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
<Setter Property="Margin" TargetName="shadow" Value="0,0,5,5"/>
<Setter Property="Background" TargetName="shadow" Value="#71000000"/>
</Trigger>-->
<Trigger Property="HasItems" Value="false">
<Setter Property="Height" TargetName="dropDownBorder" Value="95"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsGrouping" Value="true"/>
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</MultiTrigger>
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
<Setter Property="Canvas.Top" TargetName="opaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
<Setter Property="Canvas.Left" TargetName="opaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#333"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Padding" Value="6,3,5,3"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template" Value="{StaticResource ComboBoxTemplate}"/>
</Style>
<Style TargetType="ComboBoxItem">
<Setter Property="Height" Value="30"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Border Background="White" BorderBrush="Transparent" BorderThickness="1" CornerRadius="3"
Margin="1" Name="border">
<ContentPresenter VerticalAlignment="Center" Margin="3"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#111F71E5"/>
<Setter TargetName="border" Property="BorderBrush" Value="#551F71E5"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="border" Property="Background" Value="#1F71E5"/>
<Setter TargetName="border" Property="BorderBrush" Value="#1F71E5"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,298 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TabItem" x:Key="NormalTabStyle">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="#1f71e5"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Background="{TemplateBinding Background}" Height="26">
<ContentPresenter ContentSource="Header"
VerticalAlignment="Center"
Grid.Column="1"
Margin="10,0"
x:Name="header"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1000"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#1f71e5"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TabItem" x:Key="FlowTabStyle">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="#1f71e5"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Background="{TemplateBinding Background}" Height="26">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick"
Command="{Binding EditTitleCommand}"/>
</Grid.InputBindings>
<TextBlock Text="&#xe610;"
FontFamily="{DynamicResource Iconfont}"
VerticalAlignment="Center"
Margin="5,0"/>
<ContentPresenter ContentSource="Header"
VerticalAlignment="Center"
Grid.Column="1"
Margin="3,0,0,0"
x:Name="header"/>
<TextBox Grid.Column="1"
Text="{Binding Title}"
Name="m_header"
Visibility="{Binding TitleEditVisible}"
VerticalContentAlignment="Center"
Background="#DFFF"
BorderThickness="0"
Foreground="#1f71e5"
Margin="0,2">
<TextBox.InputBindings>
<KeyBinding Key="Return"
Command="{Binding AcceptTitleCommand}"/>
</TextBox.InputBindings>
</TextBox>
<Button Content="&#xe660;" FontFamily="{DynamicResource Iconfont}"
Grid.Column="2" FontSize="10" Style="{x:Null}"
Visibility="Hidden"
Width="20" Height="20" Margin="5,0" Name="button"
Command="{Binding DataContext.CloseFlowTabCommand,RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="Transparent" Name="border">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background"
Value="#2000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1000"/>
<Setter TargetName="button" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#1f71e5"/>
<Setter Property="Foreground" Value="White"/>
<Setter TargetName="button" Property="Visibility" Value="Visible"/>
<Setter TargetName="button" Property="Foreground" Value="white"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ToggleButton" x:Key="TabListButtonStyle">
<Setter Property="Foreground" Value="#888"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1000"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="#1000"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="Button" x:Key="TabListItemButtonStyle">
<Setter Property="FontSize" Value="12"/>
<Setter Property="Margin" Value="3,2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Height="30" Background="Transparent" Name="border" CornerRadius="5">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Left"
Margin="15,0,0,0"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#1000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="RepeatButton">
<Setter Property="Foreground" Value="#888"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Border Background="{TemplateBinding Background}" Margin="0,-3">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1000"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="#CCC"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="ScrollBar" x:Key="TabScrollBarStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<RepeatButton FontFamily="{DynamicResource Iconfont}"
Command="ScrollBar.LineLeftCommand"
Content="&#xe603;" />
<RepeatButton FontFamily="{DynamicResource Iconfont}"
Grid.Column="1"
Command="ScrollBar.LineRightCommand"
Content="&#xe602;" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ScrollViewer" x:Key="TabScrollViewerStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="44"/>
</Grid.ColumnDefinitions>
<Border Width="1" Height="14" Background="#BBB" HorizontalAlignment="Right"/>
<ScrollBar x:Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.ColumnSpan="2"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Grid.Column="1"
Style="{StaticResource TabScrollBarStyle}"
Margin="3,-3" Background="Red"/>
<ScrollContentPresenter CanContentScroll="{TemplateBinding CanContentScroll}"
Margin="5,0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid x:Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true"
KeyboardNavigation.TabNavigation="Local">
<Grid.RowDefinitions>
<RowDefinition Height="26"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="28"/>
</Grid.ColumnDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Visible"
Style="{StaticResource TabScrollViewerStyle}">
<TabPanel x:Name="headerPanel" Background="Transparent"
IsItemsHost="true" Margin="2,2,2,0"
KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
</ScrollViewer>
<ToggleButton Grid.Column="1" Name="tb_tabs"
Style="{StaticResource TabListButtonStyle}"
Content="&#xe600;"
FontFamily="{DynamicResource Iconfont}"/>
<Border x:Name="contentPanel" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="2" KeyboardNavigation.DirectionalNavigation="Contained"
Grid.Row="1" KeyboardNavigation.TabIndex="2"
KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost"
ContentSource="SelectedContent"
Margin="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<Popup StaysOpen="False" IsOpen="{Binding ElementName=tb_tabs,Path=IsChecked}"
PlacementTarget="{Binding ElementName=tb_tabs}"
AllowsTransparency="True"
HorizontalOffset="-130"
VerticalOffset="3">
<Border Width="160" CornerRadius="5" Background="White"
Margin="3">
<Border.Effect>
<DropShadowEffect BlurRadius="5" ShadowDepth="0" Opacity="0.3" Color="Gray"/>
</Border.Effect>
<StackPanel Margin="0,3">
<Button Content="关闭当前流程" Style="{StaticResource TabListItemButtonStyle}"
Command="{Binding CloseFlowTabCommand}"
CommandParameter="1"/>
<Button Content="关闭其他流程" Style="{StaticResource TabListItemButtonStyle}"
Command="{Binding CloseFlowTabCommand}"
CommandParameter="2"/>
<Border Height="1" Background="#DDD"/>
<ItemsControl ItemsSource="{Binding FlowTabList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Title}"
Style="{StaticResource TabListItemButtonStyle}"
Command="{Binding SelectCommand}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisionFrame.Models
{
internal class CatalogModel
{
public bool IsSelected { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Icon { get; set; }
public List<ComponentModel> Components { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisionFrame.Models
{
internal class ComponentModel
{
public string Icon { get; set; }
public string Name { get; set; }
public string TargetNode { get; set; }
public string TargetModel { get; set; }
public double W { get; set; }
public double H { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Zhaoxi.VisionFrame.Models
{
public class FlowArgModel
{
public string ArgName { get; set; }
public string ArgType { get; set; }
public object Value { get; set; }
}
}

View File

@@ -0,0 +1,56 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisionFrame.Models
{
public class LinkModel : ObservableObject
{
public string StartAnchor { get; set; }
private string _endAnchor;
public string EndAnchor
{
get { return _endAnchor; }
set { SetProperty<string>(ref _endAnchor, value); }
}
public string StartId { get; set; }
public string EndId { get; set; }
private double _startX;
public double StartX
{
get { return _startX; }
set { SetProperty<double>(ref _startX, value); }
}
private double _startY;
public double StartY
{
get { return _startY; }
set { SetProperty<double>(ref _startY, value); }
}
private double _endX;
public double EndX
{
get { return _endX; }
set { SetProperty<double>(ref _endX, value); }
}
private double _endY;
public double EndY
{
get { return _endY; }
set { SetProperty<double>(ref _endY, value); }
}
public string Condition { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisionFrame.Models
{
public class LogModel
{
public DateTime Time { get; set; }
public string NodeName { get; set; }
public string LogMessage { get; set; }
}
}

View File

@@ -0,0 +1,64 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Zhaoxi.VisionFrame.Base;
namespace Zhaoxi.VisionFrame.Models
{
public class NodeModel : ObservableObject
{
// 每个节点实例 唯一编号
public string NodeId { get; } = Guid.NewGuid().ToString();
public object TargetNodeObject { get; set; }
private double _x;
public double X
{
get { return _x; }
set { SetProperty<double>(ref _x, value); }
}
private double _y;
public double Y
{
get { return _y; }
set { SetProperty<double>(ref _y, value); }
}
public double W { get; set; }
public double H { get; set; }
private bool _isSelected = false;
public bool IsSelected
{
get { return _isSelected; }
set { SetProperty<bool>(ref _isSelected, value); }
}
public bool ShowAnchorT { get; set; } = true;
public bool ShowAnchorB { get; set; } = true;
public bool ShowAnchorL { get; set; } = true;
public bool ShowAnchorR { get; set; } = true;
public void SetAnchorShow(string anchor, bool show)
{
PropertyInfo pi = this.GetType().GetProperty("ShowAnchor" + anchor);
if (pi != null)
{
pi.SetValue(this, show);
this.OnPropertyChanged("ShowAnchor" + anchor);
}
}
}
}

View File

@@ -0,0 +1,26 @@
<UserControl x:Class="VisionFrame.Nodes.LineNode"
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:VisionFrame.Nodes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
</UserControl.Resources>
<Grid>
<Button Width="14" Height="14"
Margin="{Binding CancelLocation,RelativeSource={RelativeSource AncestorType=UserControl}}"
Foreground="White"
Content="&#xe660;"
FontFamily="{DynamicResource Iconfont}"
Style="{DynamicResource DeleteElementButtonStyle}"
Visibility="{Binding RelativeSource={RelativeSource AncestorType=UserControl},
Path=IsMouseOver,
Converter={StaticResource b2v}}"
Command="{Binding DataContext.DeleteElementCommand,RelativeSource={RelativeSource AncestorType=ItemsControl,Mode=FindAncestor}}"
CommandParameter="{Binding}"/>
</Grid>
</UserControl>

View File

@@ -0,0 +1,676 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace VisionFrame.Nodes
{
/// <summary>
/// LineNode.xaml 的交互逻辑
/// </summary>
public partial class LineNode : UserControl, INotifyPropertyChanged
{
public double X1
{
get { return (double)GetValue(X1Property); }
set { SetValue(X1Property, value); }
}
public static readonly DependencyProperty X1Property =
DependencyProperty.Register("X1", typeof(double),
typeof(LineNode),
new PropertyMetadata(0.0, OnPropertyChanged));
public double Y1
{
get { return (double)GetValue(Y1Property); }
set { SetValue(Y1Property, value); }
}
public static readonly DependencyProperty Y1Property =
DependencyProperty.Register("Y1", typeof(double),
typeof(LineNode),
new PropertyMetadata(0.0, OnPropertyChanged));
public double X2
{
get { return (double)GetValue(X2Property); }
set { SetValue(X2Property, value); }
}
public static readonly DependencyProperty X2Property =
DependencyProperty.Register("X2", typeof(double),
typeof(LineNode),
new PropertyMetadata(0.0, OnPropertyChanged));
public double Y2
{
get { return (double)GetValue(Y2Property); }
set { SetValue(Y2Property, value); }
}
public static readonly DependencyProperty Y2Property =
DependencyProperty.Register("Y2", typeof(double),
typeof(LineNode),
new PropertyMetadata(0.0, OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as LineNode).InvalidateVisual();
}
public string StartAnchor
{
get { return (string)GetValue(StartAnchorProperty); }
set { SetValue(StartAnchorProperty, value); }
}
public static readonly DependencyProperty StartAnchorProperty =
DependencyProperty.Register("StartAnchor", typeof(string),
typeof(LineNode),
new PropertyMetadata(""));
public string EndAnchor
{
get { return (string)GetValue(EndAnchorProperty); }
set { SetValue(EndAnchorProperty, value); }
}
public static readonly DependencyProperty EndAnchorProperty =
DependencyProperty.Register("EndAnchor", typeof(string),
typeof(LineNode),
new PropertyMetadata(""));
public event PropertyChangedEventHandler? PropertyChanged;
public Thickness CancelLocation { get; set; }
public LineNode()
{
InitializeComponent();
}
protected override void OnRender(DrawingContext drawingContext)
{
List<Point> points = new List<Point>();
// 起始与终止锚点坐标
Point start = new Point(X1, Y1);
Point end = new Point(X2, Y2);
//
if (EndAnchor == "N")
{
if (X2 < X1)
end += new Vector(2, 0);
else if (X2 > X1)
end += new Vector(-2, 0);
if (Y2 > Y1)
end += new Vector(0, -2);
else if (Y2 < Y1)
end += new Vector(0, 2);
}
// 起始延伸坐标
Point start_extend = new Point(X1, Y1);
if (StartAnchor == "T")
start_extend = new Point(X1, Y1 - 20);
else if (StartAnchor == "B")
start_extend = new Point(X1, Y1 + 20);
else if (StartAnchor == "L")
start_extend = new Point(X1 - 20, Y1);
else if (StartAnchor == "R")
start_extend = new Point(X1 + 20, Y1);
// 终点延伸坐标
Point end_extend = new Point(end.X, end.Y);
if (EndAnchor == "T")
end_extend = new Point(end.X, end.Y - 20);
else if (EndAnchor == "B")
end_extend = new Point(end.X, end.Y + 20);
else if (EndAnchor == "L")
end_extend = new Point(end.X - 20, end.Y);
else if (EndAnchor == "R")
end_extend = new Point(end.X + 20, end.Y);
// 添加第一点
points.Add(start);
// 添加延伸点(针对第一点),起点是哪个锚点
points.Add(start_extend);
// 添加动态点
// 锚点名称 TBLR 反射
MethodInfo mi = this.GetType().GetMethod(StartAnchor + "2" + EndAnchor,
BindingFlags.NonPublic | BindingFlags.Instance);
if (mi == null) return;
Point[] ps = (Point[])mi.Invoke(this, new object[] {
start_extend,
end_extend
});
points.AddRange(ps);
//points.AddRange(this.B2T(new Point(X1, Y1 + 20), new Point(X2, Y2 - 20)));
// 添加一个延伸点(针对最终点),终点是哪个锚点
points.Add(end_extend);
// 添加最终点
points.Add(end);
//StreamGeometry geometry = new StreamGeometry();
//using (StreamGeometryContext ctx = geometry.Open())
//{
// Point first = points.FirstOrDefault();
// ctx.BeginFigure(first, false, false);
// ctx.PolyLineTo(points, true, true);
//}
var geometry = GetBrokenGeometry(points.ToArray(), false, false);
if (EndAnchor != "N")
{
//points[points.Count - 2];// 终延
//points[points.Count - 1];// 终
Point[] arrow_points = this.GetArrowPoints(points[points.Count - 2], points[points.Count - 1]);
var arrow_geo = this.GetBrokenGeometry(arrow_points, true, true);
PathGeometry path = PathGeometry.CreateFromGeometry(geometry);
// 整合
path.AddGeometry(arrow_geo);
path.Freeze();
geometry = path;
}
//drawingContext.DrawLine(new Pen(Brushes.Red, 2), new Point(X1, Y1), new Point(X2, Y2));
drawingContext.DrawGeometry(
Brushes.Orange,
new Pen(Brushes.Orange, 2),
geometry);
if (ps.Length == 2)
{
var p = ps[0] + (ps[1] - ps[0]) / 2;
CancelLocation = new Thickness(p.X - 7, p.Y - 7, 0, 0);
}
else if (ps.Length == 1)
CancelLocation = new Thickness(ps[0].X - 7, ps[0].Y - 7, 0, 0);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CancelLocation)));
}
private Geometry GetBrokenGeometry(Point[] points, bool isFill, bool isClose)
{
StreamGeometry geometry = new StreamGeometry();
using (StreamGeometryContext ctx = geometry.Open())
{
Point first = points.FirstOrDefault();
ctx.BeginFigure(first, isFill, isClose);
ctx.PolyLineTo(points, true, true);
}
return geometry;
}
private Point[] GetArrowPoints(Point start, Point end)
{
Vector vec = start - end;
// 规范化 单位化
vec.Normalize();
vec *= 8;
Matrix matrix = new Matrix();
matrix.Rotate(20);
Point p1 = end + vec * matrix;
matrix.Rotate(-40);
Point p2 = end + vec * matrix;
return new Point[] { p1, end, p2 };
}
#region
// 下对上
private Point[] B2T(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (end.Y > start.Y)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, start.Y + cy));
}
else if (end.Y < start.Y)
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(start.X + cx, end.Y));
}
return ps.ToArray();
}
// 下对左
private Point[] B2L(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.X > end.X)
{
ps.Add(new Point(end.X, start.Y));
}
else if (start.Y < end.Y)
{
ps.Add(new Point(start.X, end.Y));
}
else
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
return ps.ToArray();
}
// 下对右
private Point[] B2R(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.X < end.X)
{
ps.Add(new Point(end.X, start.Y));
}
else if (start.Y < end.Y)
{
ps.Add(new Point(start.X, end.Y));
}
else
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
return ps.ToArray();
}
// 下对下
private Point[] B2B(Point start, Point end)
{
double cy = end.Y - start.Y;
List<Point> ps = new List<Point>();
if (start.Y > end.Y)
{
ps.Add(new Point(end.X, start.Y));
}
else if (start.Y < end.Y)
{
ps.Add(new Point(start.X, end.Y));
}
return ps.ToArray();
}
// 下对空
private Point[] B2N(Point start, Point end)
{
List<Point> ps = new List<Point>();
if (start.Y > end.Y)
{
ps.Add(new Point(end.X, start.Y));
}
else
{
ps.Add(new Point(start.X, end.Y));
}
return ps.ToArray();
}
#endregion
#region
// From右锚点To上锚点
private Point[] R2T(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
List<Point> ps = new List<Point>();
if (start.X > end.X)
{
ps.Add(new Point(start.X, end.Y));
}
else if (start.Y < end.Y)
{
ps.Add(new Point(end.X, start.Y));
}
else
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
return ps.ToArray();
}
// From右锚点To左锚点
private Point[] R2L(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.X > end.X)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, end.Y - cy));
}
else
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
return ps.ToArray();
}
// From右锚点To右锚点
private Point[] R2R(Point start, Point end)
{
List<Point> ps = new List<Point>();
if (start.X > end.X)
{
ps.Add(new Point(start.X, end.Y));
}
else
{
ps.Add(new Point(end.X, start.Y));
}
return ps.ToArray();
}
// From右锚点To下锚点
private Point[] R2B(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.X > end.X && start.Y > end.Y)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, start.Y + cy));
}
else if (start.X < end.X && start.Y < end.Y)
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
else if (start.X < end.X)
{
ps.Add(new Point(end.X, start.Y));
}
else
{
ps.Add(new Point(start.X, end.Y));
}
return ps.ToArray();
}
// Fromd右锚点To NULL
private Point[] R2N(Point start, Point end)
{
List<Point> ps = new List<Point>();
if (start.X > end.X)
{
ps.Add(new Point(start.X, end.Y));
}
else
{
ps.Add(new Point(end.X, start.Y));
}
return ps.ToArray();
}
#endregion
#region
// From左锚点To上锚点
private Point[] L2T(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.X > end.X && start.Y > end.Y)
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
else if (start.X < end.X && start.Y < end.Y)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, end.Y - cy));
}
else if (start.X < end.X)
{
ps.Add(new Point(start.X, end.Y));
}
else
{
ps.Add(new Point(end.X, start.Y));
}
return ps.ToArray();
}
// From左锚点To左锚点
private Point[] L2L(Point start, Point end)
{
List<Point> ps = new List<Point>();
if (start.X > end.X)
{
ps.Add(new Point(end.X, start.Y));
}
else
{
ps.Add(new Point(start.X, end.Y));
}
return ps.ToArray();
}
// From左锚点To右锚点
private Point[] L2R(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.X < end.X)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, start.Y + cy));
}
else
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(start.X + cx, end.Y));
}
return ps.ToArray();
}
// From左锚点To下锚点
private Point[] L2B(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.X < end.X && start.Y > end.Y)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, end.Y - cy));
}
else if (start.X > end.X && start.Y < end.Y)
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
else if (start.X > end.X)
{
ps.Add(new Point(end.X, start.Y));
}
else
{
ps.Add(new Point(start.X, end.Y));
}
return ps.ToArray();
}
// Fromd左锚点To NULL
private Point[] L2N(Point start, Point end)
{
List<Point> ps = new List<Point>();
if (start.X > end.X)
{
ps.Add(new Point(end.X, start.Y));
}
else
{
ps.Add(new Point(start.X, end.Y));
}
return ps.ToArray();
}
#endregion
#region
// From上锚点To上锚点
private Point[] T2T(Point start, Point end)
{
List<Point> ps = new List<Point>();
if (start.Y > end.Y)
{
ps.Add(new Point(start.X, end.Y));
}
else
{
ps.Add(new Point(end.X, start.Y));
}
return ps.ToArray();
}
// From上锚点To下锚点
private Point[] T2B(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.Y > end.Y)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, end.Y - cy));
}
else
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
return ps.ToArray();
}
// From上锚点To左锚点
private Point[] T2L(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.Y > end.Y && start.X > end.X)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, end.Y - cy));
}
else if (start.Y < end.Y && start.X < end.X)
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
else if (start.X < end.X)
{
ps.Add(new Point(start.X, end.Y));
}
else
{
ps.Add(new Point(end.X, start.Y));
}
return ps.ToArray();
}
// From上锚点To右锚点
private Point[] T2R(Point start, Point end)
{
double cx = (end.X - start.X) / 2;
double cy = (end.Y - start.Y) / 2;
List<Point> ps = new List<Point>();
if (start.Y > end.Y && start.X > end.X)
{
ps.Add(new Point(start.X, end.Y));
}
else if (start.Y < end.Y && start.X < end.X)
{
ps.Add(new Point(end.X, start.Y));
}
else if (start.X < end.X)
{
ps.Add(new Point(start.X, start.Y + cy));
ps.Add(new Point(end.X, end.Y - cy));
}
else
{
ps.Add(new Point(start.X + cx, start.Y));
ps.Add(new Point(end.X - cx, end.Y));
}
return ps.ToArray();
}
// Fromd上锚点To NULL
private Point[] T2N(Point start, Point end)
{
List<Point> ps = new List<Point>();
if (start.Y > end.Y)
{
ps.Add(new Point(start.X, end.Y));
}
else
{
ps.Add(new Point(end.X, start.Y));
}
return ps.ToArray();
}
#endregion
}
}

View File

@@ -0,0 +1,29 @@
<b:NodeBase x:Class="VisionFrame.Nodes.StartNode"
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:VisionFrame.Nodes"
xmlns:b="clr-namespace:VisionFrame.Base;assembly=VisionFrame.Base"
mc:Ignorable="d"
d:DesignHeight="32" d:DesignWidth="100">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
</UserControl.Resources>
<Grid Name="grid">
<Border CornerRadius="14" Background="#1f71e5" Margin="3">
<TextBlock Text="开始" VerticalAlignment="Center" HorizontalAlignment="Center"
FontSize="11" Foreground="White"/>
</Border>
<Grid Visibility="{Binding ElementName=grid,Path=IsMouseOver,Converter={StaticResource b2v}}">
<Ellipse Width="12" Height="12" Fill="#9FFF"
VerticalAlignment="Bottom"
Stroke="#CCC" StrokeThickness="1"
Margin="0,0,0,-5"
Visibility="{Binding ShowAnchorB,Converter={StaticResource b2v}}"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown">
</Ellipse>
</Grid>
</Grid>
</b:NodeBase>

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VisionFrame.Base;
using VisionFrame.Models;
namespace VisionFrame.Nodes
{
/// <summary>
/// StartNode.xaml 的交互逻辑
/// </summary>
public partial class StartNode : NodeBase
{
public StartNode()
{
InitializeComponent();
}
//public ICommand AnchorDownCommand { get; set; }
//public ICommand AnchorUpCommand { get; set; }
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// T L R B
AnchorDownCommand?.Execute((this.DataContext as NodeModelBase).NodeId + ";B");
e.Handled = true;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VisionFrame.Base;
namespace VisionFrame.Nodes
{
public class StartNodeModel : NodeModelBase
{
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,298 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using VisionFrame.Models;
namespace VisionFrame.ViewModels
{
internal class MainViewModel : ObservableObject
{
#region
private CatalogModel _currentCatalog;
public CatalogModel CurrentCatalog
{
get { return _currentCatalog; }
set { SetProperty<CatalogModel>(ref _currentCatalog, value); }
}
public List<CatalogModel> CatalogList { get; set; } =
new List<CatalogModel>();
public ICommand CatalogItemCommand { get; set; }
public ICommand ComponentItemCommand { get; set; }
#endregion
public ObservableCollection<FlowTabViewModel> FlowTabList { get; set; } =
new ObservableCollection<FlowTabViewModel>()
{
new FlowTabViewModel(){ Title="新建流程(1)"},
new FlowTabViewModel(){ Title="新建流程(2)"},
new FlowTabViewModel(){ Title="新建流程(3)"},
};
public ICommand NewFlowCommand { get; set; }
public ICommand CloseFlowTabCommand { get; set; }
public ICommand SaveFlowCommand { get; set; }
public ICommand OpenFlowCommand { get; set; }
public MainViewModel()
{
#region
CatalogList.Add(new CatalogModel()
{
IsSelected = true,
Icon = "\ue9ed",
Name = "图像采集",
Description = "获取图像方式",
Components = new List<ComponentModel>
{
new ComponentModel{ Icon="\ue604",
Name="文件夹",
TargetNode="ImageCapture;ImageCapture.FolderImageNode",
TargetModel="ImageCapture;ImageCapture.FolderImageNodeModel",
W=150,
H=34
},
new ComponentModel{ Icon="\ue621",Name="Halcon",
TargetNode="ImageCapture;ImageCapture.HalconImageNode",
TargetModel="ImageCapture;ImageCapture.HalconImageNodeModel",
W=150,
H=34},
new ComponentModel{ Icon="\ue621",Name="Basler"},
new ComponentModel{ Icon="\ue621",Name="康耐视"},
new ComponentModel{ Icon="\ue621",Name="基恩士"},
new ComponentModel{ Icon="\ue621",Name="海康"},
new ComponentModel{ Icon="\ue621",Name="大华"},
new ComponentModel{ Icon="\ue621",Name="大疆/DJI"},
new ComponentModel{ Icon="\ue621",Name="Optronis"},
new ComponentModel{ Icon="\ue621",Name="大恒"},
}
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue9ee",
Name = "图像处理",
Description = "获取图像方式获取图像方式获取图像方式",
Components = new List<ComponentModel>
{
new ComponentModel{ Name="图像保存"},
new ComponentModel{ Name="图像显示",Icon="\ue9ee",
TargetNode="ImageProcess;ImageProcess.ImageShowNode",
TargetModel="ImageProcess;ImageProcess.ImageShowNodeModel",
W=150,
H=34}
}
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ueb05",
Name = "设备通信",
Description = "获取图像方式"
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue636",
Name = "图像坐标变换",
Description = "获取图像方式"
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue73f",
Name = "逻辑控制",
Description = "获取图像方式获取图像方式获取图像方式获取图像方式",
Components = new List<ComponentModel>
{
new ComponentModel{ Name="加法",Icon="\ue74d",
TargetNode="LogicControl;LogicControl.AddNode",
TargetModel="LogicControl;LogicControl.AddNodeModel",
W=150,
H=34
},
new ComponentModel{ Name="IF判断",Icon="\ue71d",
TargetNode="LogicControl;LogicControl.DecisionNode",
TargetModel="LogicControl;LogicControl.DecisionNodeModel",
W=120,
H=45
}
}
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue8a4",
Name = "标定工具",
Description = "获取图像方式获取图像方式获取图像方式获取图像方式"
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue86e",
Name = "逻辑控制",
Description = "获取图像方式获取图像方式获取图像方式获取图像方式"
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue644",
Name = "阈值分割",
Description = "获取图像方式获取图像方式获取图像方式获取图像方式"
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue66d",
Name = "几何测量",
Description = "获取图像方式获取图像方式获取图像方式获取图像方式"
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue608",
Name = "模板匹配",
Description = "获取图像方式获取图像方式获取图像方式获取图像方式"
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue712",
Name = "图像内容识别",
Description = "获取图像方式获取图像方式获取图像方式获取图像方式"
});
CatalogList.Add(new CatalogModel()
{
Icon = "\ue73c",
Name = "变量工具",
Description = "获取图像方式获取图像方式获取图像方式获取图像方式"
});
#endregion
CurrentCatalog = CatalogList[0];
CatalogItemCommand =
new RelayCommand<CatalogModel>(model => CurrentCatalog = model);
ComponentItemCommand = new RelayCommand<object>(OnComponentItem);
NewFlowCommand = new RelayCommand(DoNewFlow);
CloseFlowTabCommand = new RelayCommand<object>(DoCloseFlowTab);
SaveFlowCommand = new RelayCommand(DoSaveFlow);
OpenFlowCommand = new RelayCommand(DoOpenFlow);
}
private void OnComponentItem(object obj)
{
// 组件标签触发的
// 当前点击标签的数据源==标签的Model
var model = (obj as FrameworkElement).DataContext;
// 完成拖拽对象的创建
DragDrop.DoDragDrop((DependencyObject)obj, model, DragDropEffects.Copy);
}
#region Tab操作
private async void DoNewFlow()
{
string title = "新建流程";
string temp = "";
await Task.Run(() =>
{
int i = 1;
do
{
temp = title + $"({i})";
i++;
} while (FlowTabList.ToList().Exists(f => f.Title == temp));
//title = temp;
});
FlowTabList.Add(new FlowTabViewModel
{
Title = temp
});
}
private void DoCloseFlowTab(object obj)
{
if (obj is FlowTabViewModel vm)
{
FlowTabList.Remove(vm);
}
else
{
if (obj.ToString() == "1")
{
// 关闭当前Tab
vm = FlowTabList.FirstOrDefault(f => f.IsCurrent);
if (vm != null)
FlowTabList.Remove(vm);
}
else if (obj.ToString() == "2")
{
// 关闭其他
var vms = FlowTabList.Where(f => !f.IsCurrent);
do
{
FlowTabList.Remove(vms.First());
} while (vms.Any());
}
}
}
#endregion
private void DoSaveFlow()
{
var flow = FlowTabList.FirstOrDefault(f => f.IsCurrent);
if (flow == null) return;
flow.Save();
}
private void DoOpenFlow()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "流程文件(*.flw)|*.flw";
dialog.Title = "选择流程文件";
if (dialog.ShowDialog() == true)
{
string fileName = dialog.FileName;
// 检查当前所有Tab中有没有这个文件
var flow = FlowTabList.FirstOrDefault(f =>
!string.IsNullOrEmpty(f.FilePath) &&
f.FilePath.ToLower() == fileName.ToLower()
);
if (flow != null)
{
flow.IsCurrent = true;
return;
}
string json = System.IO.File.ReadAllText(fileName);
string[] jsons = json.Split("@#$#@");
if (jsons.Length != 4) return;
var node = System.Text.Json.JsonSerializer.Deserialize<List<Base.NodeModelBase>>(jsons[1]);
var link = System.Text.Json.JsonSerializer.Deserialize<List<LinkModel>>(jsons[2]);
var arg = System.Text.Json.JsonSerializer.Deserialize<List<Base.Models.FlowArgModel>>(jsons[3]);
FlowTabList.Add(new FlowTabViewModel
{
IsCurrent = true,
Title = jsons[0],
NodeList = new ObservableCollection<Base.NodeModelBase>(node),
LinkList = new ObservableCollection<LinkModel>(link),
ArgumentList = new ObservableCollection<Base.Models.FlowArgModel>(arg),
FilePath = fileName
});
}
}
}
}

View File

@@ -0,0 +1,566 @@
<UserControl x:Class="VisionFrame.Views.FlowTabView"
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:VisionFrame.Views"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:n="clr-namespace:VisionFrame.Nodes"
xmlns:base="clr-namespace:VisionFrame.Base.TemplateSelector;assembly=VisionFrame.Base"
xmlns:c="clr-namespace:VisionFrame.Base.Converter;assembly=VisionFrame.Base"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="1000">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
<c:StringToNodeConverter x:Key="s2n"/>
<c:SizeConverter x:Key="sc"/>
<c:LocationConverter x:Key="lc"/>
<DataTemplate x:Key="folder_temp">
<Grid Grid.Row="1" Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
<ColumnDefinition Width="24"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ArgName}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding ArgType}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Direction}" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<!--Mode=2的情况-->
<Border Grid.Column="3" CornerRadius="3" BorderBrush="#DDD"
BorderThickness="1" Height="24" Margin="0,0,3,0" Name="bor1">
<TextBox Text="{Binding ArgValue,UpdateSourceTrigger=PropertyChanged}" Grid.Column="3" BorderThickness="0"
Margin="3" VerticalAlignment="Center"/>
</Border>
<Button Grid.Column="4" Content="···" Margin="0,0,2,0" Height="24" FontWeight="Normal"
Style="{x:Null}" Foreground="#333" Name="btn1"
Command="{Binding DataContext.SelectFolderCommand,ElementName=root}"
CommandParameter="{Binding}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="#EEE" CornerRadius="3" x:Name="border">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#DDD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</DataTemplate>
<DataTemplate x:Key="dropdown_temp">
<Grid Grid.Row="1" Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
<ColumnDefinition Width="24"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ArgName}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding ArgType}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Direction}" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<!--Mode=0-->
<Border Grid.Column="3" CornerRadius="3" BorderBrush="#DDD"
BorderThickness="1" Height="26" Margin="0,0,3,0" Name="bor3">
<ComboBox Grid.Column="3" Height="24" VerticalContentAlignment="Center"
BorderThickness="0" Background="Transparent"
SelectedIndex="-1"
SelectedValue="{Binding ArgValue}"
Text="{Binding ArgValue}"
ItemsSource="{Binding DataContext.ArgumentList,ElementName=root}"
DisplayMemberPath="ArgName"
SelectedValuePath="ArgName"/>
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="textbox_temp">
<Grid Grid.Row="1" Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
<ColumnDefinition Width="24"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ArgName}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding ArgType}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Direction}" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<!--Mode=1的情况-->
<Border Grid.Column="3" CornerRadius="3" BorderBrush="#DDD"
BorderThickness="1" Height="24" Margin="0,0,3,0" Name="bor2">
<TextBox Text="{Binding ArgValue,UpdateSourceTrigger=PropertyChanged}" Grid.Column="3" BorderThickness="0"
Margin="3" VerticalAlignment="Center"/>
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="compare_temp">
<Grid Grid.Row="1" Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
<ColumnDefinition Width="24"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ArgName}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding ArgType}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Direction}" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<!--Mode=3-->
<Border Grid.Column="3" CornerRadius="3" BorderBrush="#DDD"
BorderThickness="1" Height="26" Margin="0,0,3,0" Name="bor3">
<ComboBox Grid.Column="3" Height="24" VerticalContentAlignment="Center"
BorderThickness="0" Background="Transparent"
SelectedItem="{Binding ArgValue}"
Text="{Binding ArgValue}"
ItemsSource="{Binding DataContext.Operator,ElementName=root}"/>
</Border>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid Name="root" ClipToBounds="True">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="360"/>
</Grid.ColumnDefinitions>
<!--网格背景-->
<Border Name="border_flow_back" ClipToBounds="True">
<Border.Background>
<VisualBrush TileMode="Tile" ViewportUnits="Absolute" Viewport="0,0,14,14">
<VisualBrush.Visual>
<Border Width="14" Height="14"
Background="#9FFF"
BorderBrush="#EEE"
BorderThickness="0,0,1,1"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.Background>
<Canvas>
<!--画布部分-->
<Grid Width="{Binding ElementName=border_flow_back,Path=ActualWidth,Converter={StaticResource sc},ConverterParameter=2}"
Height="{Binding ElementName=border_flow_back,Path=ActualHeight,Converter={StaticResource sc},ConverterParameter=2}"
Name="flow_canvas" RenderTransformOrigin="0.5,0.5"
Background="Transparent"
Tag="{Binding ElementName=hwakeye_border}">
<Grid.Margin>
<MultiBinding Converter="{StaticResource lc}">
<Binding ElementName="border_flow_back" Path="ActualWidth"/>
<Binding ElementName="border_flow_back" Path="ActualHeight"/>
</MultiBinding>
</Grid.Margin>
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="{Binding MainZoom}"
ScaleY="{Binding MainZoom}"/>
<TranslateTransform X="{Binding DragX}"
Y="{Binding DragY}"/>
</TransformGroup>
</Grid.RenderTransform>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseWheel">
<i:CallMethodAction TargetObject="{Binding}"
MethodName="DoMainZoom"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseRightButtonDown">
<i:InvokeCommandAction Command="{Binding CanvasMouseDownCommand}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewMouseMove">
<!--<i:InvokeCommandAction Command="{Binding CanvasMouseMoveCommand}"
PassEventArgsToCommand="True"/>-->
<i:CallMethodAction TargetObject="{Binding}"
MethodName="DoCanvasMouseMove"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseRightButtonUp">
<i:InvokeCommandAction Command="{Binding CanvasMouseUpCommand}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<!--动态生成的节点-->
<ItemsControl ItemsSource="{Binding NodeList}"
Background="Transparent"
AllowDrop="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Drop">
<i:InvokeCommandAction Command="{Binding DragDropCommand}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding NodeMouseDownCommand}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseMove">
<i:InvokeCommandAction Command="{Binding NodeMouseMoveCommand}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding NodeMouseUpCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding TargetNodeObject,Converter={StaticResource s2n}}"
Width="{Binding W}"
Height="{Binding H}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction
Command="{Binding DataContext.NodeMouseDownCommand,
RelativeSource={RelativeSource AncestorType=UserControl}}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!--生成连线的集合控件-->
<ItemsControl ItemsSource="{Binding LinkList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--<Line X1="{Binding StartX}" Y1="{Binding StartY}"
X2="{Binding EndX}" Y2="{Binding EndY}"
Stroke="Orange"
StrokeThickness="2"/>-->
<n:LineNode X1="{Binding StartX}" Y1="{Binding StartY}"
X2="{Binding EndX}" Y2="{Binding EndY}"
StartAnchor="{Binding StartAnchor}"
EndAnchor="{Binding EndAnchor}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!--节点参数区域-->
<Canvas Visibility="{Binding CurrentNodeModel.IsShowProperties,Converter={StaticResource b2v}}">
<Border Width="400" Height="auto"
Background="{x:Null}"
Canvas.Top="{Binding CurrentNodeModel.Y}"
Canvas.Left="{Binding CurrentNodeModel.X}">
<Border Background="White" Margin="0,40,0,0" CornerRadius="5">
<Border.Effect>
<DropShadowEffect Color="Gray" BlurRadius="5" ShadowDepth="0" Opacity="0.3"/>
</Border.Effect>
<Grid Margin="0,0,0,5">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Background="#1000" CornerRadius="5,5,0,0"/>
<Grid Height="26" TextBlock.Foreground="#888">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<TextBlock Text="参数名称" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="数据类型" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="传递方向" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="目标值" Grid.Column="3" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
<ItemsControl ItemsSource="{Binding CurrentNodeModel.Arguments}"
Grid.Row="1">
<ItemsControl.ItemTemplateSelector>
<base:NodeArgTemplateSelector
DropdownTempalte="{StaticResource dropdown_temp}"
TextBoxTempalte="{StaticResource textbox_temp}"
SelectFolderTempalte="{StaticResource folder_temp}"
CompareOpratorTempalte="{StaticResource compare_temp}"
/>
</ItemsControl.ItemTemplateSelector>
</ItemsControl>
</Grid>
</Border>
</Border>
</Canvas>
</Grid>
<!--鹰眼视图-->
<Border Width="{Binding ElementName=border_flow_back,Path=ActualWidth,Converter={StaticResource sc},ConverterParameter=0.2}"
Height="{Binding ElementName=border_flow_back,Path=ActualHeight,Converter={StaticResource sc},ConverterParameter=0.2}"
Canvas.Bottom="10" Canvas.Right="10" BorderBrush="#DDD" BorderThickness="1"
Background="#F7F9FA"
Name="hwakeye_border"
Tag="{Binding ElementName=flow_canvas}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseMove">
<i:CallMethodAction TargetObject="{Binding}"
MethodName="HwakeyeMouseMove"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:CallMethodAction TargetObject="{Binding}"
MethodName="HwakeyeMouseUp"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Border>
<Border.Background>
<BitmapCacheBrush Target="{Binding ElementName=flow_canvas}"/>
</Border.Background>
<Border BorderBrush="ForestGreen" BorderThickness="1"
Width="{Binding ElementName=hwakeye_border,Path=Width,Converter={StaticResource sc},ConverterParameter=0.5}"
Height="{Binding ElementName=hwakeye_border,Path=Height,Converter={StaticResource sc},ConverterParameter=0.5}"
Background="#8FFF"
RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<TranslateTransform X="{Binding HwakeyeDragX}" Y="{Binding HwakeyeDragY}"/>
<ScaleTransform ScaleX="{Binding HwakeyeZoom}" ScaleY="{Binding HwakeyeZoom}"/>
</TransformGroup>
</Border.RenderTransform>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:CallMethodAction TargetObject="{Binding}"
MethodName="HwakeyeViewMouseDown"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Border>
</Border>
</Border>
</Canvas>
</Border>
<!--工具-->
<Border VerticalAlignment="Top" HorizontalAlignment="Left"
Height="26" CornerRadius="13" Background="#2000"
Margin="10">
<Grid Margin="8,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Button Content="&#xe61d;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}"
Command="{Binding RunCommand}"/>
<Button Content="&#xe605;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="1" FontSize="18"
Command="{Binding CircleCommand}"/>
<Button Content="&#xe758;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="2"
Command="{Binding StepCommand}"/>
<Button Content="&#xe616;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="3"
Command="{Binding StopCommand}"/>
<Border Background="#EEE" Grid.Column="4" Width="1"
Margin="3,5"/>
<Button Content="&#xe606;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="5" FontSize="18"
Command="{Binding ZoomIncreaseCommand}"
CommandParameter="{Binding ElementName=flow_canvas}"/>
<Button Content="&#xe60b;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="6" FontSize="18"
Command="{Binding ZoomReduceCommand}"
CommandParameter="{Binding ElementName=flow_canvas}"/>
<Button Content="&#xe631;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="7" FontSize="18"
Command="{Binding ZoomResetCommand}"
CommandParameter="{Binding ElementName=flow_canvas}"/>
</Grid>
</Border>
<!--图像显示、参数、日志-->
<Grid Grid.Column="1" Margin="3,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--图像显示-->
<Border Grid.Column="1" Height="220">
<Border.Background>
<VisualBrush Viewport="0,0,16,16" ViewportUnits="Absolute" TileMode="Tile">
<VisualBrush.Visual>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="#8C8C8C" Width="1" Height="1"/>
<Border Background="#767676" Width="1" Height="1" Grid.Column="1"/>
<Border Background="#767676" Width="1" Height="1" Grid.Row="1"/>
<Border Background="#8C8C8C" Width="1" Height="1" Grid.Row="1" Grid.Column="1"/>
</Grid>
</VisualBrush.Visual>
</VisualBrush>
</Border.Background>
<Image Stretch="UniformToFill" Source="{Binding PreviewImage}"/>
</Border>
<Border Height="26" CornerRadius="13" Background="#656565" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5">
<Grid Margin="8,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Button Content="&#xe606;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="0" FontSize="18" Foreground="#5FFF"/>
<Button Content="&#xe60b;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="1" FontSize="18" Foreground="#5FFF"/>
<Button Content="&#xe631;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="2" FontSize="18" Foreground="#5FFF"/>
<Button Content="&#xeb71;" FontFamily="{StaticResource Iconfont}"
Style="{StaticResource ToolButtonStyle}" Grid.Column="3" FontSize="16" Foreground="#5FFF"/>
</Grid>
</Border>
<!--参数与日志-->
<TabControl Grid.Row="1" Margin="0,5,0,0"
BorderThickness="0,1,0,0" BorderBrush="#1f71e5"
Background="#5FFF" Padding="0">
<TabItem Style="{StaticResource NormalTabStyle}">
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xe655;" FontFamily="{StaticResource Iconfont}"
FontSize="16" VerticalAlignment="Center" Margin="0,0,3,0"/>
<TextBlock Text="流程参数管理" VerticalAlignment="Center"/>
</StackPanel>
</TabItem.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<ListBox Background="Transparent" BorderThickness="0"
ItemsSource="{Binding ArgumentList}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Border Margin="3,3,1,3" CornerRadius="3" Background="#FFF">
<TextBox Text="{Binding ArgName,UpdateSourceTrigger=PropertyChanged}"
VerticalContentAlignment="Center"
BorderThickness="0"
Background="Transparent"
Margin="2" FontWeight="Normal"
Foreground="#555"/>
</Border>
<ComboBox Grid.Column="1" SelectedItem="{Binding ArgType}"
Margin="1,3" BorderThickness="0"
ItemsSource="{Binding DataContext.ArgTypeList,RelativeSource={RelativeSource AncestorType=UserControl}}">
</ComboBox>
<Button Content="&#xe660;" FontFamily="{StaticResource Iconfont}"
Grid.Column="2" Style="{StaticResource DeleteElementButtonStyle}"
FontSize="10" Width="22" Height="22"
Margin="0" Background="Transparent"
Command="{Binding DataContext.DelArgumentCommand,RelativeSource={RelativeSource AncestorType=UserControl}}"
CommandParameter="{Binding}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Margin="3,1" CornerRadius="5" Background="#09000000">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<Border Height="1" Background="#DDD" VerticalAlignment="Top"
Grid.Row="1" Margin="5,0"/>
<Button Grid.Row="1" Height="30" Content="添加参数" Width="120"
HorizontalAlignment="Right"
Margin="5" Command="{Binding AddArgumentCommand}"/>
</Grid>
</TabItem>
<TabItem Style="{StaticResource NormalTabStyle}">
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xe7c3;" FontFamily="{StaticResource Iconfont}"
FontSize="16" VerticalAlignment="Center" Margin="0,0,3,0"/>
<TextBlock Text="运行日志" VerticalAlignment="Center"/>
</StackPanel>
</TabItem.Header>
<ItemsControl ItemsSource="{Binding LogList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="28" Margin="3,1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Time ,StringFormat=HH:mm:ss}"
VerticalAlignment="Center" HorizontalAlignment="Center"
Foreground="#888"/>
<TextBlock Text="{Binding NodeName}" Foreground="#333"
Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding LogMessage}" Grid.Column="2" Foreground="#333"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</TabItem>
</TabControl>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace VisionFrame.Views
{
/// <summary>
/// FlowTabView.xaml 的交互逻辑
/// </summary>
public partial class FlowTabView : UserControl
{
public FlowTabView()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//var temp = this.gggg;
}
}
}

View File

@@ -0,0 +1,264 @@
<Window x:Class="VisionFrame.Views.MainView"
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:VisionFrame.Views"
mc:Ignorable="d" Name="win"
WindowStartupLocation="CenterScreen"
FontWeight="ExtraLight"
FontSize="12"
Title="朝夕运动视觉框架" Height="750" Width="1300">
<WindowChrome.WindowChrome>
<WindowChrome NonClientFrameEdges="None" UseAeroCaptionButtons="False"/>
</WindowChrome.WindowChrome>
<Window.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#DCEAFC" Offset="0"/>
<GradientStop Color="#FFFFFF" Offset="0.5"/>
<GradientStop Color="#DCEAFC" Offset="1"/>
</LinearGradientBrush>
</Window.Background>
<Window.Resources>
<ControlTemplate TargetType="RadioButton" x:Key="CatalogButtonTemp">
<Grid>
<Border Background="Transparent"
Height="40" Margin="0,2"
Name="border">
<TextBlock Text="{Binding Icon}"
FontFamily="{StaticResource Iconfont}"
FontSize="22" Foreground="White"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
<Canvas Name="canvas" Visibility="Collapsed" Background="Transparent"
Width="60">
<Polygon Points="5 0 0 4 5 8"
Fill="#DD1f71e5"
Canvas.Left="50"
Canvas.Top="10"/>
<Border MaxWidth="200" Height="60" Canvas.Left="55"
Background="#DD1f71e5" CornerRadius="5"
TextBlock.Foreground="White">
<StackPanel Margin="10,0" VerticalAlignment="Center">
<TextBlock Text="{Binding Name}" FontWeight="Bold" Margin="0,0,0,5"/>
<Border Height="1" Background="#3FFF"/>
<TextBlock Text="{Binding Description}"
Foreground="#9FFF"
TextTrimming="CharacterEllipsis" Margin="0,5,0,0"/>
</StackPanel>
</Border>
</Canvas>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#2FFF"/>
<!--<Setter TargetName="canvas" Property="Visibility" Value="Visible"/>-->
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="canvas"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.500">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="canvas" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="border" Property="Background" Value="#6FFF"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Grid ClipToBounds="True">
<Ellipse Width="500" Height="500" Fill="{StaticResource lgb}"
VerticalAlignment="Top" HorizontalAlignment="Left"
Margin="200,-80,0,0" Opacity="0.6">
</Ellipse>
<Ellipse Width="400" Height="400" Fill="{StaticResource lgb}"
VerticalAlignment="Top" HorizontalAlignment="Left"
Margin="-80,-250,0,0">
</Ellipse>
<!--窗口内容部分-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--Logo+Title-->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left"
VerticalAlignment="Center">
<!--<Image Source="../Assets/Images/Logo_64.png" Width="30"
Effect="{StaticResource dse}"
Margin="10,0"/>-->
<TextBlock FontSize="14" FontFamily="YouYuan"
Foreground="#555" Effect="{StaticResource dse}"
VerticalAlignment="Center">
<Run Text=" "/>
<Run Text=" "/>
<Run Text="运动视觉流程控制系统"/>
<Run Text="v1.0" FontFamily="Microsoft YaHei" FontSize="9"/>
</TextBlock>
</StackPanel>
<!--Title部分控制按钮-->
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right">
<Button Content="&#xe617;" Style="{StaticResource TitleButtonStyle}"
Command="{Binding NewFlowCommand}"/>
<Button Content="&#xeabe;" Style="{StaticResource TitleButtonStyle}"
Command="{Binding OpenFlowCommand}"/>
<Button Content="&#xe60f;" Style="{StaticResource TitleButtonStyle}"
Command="{Binding SaveFlowCommand}"/>
<Button Content="&#xe9d4;" Style="{StaticResource TitleButtonStyle}"/>
<Border Height="16" Width="1" Background="#CCC" Margin="5,0" VerticalAlignment="Center"/>
<Button Content="&#xea6e;" Style="{StaticResource TitleButtonStyle}"/>
<Button Content="&#xea76;" Style="{StaticResource TitleButtonStyle}"/>
<Border Height="16" Width="1" Background="#CCC" Margin="5,0"/>
<Button Content="&#xe669;" Style="{StaticResource TitleButtonStyle}"/>
<Button Content="&#xe618;" Style="{StaticResource TitleButtonStyle}"/>
<Border Height="16" Width="1" Background="#CCC" Margin="5,0"/>
<TextBlock Text="&#xe80a;" FontFamily="{StaticResource Iconfont}" VerticalAlignment="Center"
FontSize="18" Margin="3,0" Foreground=" #1f71e5"/>
<TextBlock Text="&lt;未登录&gt;" VerticalAlignment="Center" Margin="3,0"/>
<Border Height="16" Width="1" Background="#CCC" Margin="5,0"/>
<Button Content="&#xe65a;" Style="{StaticResource TitleButtonStyle}"
FontSize="14" Margin="0"/>
<Button Content="&#xe692;" Style="{StaticResource TitleButtonStyle}"
FontSize="14" Margin="0"/>
<Button Content="&#xe660;" Style="{StaticResource TitleButtonStyle}"
FontSize="14" Margin="0,0,5,0"
Click="Button_Click"/>
</StackPanel>
<!--流程相关交互-->
<Grid Grid.Row="1" Margin="10,0,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45"/>
<ColumnDefinition Width="150"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="#1f71e5" CornerRadius="10,0,0,10"/>
<Border Background="#8FFF" Grid.Column="1"/>
<!--组件类别-->
<ItemsControl ItemsSource="{Binding CatalogList}"
Margin="0,8"
Panel.ZIndex="10">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton GroupName="A"
IsChecked="{Binding IsSelected}"
Template="{StaticResource CatalogButtonTemp}"
Command="{Binding DataContext.CatalogItemCommand,RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}">
</RadioButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!--组件列表-->
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Height="1" Background="#1000" VerticalAlignment="Bottom"/>
<TextBlock Text="{Binding CurrentCatalog.Name}"
VerticalAlignment="Center" Margin="5,0"
FontWeight="Bold" Foreground="#666"/>
<ItemsControl ItemsSource="{Binding CurrentCatalog.Components}"
Grid.Row="1" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="Transparent"
Width="55" VerticalAlignment="Center"
HorizontalAlignment="Center"
CornerRadius="5"
Margin="0,5"
Name="border">
<Border.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding DataContext.ComponentItemCommand,ElementName=win}"
CommandParameter="{Binding ElementName=border}"/>
</Border.InputBindings>
<StackPanel Margin="0,5">
<TextBlock Text="{Binding Icon}"
FontFamily="{StaticResource Iconfont}"
FontSize="30"
Foreground="#771f71e5"
HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Name}"
FontSize="10"
HorizontalAlignment="Center"
Foreground="#C000"/>
</StackPanel>
</Border>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#1000"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
<!--流程页-->
<TabControl Style="{DynamicResource TabControlStyle}" Grid.Column="2"
Margin="3,0,0,0" BorderThickness="0,1,0,0"
BorderBrush="#1f71e5"
Background="Transparent"
ItemsSource="{Binding FlowTabList}"
SelectedIndex="0">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem" BasedOn="{StaticResource FlowTabStyle}">
<Setter Property="Header" Value="{Binding Title}"/>
<Setter Property="IsSelected" Value="{Binding IsCurrent}"/>
</Style>
</TabControl.ItemContainerStyle>
<TabControl.ContentTemplate>
<DataTemplate>
<local:FlowTabView/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Grid>
</Grid>
</Window>

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using VisionFrame.ViewModels;
namespace VisionFrame.Views
{
/// <summary>
/// MainView.xaml 的交互逻辑
/// </summary>
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}

View File

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Models\FlowArgModel.cs" />
<Compile Remove="Models\NodeModel.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="Assets\Fonts\iconfont.ttf" />
<None Remove="Assets\Images\Logo_64.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VisionFrame.Base\VisionFrame.Base.csproj" />
</ItemGroup>
<ItemGroup>
<Resource Include="Assets\Fonts\iconfont.ttf" />
<Resource Include="Assets\Images\Logo_64.png" />
</ItemGroup>
</Project>