@@ -87,7 +87,7 @@ | |||||
</ControlTemplate> | </ControlTemplate> | ||||
<Style TargetType="{x:Type ComboBox}"> | |||||
<Style TargetType="{x:Type ComboBox}"> | |||||
<Setter Property="BorderThickness" Value="1" /> | <Setter Property="BorderThickness" Value="1" /> | ||||
<Setter Property="Background" Value=" #041039"/> | <Setter Property="Background" Value=" #041039"/> | ||||
<Setter Property="BorderBrush" Value="#FF2AB2E7"/> | <Setter Property="BorderBrush" Value="#FF2AB2E7"/> | ||||
@@ -101,13 +101,12 @@ | |||||
<ControlTemplate TargetType="{x:Type ComboBoxItem}"> | <ControlTemplate TargetType="{x:Type ComboBoxItem}"> | ||||
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" > | <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" > | ||||
<Border x:Name="_borderbg" Background=" #041039" BorderBrush="#FF2AB2E7" BorderThickness="0"/> | <Border x:Name="_borderbg" Background=" #041039" BorderBrush="#FF2AB2E7" BorderThickness="0"/> | ||||
<TextBlock | |||||
<ContentPresenter | |||||
x:Name="_txt" | x:Name="_txt" | ||||
Margin="5,0,3,0" | Margin="5,0,3,0" | ||||
HorizontalAlignment="Left" | HorizontalAlignment="Left" | ||||
VerticalAlignment="Center" | VerticalAlignment="Center" | ||||
Foreground="#FF2AB2E7" | |||||
Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" /> | |||||
/> | |||||
<Border | <Border | ||||
x:Name="_border" | x:Name="_border" | ||||
@@ -123,7 +122,7 @@ | |||||
<Setter TargetName="_borderbg" Property="Background" Value="#37405E" /> | <Setter TargetName="_borderbg" Property="Background" Value="#37405E" /> | ||||
<Setter TargetName="_borderbg" Property="BorderBrush" Value="white" /> | <Setter TargetName="_borderbg" Property="BorderBrush" Value="white" /> | ||||
<Setter TargetName="_borderbg" Property="BorderThickness" Value="1" /> | <Setter TargetName="_borderbg" Property="BorderThickness" Value="1" /> | ||||
<Setter TargetName="_txt" Property="Foreground" Value="white" /> | |||||
<!--<Setter TargetName="_txt" Property="Foreground" Value="white" />--> | |||||
</MultiTrigger> | </MultiTrigger> | ||||
<MultiTrigger> | <MultiTrigger> | ||||
<MultiTrigger.Conditions> | <MultiTrigger.Conditions> | ||||
@@ -132,7 +131,7 @@ | |||||
<Setter TargetName="_borderbg" Property="Background" Value="#022352" /> | <Setter TargetName="_borderbg" Property="Background" Value="#022352" /> | ||||
<Setter TargetName="_borderbg" Property="BorderBrush" Value=" #00BFFF" /> | <Setter TargetName="_borderbg" Property="BorderBrush" Value=" #00BFFF" /> | ||||
<Setter TargetName="_borderbg" Property="BorderThickness" Value="1" /> | <Setter TargetName="_borderbg" Property="BorderThickness" Value="1" /> | ||||
<Setter TargetName="_txt" Property="Foreground" Value="white" /> | |||||
<!--<Setter TargetName="_txt" Property="Foreground" Value="white" />--> | |||||
</MultiTrigger> | </MultiTrigger> | ||||
</ControlTemplate.Triggers> | </ControlTemplate.Triggers> | ||||
</ControlTemplate> | </ControlTemplate> | ||||
@@ -221,7 +220,8 @@ | |||||
<StackPanel | <StackPanel | ||||
Background="{TemplateBinding Background}" | Background="{TemplateBinding Background}" | ||||
IsItemsHost="True" | IsItemsHost="True" | ||||
KeyboardNavigation.DirectionalNavigation="Contained"/> | |||||
KeyboardNavigation.DirectionalNavigation="Contained"> | |||||
</StackPanel> | |||||
</ScrollViewer> | </ScrollViewer> | ||||
</Grid> | </Grid> | ||||
</Popup> | </Popup> | ||||
@@ -49,6 +49,7 @@ | |||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\BPASmart.Model\BPASmart.Model.csproj" /> | <ProjectReference Include="..\BPASmart.Model\BPASmart.Model.csproj" /> | ||||
<ProjectReference Include="..\BPASmartClient.CustomResource\BPASmartClient.CustomResource.csproj" /> | |||||
<ProjectReference Include="..\BPASmartClient.Model\BPASmartClient.Model.csproj" /> | <ProjectReference Include="..\BPASmartClient.Model\BPASmartClient.Model.csproj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -66,7 +66,7 @@ | |||||
<ColumnDefinition Width="2*" /> | <ColumnDefinition Width="2*" /> | ||||
</Grid.ColumnDefinitions> | </Grid.ColumnDefinitions> | ||||
<ComboBox | |||||
<ComboBox | |||||
Name="cb" | Name="cb" | ||||
Grid.Column="0" | Grid.Column="0" | ||||
Margin="3,1" | Margin="3,1" | ||||
@@ -77,7 +77,6 @@ | |||||
FontFamily="楷体" | FontFamily="楷体" | ||||
FontSize="20" | FontSize="20" | ||||
IsEditable="False" | IsEditable="False" | ||||
SelectedValuePath="Key" DisplayMemberPath="Value" | SelectedValuePath="Key" DisplayMemberPath="Value" | ||||
ItemsSource="{Binding DataContext.materialsName, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | ItemsSource="{Binding DataContext.materialsName, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | ||||
SelectedValue="{Binding ID}" | SelectedValue="{Binding ID}" | ||||
@@ -1,5 +1,7 @@ | |||||
using BPASmart.Model; | using BPASmart.Model; | ||||
using BPASmart.RecipeManagement.View; | using BPASmart.RecipeManagement.View; | ||||
using BPASmartClient.CustomResource.UserControls; | |||||
using BPASmartClient.CustomResource.UserControls.MessageShow; | |||||
using BPASmartClient.Helper; | using BPASmartClient.Helper; | ||||
using BPASmartClient.RecipeManagement.View; | using BPASmartClient.RecipeManagement.View; | ||||
using Microsoft.Toolkit.Mvvm.ComponentModel; | using Microsoft.Toolkit.Mvvm.ComponentModel; | ||||
@@ -10,6 +12,7 @@ using System.Collections.ObjectModel; | |||||
using System.Linq; | using System.Linq; | ||||
using System.Text; | using System.Text; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using System.Windows; | |||||
namespace BPASmart.RecipeManagement.ViewModel | namespace BPASmart.RecipeManagement.ViewModel | ||||
{ | { | ||||
@@ -81,8 +84,8 @@ namespace BPASmart.RecipeManagement.ViewModel | |||||
var res = Json<LocalRecipes>.Data.locaRecipes.FirstOrDefault(p => p.ID == id); | var res = Json<LocalRecipes>.Data.locaRecipes.FirstOrDefault(p => p.ID == id); | ||||
if (res != null) | if (res != null) | ||||
{ | { | ||||
//下发配方 | |||||
//下发配方 | |||||
NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "提示", $"配方下发成功!"); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -424,7 +424,7 @@ | |||||
<Setter Property="Template"> | <Setter Property="Template"> | ||||
<Setter.Value> | <Setter.Value> | ||||
<ControlTemplate TargetType="ComboBoxItem"> | <ControlTemplate TargetType="ComboBoxItem"> | ||||
<Border Name="Back" Background="Transparent" BorderThickness="0,0,0,0" BorderBrush="#81D779" > | |||||
<Border Name="Back" Background="Transparent" BorderThickness="0,0,0,0" BorderBrush="#81D779" Height="{TemplateBinding Height}" > | |||||
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5,0,0,0"></ContentPresenter> | <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5,0,0,0"></ContentPresenter> | ||||
</Border> | </Border> | ||||
<ControlTemplate.Triggers> | <ControlTemplate.Triggers> | ||||
@@ -444,13 +444,13 @@ | |||||
<Setter Property="Template"> | <Setter Property="Template"> | ||||
<Setter.Value> | <Setter.Value> | ||||
<ControlTemplate TargetType="{x:Type ComboBox}"> | <ControlTemplate TargetType="{x:Type ComboBox}"> | ||||
<Border BorderThickness="1" BorderBrush="#CDC9C9 " CornerRadius="3" Width="{TemplateBinding Width}" Height="30" Background="{TemplateBinding Background}" > | |||||
<Grid > | |||||
<Border BorderThickness="1" BorderBrush="#CDC9C9 " CornerRadius="3" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" Background="{TemplateBinding Background}" > | |||||
<Grid Height="{TemplateBinding Height}"> | |||||
<Grid.ColumnDefinitions> | <Grid.ColumnDefinitions> | ||||
<ColumnDefinition Width="3*"/> | <ColumnDefinition Width="3*"/> | ||||
<ColumnDefinition Width="*"/> | <ColumnDefinition Width="*"/> | ||||
</Grid.ColumnDefinitions> | </Grid.ColumnDefinitions> | ||||
<Grid Grid.Column="0" x:Name="grid"> | |||||
<Grid Grid.Column="0" x:Name="grid" > | |||||
<ToggleButton | <ToggleButton | ||||
Width="{Binding ElementName=grid,Path=ActualWidth}" | Width="{Binding ElementName=grid,Path=ActualWidth}" | ||||
Height="{Binding ElementName=grid, Path=ActualHeight}" | Height="{Binding ElementName=grid, Path=ActualHeight}" | ||||
@@ -672,5 +672,13 @@ | |||||
</DoubleAnimationUsingKeyFrames> | </DoubleAnimationUsingKeyFrames> | ||||
</Storyboard> | </Storyboard> | ||||
<Style TargetType="TextBlock"> | |||||
<Setter Property="FontSize" Value="18"/> | |||||
<Setter Property="Foreground" Value="DarkSlateGray"/> | |||||
<Setter Property="VerticalAlignment" Value="Center"/> | |||||
<Setter Property="HorizontalAlignment" Value="Center"/> | |||||
<Setter Property="FontSize" Value="18"/> | |||||
</Style> | |||||
</Application.Resources> | </Application.Resources> | ||||
</Application> | </Application> |
@@ -1,11 +1,22 @@ | |||||
using BPASmartClient.Helper; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Configuration; | |||||
using System.Data; | |||||
using System.Linq; | |||||
using System.Threading.Tasks; | |||||
using System.Windows; | |||||
global using BPA.Message; | |||||
global using BPA.Message.Enum; | |||||
global using BPASmartClient.Device; | |||||
global using BPASmartClient.EventBus; | |||||
global using BPASmartClient.Helper; | |||||
global using BPASmartClient.MilkWithTea.Model; | |||||
global using BPASmartClient.Model; | |||||
global using BPASmartClient.MorkMOC; | |||||
global using System; | |||||
global using System.Collections.Generic; | |||||
global using System.Collections.ObjectModel; | |||||
global using System.Linq; | |||||
global using System.Text; | |||||
global using System.Threading.Tasks; | |||||
global using System.Windows; | |||||
global using System.Configuration; | |||||
global using System.Data; | |||||
namespace BPASmartClient.MilkWithTea | namespace BPASmartClient.MilkWithTea | ||||
{ | { | ||||
@@ -23,14 +23,19 @@ | |||||
</EmbeddedResource> | </EmbeddedResource> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.0.0" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\BPASmartClient.Business\BPASmartClient.Business.csproj" /> | <ProjectReference Include="..\BPASmartClient.Business\BPASmartClient.Business.csproj" /> | ||||
<ProjectReference Include="..\BPASmartClient.CustomResource\BPASmartClient.CustomResource.csproj" /> | <ProjectReference Include="..\BPASmartClient.CustomResource\BPASmartClient.CustomResource.csproj" /> | ||||
<ProjectReference Include="..\BPASmartClient.EventBus\BPASmartClient.EventBus.csproj" /> | <ProjectReference Include="..\BPASmartClient.EventBus\BPASmartClient.EventBus.csproj" /> | ||||
<ProjectReference Include="..\BPASmartClient.Helper\BPASmartClient.Helper.csproj" /> | |||||
<ProjectReference Include="..\BPASmartClient.IoT\BPASmartClient.IoT.csproj" /> | <ProjectReference Include="..\BPASmartClient.IoT\BPASmartClient.IoT.csproj" /> | ||||
<ProjectReference Include="..\BPASmartClient.Model\BPASmartClient.Model.csproj" /> | <ProjectReference Include="..\BPASmartClient.Model\BPASmartClient.Model.csproj" /> | ||||
<ProjectReference Include="..\BPASmartClient.MorkMOC\BPASmartClient.MorkMOC.csproj" /> | |||||
<ProjectReference Include="..\BPASmartClient.MORKSM.BK.PLC\BPASmartClient.PLC.csproj" /> | <ProjectReference Include="..\BPASmartClient.MORKSM.BK.PLC\BPASmartClient.PLC.csproj" /> | ||||
<ProjectReference Include="..\BPASmartClient.MorkTM\BPASmartClient.MorkTM.csproj" /> | |||||
<ProjectReference Include="..\BPASmartClient.ViewModel\BPASmartClient.ViewModel.csproj" /> | <ProjectReference Include="..\BPASmartClient.ViewModel\BPASmartClient.ViewModel.csproj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -0,0 +1,30 @@ | |||||
using System.Windows.Controls; | |||||
using System.Windows.Controls.Primitives; | |||||
namespace BPASmartClient.MilkWithTea.Control; | |||||
/// <summary> | |||||
/// 带上下文菜单的切换按钮 | |||||
/// </summary> | |||||
public class ContextMenuToggleButton : ToggleButton | |||||
{ | |||||
public ContextMenu Menu { get; set; } | |||||
protected override void OnClick() | |||||
{ | |||||
base.OnClick(); | |||||
if (Menu != null) | |||||
{ | |||||
if (IsChecked == true) | |||||
{ | |||||
Menu.PlacementTarget = this; | |||||
Menu.IsOpen = true; | |||||
} | |||||
else | |||||
{ | |||||
Menu.IsOpen = false; | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,225 @@ | |||||
using BPASmartClient.MilkWithTea.Data; | |||||
using System; | |||||
using System.Windows; | |||||
using System.Windows.Controls; | |||||
using System.Windows.Input; | |||||
using System.Windows.Media; | |||||
using System.Windows.Media.Animation; | |||||
namespace BPASmartClient.MilkWithTea.Control; | |||||
public class ScrollViewer : System.Windows.Controls.ScrollViewer | |||||
{ | |||||
private double _totalVerticalOffset; | |||||
private double _totalHorizontalOffset; | |||||
private bool _isRunning; | |||||
/// <summary> | |||||
/// 是否响应鼠标滚轮操作 | |||||
/// </summary> | |||||
public static readonly DependencyProperty CanMouseWheelProperty = DependencyProperty.Register( | |||||
"CanMouseWheel", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.TrueBox)); | |||||
/// <summary> | |||||
/// 是否响应鼠标滚轮操作 | |||||
/// </summary> | |||||
public bool CanMouseWheel | |||||
{ | |||||
get => (bool) GetValue(CanMouseWheelProperty); | |||||
set => SetValue(CanMouseWheelProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
protected override void OnMouseWheel(MouseWheelEventArgs e) | |||||
{ | |||||
if (!CanMouseWheel) return; | |||||
if (!IsInertiaEnabled) | |||||
{ | |||||
if (ScrollViewerAttach.GetOrientation(this) == Orientation.Vertical) | |||||
{ | |||||
base.OnMouseWheel(e); | |||||
} | |||||
else | |||||
{ | |||||
_totalHorizontalOffset = HorizontalOffset; | |||||
CurrentHorizontalOffset = HorizontalOffset; | |||||
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth); | |||||
CurrentHorizontalOffset = _totalHorizontalOffset; | |||||
} | |||||
return; | |||||
} | |||||
e.Handled = true; | |||||
if (ScrollViewerAttach.GetOrientation(this) == Orientation.Vertical) | |||||
{ | |||||
if (!_isRunning) | |||||
{ | |||||
_totalVerticalOffset = VerticalOffset; | |||||
CurrentVerticalOffset = VerticalOffset; | |||||
} | |||||
_totalVerticalOffset = Math.Min(Math.Max(0, _totalVerticalOffset - e.Delta), ScrollableHeight); | |||||
ScrollToVerticalOffsetWithAnimation(_totalVerticalOffset); | |||||
} | |||||
else | |||||
{ | |||||
if (!_isRunning) | |||||
{ | |||||
_totalHorizontalOffset = HorizontalOffset; | |||||
CurrentHorizontalOffset = HorizontalOffset; | |||||
} | |||||
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth); | |||||
ScrollToHorizontalOffsetWithAnimation(_totalHorizontalOffset); | |||||
} | |||||
} | |||||
internal void ScrollToTopInternal(double milliseconds = 500) | |||||
{ | |||||
if (!_isRunning) | |||||
{ | |||||
_totalVerticalOffset = VerticalOffset; | |||||
CurrentVerticalOffset = VerticalOffset; | |||||
} | |||||
ScrollToVerticalOffsetWithAnimation(0, milliseconds); | |||||
} | |||||
public void ScrollToVerticalOffsetWithAnimation(double offset, double milliseconds = 500) | |||||
{ | |||||
var animation = CreateAnimation(offset, milliseconds); | |||||
animation.EasingFunction = new CubicEase | |||||
{ | |||||
EasingMode = EasingMode.EaseOut | |||||
}; | |||||
animation.FillBehavior = FillBehavior.Stop; | |||||
animation.Completed += (s, e1) => | |||||
{ | |||||
CurrentVerticalOffset = offset; | |||||
_isRunning = false; | |||||
}; | |||||
_isRunning = true; | |||||
BeginAnimation(CurrentVerticalOffsetProperty, animation, HandoffBehavior.Compose); | |||||
} | |||||
public void ScrollToHorizontalOffsetWithAnimation(double offset, double milliseconds = 500) | |||||
{ | |||||
var animation = CreateAnimation(offset, milliseconds); | |||||
animation.EasingFunction = new CubicEase | |||||
{ | |||||
EasingMode = EasingMode.EaseOut | |||||
}; | |||||
animation.FillBehavior = FillBehavior.Stop; | |||||
animation.Completed += (s, e1) => | |||||
{ | |||||
CurrentHorizontalOffset = offset; | |||||
_isRunning = false; | |||||
}; | |||||
_isRunning = true; | |||||
BeginAnimation(CurrentHorizontalOffsetProperty, animation, HandoffBehavior.Compose); | |||||
} | |||||
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) => | |||||
IsPenetrating ? null : base.HitTestCore(hitTestParameters); | |||||
/// <summary> | |||||
/// 是否支持惯性 | |||||
/// </summary> | |||||
public static readonly DependencyProperty IsInertiaEnabledProperty = DependencyProperty.RegisterAttached( | |||||
"IsInertiaEnabled", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.FalseBox)); | |||||
public static void SetIsInertiaEnabled(DependencyObject element, bool value) => element.SetValue(IsInertiaEnabledProperty, ValueBoxes.BooleanBox(value)); | |||||
public static bool GetIsInertiaEnabled(DependencyObject element) => (bool) element.GetValue(IsInertiaEnabledProperty); | |||||
/// <summary> | |||||
/// 是否支持惯性 | |||||
/// </summary> | |||||
public bool IsInertiaEnabled | |||||
{ | |||||
get => (bool) GetValue(IsInertiaEnabledProperty); | |||||
set => SetValue(IsInertiaEnabledProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 控件是否可以穿透点击 | |||||
/// </summary> | |||||
public static readonly DependencyProperty IsPenetratingProperty = DependencyProperty.RegisterAttached( | |||||
"IsPenetrating", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.FalseBox)); | |||||
/// <summary> | |||||
/// 控件是否可以穿透点击 | |||||
/// </summary> | |||||
public bool IsPenetrating | |||||
{ | |||||
get => (bool) GetValue(IsPenetratingProperty); | |||||
set => SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
public static void SetIsPenetrating(DependencyObject element, bool value) => element.SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value)); | |||||
public static bool GetIsPenetrating(DependencyObject element) => (bool) element.GetValue(IsPenetratingProperty); | |||||
/// <summary> | |||||
/// 当前垂直滚动偏移 | |||||
/// </summary> | |||||
internal static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register( | |||||
"CurrentVerticalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentVerticalOffsetChanged)); | |||||
private static void OnCurrentVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |||||
{ | |||||
if (d is ScrollViewer ctl && e.NewValue is double v) | |||||
{ | |||||
ctl.ScrollToVerticalOffset(v); | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// 当前垂直滚动偏移 | |||||
/// </summary> | |||||
internal double CurrentVerticalOffset | |||||
{ | |||||
// ReSharper disable once UnusedMember.Local | |||||
get => (double) GetValue(CurrentVerticalOffsetProperty); | |||||
set => SetValue(CurrentVerticalOffsetProperty, value); | |||||
} | |||||
/// <summary> | |||||
/// 当前水平滚动偏移 | |||||
/// </summary> | |||||
internal static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register( | |||||
"CurrentHorizontalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentHorizontalOffsetChanged)); | |||||
private static void OnCurrentHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |||||
{ | |||||
if (d is ScrollViewer ctl && e.NewValue is double v) | |||||
{ | |||||
ctl.ScrollToHorizontalOffset(v); | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// 当前水平滚动偏移 | |||||
/// </summary> | |||||
internal double CurrentHorizontalOffset | |||||
{ | |||||
get => (double) GetValue(CurrentHorizontalOffsetProperty); | |||||
set => SetValue(CurrentHorizontalOffsetProperty, value); | |||||
} | |||||
/// <summary> | |||||
/// 创建一个Double动画 | |||||
/// </summary> | |||||
/// <param name="toValue"></param> | |||||
/// <param name="milliseconds"></param> | |||||
/// <returns></returns> | |||||
public DoubleAnimation CreateAnimation(double toValue, double milliseconds = 200) | |||||
{ | |||||
return new(toValue, new Duration(TimeSpan.FromMilliseconds(milliseconds))) | |||||
{ | |||||
EasingFunction = new PowerEase { EasingMode = EasingMode.EaseInOut } | |||||
}; | |||||
} | |||||
} |
@@ -0,0 +1,111 @@ | |||||
using BPASmartClient.MilkWithTea.Data; | |||||
using System; | |||||
using System.Windows; | |||||
using System.Windows.Controls; | |||||
using System.Windows.Input; | |||||
using System.Windows.Media; | |||||
namespace BPASmartClient.MilkWithTea.Control; | |||||
public class ScrollViewerAttach | |||||
{ | |||||
public static readonly DependencyProperty AutoHideProperty = DependencyProperty.RegisterAttached( | |||||
"AutoHide", typeof(bool), typeof(ScrollViewerAttach), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.Inherits)); | |||||
public static void SetAutoHide(DependencyObject element, bool value) | |||||
=> element.SetValue(AutoHideProperty, ValueBoxes.BooleanBox(value)); | |||||
public static bool GetAutoHide(DependencyObject element) | |||||
=> (bool) element.GetValue(AutoHideProperty); | |||||
public static readonly DependencyProperty OrientationProperty = DependencyProperty.RegisterAttached( | |||||
"Orientation", typeof(Orientation), typeof(ScrollViewerAttach), new FrameworkPropertyMetadata(ValueBoxes.VerticalBox, FrameworkPropertyMetadataOptions.Inherits, OnOrientationChanged)); | |||||
private static void OnOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |||||
{ | |||||
if (d is ScrollViewer) | |||||
{ | |||||
return; | |||||
} | |||||
if (d is System.Windows.Controls.ScrollViewer scrollViewer) | |||||
{ | |||||
if ((Orientation) e.NewValue == Orientation.Horizontal) | |||||
{ | |||||
scrollViewer.PreviewMouseWheel += ScrollViewerPreviewMouseWheel; | |||||
} | |||||
else | |||||
{ | |||||
scrollViewer.PreviewMouseWheel -= ScrollViewerPreviewMouseWheel; | |||||
} | |||||
} | |||||
void ScrollViewerPreviewMouseWheel(object sender, MouseWheelEventArgs args) | |||||
{ | |||||
var scrollViewerNative = (System.Windows.Controls.ScrollViewer) sender; | |||||
scrollViewerNative.ScrollToHorizontalOffset(Math.Min(Math.Max(0, scrollViewerNative.HorizontalOffset - args.Delta), scrollViewerNative.ScrollableWidth)); | |||||
args.Handled = true; | |||||
} | |||||
} | |||||
public static void SetOrientation(DependencyObject element, Orientation value) | |||||
=> element.SetValue(OrientationProperty, ValueBoxes.OrientationBox(value)); | |||||
public static Orientation GetOrientation(DependencyObject element) | |||||
=> (Orientation) element.GetValue(OrientationProperty); | |||||
public static readonly DependencyProperty IsDisabledProperty = DependencyProperty.RegisterAttached( | |||||
"IsDisabled", typeof(bool), typeof(ScrollViewerAttach), new PropertyMetadata(ValueBoxes.FalseBox, OnIsDisabledChanged)); | |||||
private static void OnIsDisabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |||||
{ | |||||
if (d is UIElement element) | |||||
{ | |||||
if ((bool) e.NewValue) | |||||
{ | |||||
element.PreviewMouseWheel += ScrollViewerPreviewMouseWheel; | |||||
} | |||||
else | |||||
{ | |||||
element.PreviewMouseWheel -= ScrollViewerPreviewMouseWheel; | |||||
} | |||||
} | |||||
void ScrollViewerPreviewMouseWheel(object sender, MouseWheelEventArgs args) | |||||
{ | |||||
if (args.Handled) | |||||
{ | |||||
return; | |||||
} | |||||
args.Handled = true; | |||||
if (GetParent<System.Windows.Controls.ScrollViewer>((UIElement) sender) is { } scrollViewer) | |||||
{ | |||||
scrollViewer.RaiseEvent(new MouseWheelEventArgs(args.MouseDevice, args.Timestamp, args.Delta) | |||||
{ | |||||
RoutedEvent = UIElement.MouseWheelEvent, | |||||
Source = sender | |||||
}); | |||||
} | |||||
} | |||||
static T GetParent<T>(DependencyObject d) where T : DependencyObject => | |||||
d switch | |||||
{ | |||||
null => default, | |||||
T t => t, | |||||
Window _ => null, | |||||
_ => GetParent<T>(VisualTreeHelper.GetParent(d)) | |||||
}; | |||||
} | |||||
public static void SetIsDisabled(DependencyObject element, bool value) | |||||
=> element.SetValue(IsDisabledProperty, ValueBoxes.BooleanBox(value)); | |||||
public static bool GetIsDisabled(DependencyObject element) | |||||
=> (bool) element.GetValue(IsDisabledProperty); | |||||
} |
@@ -0,0 +1,426 @@ | |||||
using BPASmartClient.MilkWithTea.Data; | |||||
using System; | |||||
using System.Collections; | |||||
using System.Collections.Specialized; | |||||
using System.Windows; | |||||
using System.Windows.Controls; | |||||
using System.Windows.Controls.Primitives; | |||||
using System.Windows.Input; | |||||
namespace BPASmartClient.MilkWithTea.Control; | |||||
[TemplatePart(Name = HeaderPanelKey, Type = typeof(TabPanel))] | |||||
[TemplatePart(Name = OverflowScrollviewer, Type = typeof(ScrollViewer))] | |||||
[TemplatePart(Name = ScrollButtonLeft, Type = typeof(ButtonBase))] | |||||
[TemplatePart(Name = ScrollButtonRight, Type = typeof(ButtonBase))] | |||||
[TemplatePart(Name = HeaderBorder, Type = typeof(Border))] | |||||
public class TabControl : System.Windows.Controls.TabControl | |||||
{ | |||||
private const string OverflowButtonKey = "PART_OverflowButton"; | |||||
private const string HeaderPanelKey = "PART_HeaderPanel"; | |||||
private const string OverflowScrollviewer = "PART_OverflowScrollviewer"; | |||||
private const string ScrollButtonLeft = "PART_ScrollButtonLeft"; | |||||
private const string ScrollButtonRight = "PART_ScrollButtonRight"; | |||||
private const string HeaderBorder = "PART_HeaderBorder"; | |||||
private ContextMenuToggleButton _buttonOverflow; | |||||
internal TabPanel HeaderPanel { get; private set; } | |||||
private ScrollViewer _scrollViewerOverflow; | |||||
private ButtonBase _buttonScrollLeft; | |||||
private ButtonBase _buttonScrollRight; | |||||
private Border _headerBorder; | |||||
/// <summary> | |||||
/// 是否为内部操作 | |||||
/// </summary> | |||||
internal bool IsInternalAction; | |||||
/// <summary> | |||||
/// 是否启用动画 | |||||
/// </summary> | |||||
public static readonly DependencyProperty IsAnimationEnabledProperty = DependencyProperty.Register( | |||||
"IsAnimationEnabled", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox)); | |||||
/// <summary> | |||||
/// 是否启用动画 | |||||
/// </summary> | |||||
public bool IsAnimationEnabled | |||||
{ | |||||
get => (bool) GetValue(IsAnimationEnabledProperty); | |||||
set => SetValue(IsAnimationEnabledProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 是否可以拖动 | |||||
/// </summary> | |||||
public static readonly DependencyProperty IsDraggableProperty = DependencyProperty.Register( | |||||
"IsDraggable", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox)); | |||||
/// <summary> | |||||
/// 是否可以拖动 | |||||
/// </summary> | |||||
public bool IsDraggable | |||||
{ | |||||
get => (bool) GetValue(IsDraggableProperty); | |||||
set => SetValue(IsDraggableProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 是否显示关闭按钮 | |||||
/// </summary> | |||||
public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.RegisterAttached( | |||||
"ShowCloseButton", typeof(bool), typeof(TabControl), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits)); | |||||
public static void SetShowCloseButton(DependencyObject element, bool value) | |||||
=> element.SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value)); | |||||
public static bool GetShowCloseButton(DependencyObject element) | |||||
=> (bool) element.GetValue(ShowCloseButtonProperty); | |||||
/// <summary> | |||||
/// 是否显示关闭按钮 | |||||
/// </summary> | |||||
public bool ShowCloseButton | |||||
{ | |||||
get => (bool) GetValue(ShowCloseButtonProperty); | |||||
set => SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 是否显示上下文菜单 | |||||
/// </summary> | |||||
public static readonly DependencyProperty ShowContextMenuProperty = DependencyProperty.RegisterAttached( | |||||
"ShowContextMenu", typeof(bool), typeof(TabControl), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.Inherits)); | |||||
public static void SetShowContextMenu(DependencyObject element, bool value) | |||||
=> element.SetValue(ShowContextMenuProperty, ValueBoxes.BooleanBox(value)); | |||||
public static bool GetShowContextMenu(DependencyObject element) | |||||
=> (bool) element.GetValue(ShowContextMenuProperty); | |||||
/// <summary> | |||||
/// 是否显示上下文菜单 | |||||
/// </summary> | |||||
public bool ShowContextMenu | |||||
{ | |||||
get => (bool) GetValue(ShowContextMenuProperty); | |||||
set => SetValue(ShowContextMenuProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 是否将标签填充 | |||||
/// </summary> | |||||
public static readonly DependencyProperty IsTabFillEnabledProperty = DependencyProperty.Register( | |||||
"IsTabFillEnabled", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox)); | |||||
/// <summary> | |||||
/// 是否将标签填充 | |||||
/// </summary> | |||||
public bool IsTabFillEnabled | |||||
{ | |||||
get => (bool) GetValue(IsTabFillEnabledProperty); | |||||
set => SetValue(IsTabFillEnabledProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 标签宽度 | |||||
/// </summary> | |||||
public static readonly DependencyProperty TabItemWidthProperty = DependencyProperty.Register( | |||||
"TabItemWidth", typeof(double), typeof(TabControl), new PropertyMetadata(200.0)); | |||||
/// <summary> | |||||
/// 标签宽度 | |||||
/// </summary> | |||||
public double TabItemWidth | |||||
{ | |||||
get => (double) GetValue(TabItemWidthProperty); | |||||
set => SetValue(TabItemWidthProperty, value); | |||||
} | |||||
/// <summary> | |||||
/// 标签高度 | |||||
/// </summary> | |||||
public static readonly DependencyProperty TabItemHeightProperty = DependencyProperty.Register( | |||||
"TabItemHeight", typeof(double), typeof(TabControl), new PropertyMetadata(30.0)); | |||||
/// <summary> | |||||
/// 标签高度 | |||||
/// </summary> | |||||
public double TabItemHeight | |||||
{ | |||||
get => (double) GetValue(TabItemHeightProperty); | |||||
set => SetValue(TabItemHeightProperty, value); | |||||
} | |||||
/// <summary> | |||||
/// 是否可以滚动 | |||||
/// </summary> | |||||
public static readonly DependencyProperty IsScrollableProperty = DependencyProperty.Register( | |||||
"IsScrollable", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox)); | |||||
/// <summary> | |||||
/// 是否可以滚动 | |||||
/// </summary> | |||||
public bool IsScrollable | |||||
{ | |||||
get => (bool) GetValue(IsScrollableProperty); | |||||
set => SetValue(IsScrollableProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 是否显示溢出按钮 | |||||
/// </summary> | |||||
public static readonly DependencyProperty ShowOverflowButtonProperty = DependencyProperty.Register( | |||||
"ShowOverflowButton", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.TrueBox)); | |||||
/// <summary> | |||||
/// 是否显示溢出按钮 | |||||
/// </summary> | |||||
public bool ShowOverflowButton | |||||
{ | |||||
get => (bool) GetValue(ShowOverflowButtonProperty); | |||||
set => SetValue(ShowOverflowButtonProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 是否显示滚动按钮 | |||||
/// </summary> | |||||
public static readonly DependencyProperty ShowScrollButtonProperty = DependencyProperty.Register( | |||||
"ShowScrollButton", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox)); | |||||
/// <summary> | |||||
/// 是否显示滚动按钮 | |||||
/// </summary> | |||||
public bool ShowScrollButton | |||||
{ | |||||
get => (bool) GetValue(ShowScrollButtonProperty); | |||||
set => SetValue(ShowScrollButtonProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 可见的标签数量 | |||||
/// </summary> | |||||
private int _itemShowCount; | |||||
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) | |||||
{ | |||||
base.OnItemsChanged(e); | |||||
if (HeaderPanel == null) | |||||
{ | |||||
IsInternalAction = false; | |||||
return; | |||||
} | |||||
UpdateOverflowButton(); | |||||
if (IsInternalAction) | |||||
{ | |||||
IsInternalAction = false; | |||||
return; | |||||
} | |||||
if (e.Action == NotifyCollectionChangedAction.Add) | |||||
{ | |||||
for (var i = 0; i < Items.Count; i++) | |||||
{ | |||||
if (ItemContainerGenerator.ContainerFromIndex(i) is not TabItem item) return; | |||||
item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); | |||||
item.TabPanel = HeaderPanel; | |||||
} | |||||
} | |||||
_headerBorder?.InvalidateMeasure(); | |||||
IsInternalAction = false; | |||||
} | |||||
public override void OnApplyTemplate() | |||||
{ | |||||
if (_buttonOverflow != null) | |||||
{ | |||||
if (_buttonOverflow.Menu != null) | |||||
{ | |||||
_buttonOverflow.Menu.Closed -= Menu_Closed; | |||||
_buttonOverflow.Menu = null; | |||||
} | |||||
_buttonOverflow.Click -= ButtonOverflow_Click; | |||||
} | |||||
if (_buttonScrollLeft != null) _buttonScrollLeft.Click -= ButtonScrollLeft_Click; | |||||
if (_buttonScrollRight != null) _buttonScrollRight.Click -= ButtonScrollRight_Click; | |||||
base.OnApplyTemplate(); | |||||
HeaderPanel = GetTemplateChild(HeaderPanelKey) as TabPanel; | |||||
if (IsTabFillEnabled) return; | |||||
_buttonOverflow = GetTemplateChild(OverflowButtonKey) as ContextMenuToggleButton; | |||||
_scrollViewerOverflow = GetTemplateChild(OverflowScrollviewer) as ScrollViewer; | |||||
_buttonScrollLeft = GetTemplateChild(ScrollButtonLeft) as ButtonBase; | |||||
_buttonScrollRight = GetTemplateChild(ScrollButtonRight) as ButtonBase; | |||||
_headerBorder = GetTemplateChild(HeaderBorder) as Border; | |||||
if (_buttonScrollLeft != null) _buttonScrollLeft.Click += ButtonScrollLeft_Click; | |||||
if (_buttonScrollRight != null) _buttonScrollRight.Click += ButtonScrollRight_Click; | |||||
if (_buttonOverflow != null) | |||||
{ | |||||
var menu = new ContextMenu | |||||
{ | |||||
Placement = PlacementMode.Bottom, | |||||
PlacementTarget = _buttonOverflow | |||||
}; | |||||
menu.Closed += Menu_Closed; | |||||
_buttonOverflow.Menu = menu; | |||||
_buttonOverflow.Click += ButtonOverflow_Click; | |||||
} | |||||
} | |||||
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) | |||||
{ | |||||
base.OnRenderSizeChanged(sizeInfo); | |||||
UpdateOverflowButton(); | |||||
} | |||||
private void UpdateOverflowButton() | |||||
{ | |||||
if (!IsTabFillEnabled) | |||||
{ | |||||
_itemShowCount = (int) (ActualWidth / TabItemWidth); | |||||
//_buttonOverflow?.Show(ShowOverflowButton && Items.Count > 0 && Items.Count >= _itemShowCount); | |||||
} | |||||
} | |||||
private void Menu_Closed(object sender, RoutedEventArgs e) => _buttonOverflow.IsChecked = false; | |||||
private void ButtonScrollRight_Click(object sender, RoutedEventArgs e) => | |||||
_scrollViewerOverflow.ScrollToHorizontalOffsetWithAnimation(Math.Min( | |||||
_scrollViewerOverflow.CurrentHorizontalOffset + TabItemWidth, _scrollViewerOverflow.ScrollableWidth)); | |||||
private void ButtonScrollLeft_Click(object sender, RoutedEventArgs e) => | |||||
_scrollViewerOverflow.ScrollToHorizontalOffsetWithAnimation(Math.Max( | |||||
_scrollViewerOverflow.CurrentHorizontalOffset - TabItemWidth, 0)); | |||||
private void ButtonOverflow_Click(object sender, RoutedEventArgs e) | |||||
{ | |||||
if (_buttonOverflow.IsChecked == true) | |||||
{ | |||||
_buttonOverflow.Menu.Items.Clear(); | |||||
for (var i = 0; i < Items.Count; i++) | |||||
{ | |||||
if (ItemContainerGenerator.ContainerFromIndex(i) is not TabItem item) continue; | |||||
var menuItem = new MenuItem | |||||
{ | |||||
HeaderStringFormat = ItemStringFormat, | |||||
HeaderTemplate = ItemTemplate, | |||||
HeaderTemplateSelector = ItemTemplateSelector, | |||||
Header = item.Header, | |||||
Width = TabItemWidth, | |||||
IsChecked = item.IsSelected, | |||||
IsCheckable = true, | |||||
IsEnabled = item.IsEnabled | |||||
}; | |||||
menuItem.Click += delegate | |||||
{ | |||||
_buttonOverflow.IsChecked = false; | |||||
var list = GetActualList(); | |||||
if (list == null) return; | |||||
var actualItem = ItemContainerGenerator.ItemFromContainer(item); | |||||
if (actualItem == null) return; | |||||
var index = list.IndexOf(actualItem); | |||||
if (index >= _itemShowCount) | |||||
{ | |||||
list.Remove(actualItem); | |||||
list.Insert(0, actualItem); | |||||
HeaderPanel.SetValue(TabPanel.FluidMoveDurationPropertyKey, | |||||
IsAnimationEnabled | |||||
? new Duration(TimeSpan.FromMilliseconds(200)) | |||||
: new Duration(TimeSpan.FromMilliseconds(0))); | |||||
HeaderPanel.ForceUpdate = true; | |||||
HeaderPanel.Measure(new Size(HeaderPanel.DesiredSize.Width, ActualHeight)); | |||||
HeaderPanel.ForceUpdate = false; | |||||
SetCurrentValue(SelectedIndexProperty, ValueBoxes.Int0Box); | |||||
} | |||||
item.IsSelected = true; | |||||
}; | |||||
_buttonOverflow.Menu.Items.Add(menuItem); | |||||
} | |||||
} | |||||
} | |||||
internal double GetHorizontalOffset() => _scrollViewerOverflow?.CurrentHorizontalOffset ?? 0; | |||||
internal void UpdateScroll() => _scrollViewerOverflow?.RaiseEvent(new MouseWheelEventArgs(Mouse.PrimaryDevice, Environment.TickCount, 0) | |||||
{ | |||||
RoutedEvent = MouseWheelEvent | |||||
}); | |||||
internal void CloseAllItems() => CloseOtherItems(null); | |||||
internal void CloseOtherItems(TabItem currentItem) | |||||
{ | |||||
var actualItem = currentItem != null ? ItemContainerGenerator.ItemFromContainer(currentItem) : null; | |||||
var list = GetActualList(); | |||||
if (list == null) return; | |||||
IsInternalAction = true; | |||||
for (var i = 0; i < Items.Count; i++) | |||||
{ | |||||
var item = list[i]; | |||||
if (!Equals(item, actualItem) && item != null) | |||||
{ | |||||
var argsClosing = new CancelRoutedEventArgs(TabItem.ClosingEvent, item); | |||||
if (ItemContainerGenerator.ContainerFromItem(item) is not TabItem tabItem) continue; | |||||
tabItem.RaiseEvent(argsClosing); | |||||
if (argsClosing.Cancel) return; | |||||
tabItem.RaiseEvent(new RoutedEventArgs(TabItem.ClosedEvent, item)); | |||||
list.Remove(item); | |||||
i--; | |||||
} | |||||
} | |||||
SetCurrentValue(SelectedIndexProperty, Items.Count == 0 ? -1 : 0); | |||||
} | |||||
internal IList GetActualList() | |||||
{ | |||||
IList list; | |||||
if (ItemsSource != null) | |||||
{ | |||||
list = ItemsSource as IList; | |||||
} | |||||
else | |||||
{ | |||||
list = Items; | |||||
} | |||||
return list; | |||||
} | |||||
protected override bool IsItemItsOwnContainerOverride(object item) => item is TabItem; | |||||
protected override DependencyObject GetContainerForItemOverride() => new TabItem(); | |||||
} |
@@ -0,0 +1,509 @@ | |||||
using System; | |||||
using System.Windows; | |||||
using System.Windows.Controls; | |||||
using System.Windows.Controls.Primitives; | |||||
using System.Windows.Data; | |||||
using System.Windows.Input; | |||||
using System.Windows.Media; | |||||
using System.Windows.Media.Animation; | |||||
using BPASmartClient.MilkWithTea.Control; | |||||
using BPASmartClient.MilkWithTea.Data; | |||||
using TabControl = BPASmartClient.MilkWithTea.Control.TabControl; | |||||
namespace BPASmartClient.MilkWithTea.Control; | |||||
public class TabItem : System.Windows.Controls.TabItem | |||||
{ | |||||
/// <summary> | |||||
/// 动画速度 | |||||
/// </summary> | |||||
private const int AnimationSpeed = 150; | |||||
/// <summary> | |||||
/// 选项卡是否处于拖动状态 | |||||
/// </summary> | |||||
private static bool ItemIsDragging; | |||||
/// <summary> | |||||
/// 选项卡是否等待被拖动 | |||||
/// </summary> | |||||
private bool _isWaiting; | |||||
/// <summary> | |||||
/// 拖动中的选项卡坐标 | |||||
/// </summary> | |||||
private Point _dragPoint; | |||||
/// <summary> | |||||
/// 鼠标按下时选项卡位置 | |||||
/// </summary> | |||||
private int _mouseDownIndex; | |||||
/// <summary> | |||||
/// 鼠标按下时选项卡横向偏移 | |||||
/// </summary> | |||||
private double _mouseDownOffsetX; | |||||
/// <summary> | |||||
/// 鼠标按下时的坐标 | |||||
/// </summary> | |||||
private Point _mouseDownPoint; | |||||
/// <summary> | |||||
/// 右侧可移动的最大值 | |||||
/// </summary> | |||||
private double _maxMoveRight; | |||||
/// <summary> | |||||
/// 左侧可移动的最大值 | |||||
/// </summary> | |||||
private double _maxMoveLeft; | |||||
/// <summary> | |||||
/// 选项卡宽度 | |||||
/// </summary> | |||||
public double ItemWidth { get; internal set; } | |||||
/// <summary> | |||||
/// 选项卡拖动等待距离(在鼠标移动了超过20个像素无关单位后,选项卡才开始被拖动) | |||||
/// </summary> | |||||
private const double WaitLength = 20; | |||||
/// <summary> | |||||
/// 选项卡是否处于拖动状态 | |||||
/// </summary> | |||||
private bool _isDragging; | |||||
/// <summary> | |||||
/// 选项卡是否已经被拖动 | |||||
/// </summary> | |||||
private bool _isDragged; | |||||
/// <summary> | |||||
/// 目标横向位移 | |||||
/// </summary> | |||||
internal double TargetOffsetX { get; set; } | |||||
/// <summary> | |||||
/// 当前编号 | |||||
/// </summary> | |||||
private int _currentIndex; | |||||
/// <summary> | |||||
/// 标签容器横向滚动距离 | |||||
/// </summary> | |||||
private double _scrollHorizontalOffset; | |||||
private TabPanel _tabPanel; | |||||
/// <summary> | |||||
/// 标签容器 | |||||
/// </summary> | |||||
internal TabPanel TabPanel | |||||
{ | |||||
get | |||||
{ | |||||
if (_tabPanel == null && TabControlParent != null) | |||||
{ | |||||
_tabPanel = TabControlParent.HeaderPanel; | |||||
} | |||||
return _tabPanel; | |||||
} | |||||
set => _tabPanel = value; | |||||
} | |||||
private TabControl TabControlParent => ItemsControl.ItemsControlFromItemContainer(this) as TabControl; | |||||
/// <summary> | |||||
/// 当前编号 | |||||
/// </summary> | |||||
internal int CurrentIndex | |||||
{ | |||||
get => _currentIndex; | |||||
set | |||||
{ | |||||
if (_currentIndex == value || value < 0) return; | |||||
var oldIndex = _currentIndex; | |||||
_currentIndex = value; | |||||
UpdateItemOffsetX(oldIndex); | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// 是否显示关闭按钮 | |||||
/// </summary> | |||||
public static readonly DependencyProperty ShowCloseButtonProperty = | |||||
TabControl.ShowCloseButtonProperty.AddOwner(typeof(TabItem)); | |||||
/// <summary> | |||||
/// 是否显示关闭按钮 | |||||
/// </summary> | |||||
public bool ShowCloseButton | |||||
{ | |||||
get => (bool) GetValue(ShowCloseButtonProperty); | |||||
set => SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
public static void SetShowCloseButton(DependencyObject element, bool value) | |||||
=> element.SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value)); | |||||
public static bool GetShowCloseButton(DependencyObject element) | |||||
=> (bool) element.GetValue(ShowCloseButtonProperty); | |||||
/// <summary> | |||||
/// 是否显示上下文菜单 | |||||
/// </summary> | |||||
public static readonly DependencyProperty ShowContextMenuProperty = | |||||
TabControl.ShowContextMenuProperty.AddOwner(typeof(TabItem), new FrameworkPropertyMetadata(OnShowContextMenuChanged)); | |||||
private static void OnShowContextMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |||||
{ | |||||
var ctl = (TabItem) d; | |||||
if (ctl.Menu != null) | |||||
{ | |||||
var show = (bool) e.NewValue; | |||||
ctl.Menu.IsEnabled = show; | |||||
//ctl.Menu.Show(show); | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// 是否显示上下文菜单 | |||||
/// </summary> | |||||
public bool ShowContextMenu | |||||
{ | |||||
get => (bool) GetValue(ShowContextMenuProperty); | |||||
set => SetValue(ShowContextMenuProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
public static void SetShowContextMenu(DependencyObject element, bool value) | |||||
=> element.SetValue(ShowContextMenuProperty, ValueBoxes.BooleanBox(value)); | |||||
public static bool GetShowContextMenu(DependencyObject element) | |||||
=> (bool) element.GetValue(ShowContextMenuProperty); | |||||
public static readonly DependencyProperty MenuProperty = DependencyProperty.Register( | |||||
"Menu", typeof(ContextMenu), typeof(TabItem), new PropertyMetadata(default(ContextMenu), OnMenuChanged)); | |||||
private static void OnMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |||||
{ | |||||
var ctl = (TabItem) d; | |||||
//ctl.OnMenuChanged(e.NewValue as ContextMenu); | |||||
} | |||||
//private void OnMenuChanged(ContextMenu menu) | |||||
//{ | |||||
// if (IsLoaded && menu != null) | |||||
// { | |||||
// var parent = TabControlParent; | |||||
// if (parent == null) return; | |||||
// var item = parent.ItemContainerGenerator.ItemFromContainer(this); | |||||
// menu.DataContext = item; | |||||
// menu.SetBinding(IsEnabledProperty, new Binding(ShowContextMenuProperty.Name) | |||||
// { | |||||
// Source = this | |||||
// }); | |||||
// menu.SetBinding(VisibilityProperty, new Binding(ShowContextMenuProperty.Name) | |||||
// { | |||||
// Source = this, | |||||
// Converter = GetResourceInternal<IValueConverter>(ResourceToken.Boolean2VisibilityConverter) | |||||
// }); | |||||
// } | |||||
//} | |||||
public ContextMenu Menu | |||||
{ | |||||
get => (ContextMenu) GetValue(MenuProperty); | |||||
set => SetValue(MenuProperty, value); | |||||
} | |||||
/// <summary> | |||||
/// 更新选项卡横向偏移 | |||||
/// </summary> | |||||
/// <param name="oldIndex"></param> | |||||
private void UpdateItemOffsetX(int oldIndex) | |||||
{ | |||||
if (!_isDragging || CurrentIndex >= TabPanel.ItemDic.Count) | |||||
{ | |||||
return; | |||||
} | |||||
var moveItem = TabPanel.ItemDic[CurrentIndex]; | |||||
moveItem.CurrentIndex -= CurrentIndex - oldIndex; | |||||
var offsetX = moveItem.TargetOffsetX; | |||||
var resultX = offsetX + (oldIndex - CurrentIndex) * ItemWidth; | |||||
TabPanel.ItemDic[CurrentIndex] = this; | |||||
TabPanel.ItemDic[moveItem.CurrentIndex] = moveItem; | |||||
moveItem.CreateAnimation(offsetX, resultX); | |||||
} | |||||
public TabItem() | |||||
{ | |||||
//CommandBindings.Add(new CommandBinding(ControlCommands.Close, (s, e) => Close())); | |||||
//CommandBindings.Add(new CommandBinding(ControlCommands.CloseAll, | |||||
// (s, e) => { TabControlParent.CloseAllItems(); })); | |||||
//CommandBindings.Add(new CommandBinding(ControlCommands.CloseOther, | |||||
// (s, e) => { TabControlParent.CloseOtherItems(this); })); | |||||
//Loaded += (s, e) => OnMenuChanged(Menu); | |||||
} | |||||
protected override void OnMouseRightButtonDown(MouseButtonEventArgs e) | |||||
{ | |||||
base.OnMouseRightButtonDown(e); | |||||
if (VisualTreeHelper.HitTest(this, e.GetPosition(this)) == null) return; | |||||
IsSelected = true; | |||||
Focus(); | |||||
} | |||||
protected override void OnHeaderChanged(object oldHeader, object newHeader) | |||||
{ | |||||
base.OnHeaderChanged(oldHeader, newHeader); | |||||
if (TabPanel != null) | |||||
{ | |||||
TabPanel.ForceUpdate = true; | |||||
InvalidateMeasure(); | |||||
TabPanel.ForceUpdate = true; | |||||
} | |||||
} | |||||
internal void Close() | |||||
{ | |||||
var parent = TabControlParent; | |||||
if (parent == null) return; | |||||
var item = parent.ItemContainerGenerator.ItemFromContainer(this); | |||||
var argsClosing = new CancelRoutedEventArgs(ClosingEvent, item); | |||||
RaiseEvent(argsClosing); | |||||
if (argsClosing.Cancel) return; | |||||
TabPanel.SetValue(TabPanel.FluidMoveDurationPropertyKey, parent.IsAnimationEnabled | |||||
? new Duration(TimeSpan.FromMilliseconds(200)) | |||||
: new Duration(TimeSpan.FromMilliseconds(1))); | |||||
parent.IsInternalAction = true; | |||||
RaiseEvent(new RoutedEventArgs(ClosedEvent, item)); | |||||
var list = parent.GetActualList(); | |||||
list?.Remove(item); | |||||
} | |||||
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) | |||||
{ | |||||
base.OnMouseLeftButtonDown(e); | |||||
if (VisualTreeHelper.HitTest(this, e.GetPosition(this)) == null) return; | |||||
var parent = TabControlParent; | |||||
if (parent == null) return; | |||||
if (parent.IsDraggable && !ItemIsDragging && !_isDragging) | |||||
{ | |||||
parent.UpdateScroll(); | |||||
TabPanel.SetValue(TabPanel.FluidMoveDurationPropertyKey, new Duration(TimeSpan.FromSeconds(0))); | |||||
_mouseDownOffsetX = RenderTransform.Value.OffsetX; | |||||
_scrollHorizontalOffset = parent.GetHorizontalOffset(); | |||||
var mx = TranslatePoint(new Point(), parent).X + _scrollHorizontalOffset; | |||||
_mouseDownIndex = CalLocationIndex(mx); | |||||
var subIndex = _mouseDownIndex - CalLocationIndex(_scrollHorizontalOffset); | |||||
_maxMoveLeft = -subIndex * ItemWidth; | |||||
_maxMoveRight = parent.ActualWidth - ActualWidth + _maxMoveLeft; | |||||
_isDragging = true; | |||||
ItemIsDragging = true; | |||||
_isWaiting = true; | |||||
_dragPoint = e.GetPosition(parent); | |||||
_dragPoint = new Point(_dragPoint.X + _scrollHorizontalOffset, _dragPoint.Y); | |||||
_mouseDownPoint = _dragPoint; | |||||
CaptureMouse(); | |||||
} | |||||
} | |||||
protected override void OnMouseMove(MouseEventArgs e) | |||||
{ | |||||
base.OnMouseMove(e); | |||||
if (ItemIsDragging && _isDragging) | |||||
{ | |||||
var parent = TabControlParent; | |||||
if (parent == null) return; | |||||
var subX = TranslatePoint(new Point(), parent).X + _scrollHorizontalOffset; | |||||
CurrentIndex = CalLocationIndex(subX); | |||||
var p = e.GetPosition(parent); | |||||
p = new Point(p.X + _scrollHorizontalOffset, p.Y); | |||||
var subLeft = p.X - _dragPoint.X; | |||||
var totalLeft = p.X - _mouseDownPoint.X; | |||||
if (Math.Abs(subLeft) <= WaitLength && _isWaiting) return; | |||||
_isWaiting = false; | |||||
_isDragged = true; | |||||
var left = subLeft + RenderTransform.Value.OffsetX; | |||||
if (totalLeft < _maxMoveLeft) | |||||
{ | |||||
left = _maxMoveLeft + _mouseDownOffsetX; | |||||
} | |||||
else if (totalLeft > _maxMoveRight) | |||||
{ | |||||
left = _maxMoveRight + _mouseDownOffsetX; | |||||
} | |||||
var t = new TranslateTransform(left, 0); | |||||
RenderTransform = t; | |||||
_dragPoint = p; | |||||
} | |||||
} | |||||
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) | |||||
{ | |||||
base.OnMouseLeftButtonUp(e); | |||||
ReleaseMouseCapture(); | |||||
if (_isDragged) | |||||
{ | |||||
var parent = TabControlParent; | |||||
if (parent == null) return; | |||||
var subX = TranslatePoint(new Point(), parent).X + _scrollHorizontalOffset; | |||||
var index = CalLocationIndex(subX); | |||||
var left = index * ItemWidth; | |||||
var offsetX = RenderTransform.Value.OffsetX; | |||||
CreateAnimation(offsetX, offsetX - subX + left, index); | |||||
} | |||||
_isDragging = false; | |||||
ItemIsDragging = false; | |||||
_isDragged = false; | |||||
} | |||||
protected override void OnMouseDown(MouseButtonEventArgs e) | |||||
{ | |||||
if (e.ChangedButton == MouseButton.Middle && e.ButtonState == MouseButtonState.Pressed) | |||||
{ | |||||
if (ShowCloseButton || ShowContextMenu) | |||||
{ | |||||
Close(); | |||||
} | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// 创建动画 | |||||
/// </summary> | |||||
internal void CreateAnimation(double offsetX, double resultX, int index = -1) | |||||
{ | |||||
var parent = TabControlParent; | |||||
void AnimationCompleted() | |||||
{ | |||||
RenderTransform = new TranslateTransform(resultX, 0); | |||||
if (index == -1) return; | |||||
var list = parent.GetActualList(); | |||||
if (list == null) return; | |||||
var item = parent.ItemContainerGenerator.ItemFromContainer(this); | |||||
if (item == null) return; | |||||
TabPanel.CanUpdate = false; | |||||
parent.IsInternalAction = true; | |||||
list.Remove(item); | |||||
parent.IsInternalAction = true; | |||||
list.Insert(index, item); | |||||
_tabPanel.SetValue(TabPanel.FluidMoveDurationPropertyKey, new Duration(TimeSpan.FromMilliseconds(0))); | |||||
TabPanel.CanUpdate = true; | |||||
TabPanel.ForceUpdate = true; | |||||
TabPanel.Measure(new Size(TabPanel.DesiredSize.Width, ActualHeight)); | |||||
TabPanel.ForceUpdate = false; | |||||
Focus(); | |||||
IsSelected = true; | |||||
if (!IsMouseCaptured) | |||||
{ | |||||
parent.SetCurrentValue(Selector.SelectedIndexProperty, _currentIndex); | |||||
} | |||||
} | |||||
TargetOffsetX = resultX; | |||||
if (!parent.IsAnimationEnabled) | |||||
{ | |||||
AnimationCompleted(); | |||||
return; | |||||
} | |||||
var animation = CreateAnimation(resultX, AnimationSpeed); | |||||
animation.FillBehavior = FillBehavior.Stop; | |||||
animation.Completed += (s1, e1) => AnimationCompleted(); | |||||
var f = new TranslateTransform(offsetX, 0); | |||||
RenderTransform = f; | |||||
f.BeginAnimation(TranslateTransform.XProperty, animation, HandoffBehavior.Compose); | |||||
} | |||||
/// <summary> | |||||
/// 创建一个Double动画 | |||||
/// </summary> | |||||
/// <param name="toValue"></param> | |||||
/// <param name="milliseconds"></param> | |||||
/// <returns></returns> | |||||
public static DoubleAnimation CreateAnimation(double toValue, double milliseconds = 200) | |||||
{ | |||||
return new(toValue, new Duration(TimeSpan.FromMilliseconds(milliseconds))) | |||||
{ | |||||
EasingFunction = new PowerEase { EasingMode = EasingMode.EaseInOut } | |||||
}; | |||||
} | |||||
/// <summary> | |||||
/// 计算选项卡当前合适的位置编号 | |||||
/// </summary> | |||||
/// <param name="left"></param> | |||||
/// <returns></returns> | |||||
private int CalLocationIndex(double left) | |||||
{ | |||||
if (_isWaiting) | |||||
{ | |||||
return CurrentIndex; | |||||
} | |||||
var maxIndex = TabControlParent.Items.Count - 1; | |||||
var div = (int) (left / ItemWidth); | |||||
var rest = left % ItemWidth; | |||||
var result = rest / ItemWidth > .5 ? div + 1 : div; | |||||
return result > maxIndex ? maxIndex : result; | |||||
} | |||||
public static readonly RoutedEvent ClosingEvent = EventManager.RegisterRoutedEvent("Closing", RoutingStrategy.Bubble, typeof(EventHandler), typeof(TabItem)); | |||||
public event EventHandler Closing | |||||
{ | |||||
add => AddHandler(ClosingEvent, value); | |||||
remove => RemoveHandler(ClosingEvent, value); | |||||
} | |||||
public static readonly RoutedEvent ClosedEvent = EventManager.RegisterRoutedEvent("Closed", RoutingStrategy.Bubble, typeof(EventHandler), typeof(TabItem)); | |||||
public event EventHandler Closed | |||||
{ | |||||
add => AddHandler(ClosedEvent, value); | |||||
remove => RemoveHandler(ClosedEvent, value); | |||||
} | |||||
} |
@@ -0,0 +1,200 @@ | |||||
using BPASmartClient.MilkWithTea.Data; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Windows; | |||||
using System.Windows.Controls; | |||||
using System.Windows.Media; | |||||
namespace BPASmartClient.MilkWithTea.Control; | |||||
public class TabPanel : Panel | |||||
{ | |||||
private int _itemCount; | |||||
/// <summary> | |||||
/// 是否可以更新 | |||||
/// </summary> | |||||
internal bool CanUpdate = true; | |||||
/// <summary> | |||||
/// 选项卡字典 | |||||
/// </summary> | |||||
internal Dictionary<int, TabItem> ItemDic = new(); | |||||
public static readonly DependencyPropertyKey FluidMoveDurationPropertyKey = | |||||
DependencyProperty.RegisterReadOnly("FluidMoveDuration", typeof(Duration), typeof(TabPanel), | |||||
new PropertyMetadata(new Duration(TimeSpan.FromMilliseconds(0)))); | |||||
/// <summary> | |||||
/// 流式行为持续时间 | |||||
/// </summary> | |||||
public static readonly DependencyProperty FluidMoveDurationProperty = | |||||
FluidMoveDurationPropertyKey.DependencyProperty; | |||||
/// <summary> | |||||
/// 流式行为持续时间 | |||||
/// </summary> | |||||
public Duration FluidMoveDuration | |||||
{ | |||||
get => (Duration) GetValue(FluidMoveDurationProperty); | |||||
set => SetValue(FluidMoveDurationProperty, value); | |||||
} | |||||
/// <summary> | |||||
/// 是否将标签填充 | |||||
/// </summary> | |||||
public static readonly DependencyProperty IsTabFillEnabledProperty = DependencyProperty.Register( | |||||
"IsTabFillEnabled", typeof(bool), typeof(TabPanel), new PropertyMetadata(ValueBoxes.FalseBox)); | |||||
/// <summary> | |||||
/// 是否将标签填充 | |||||
/// </summary> | |||||
public bool IsTabFillEnabled | |||||
{ | |||||
get => (bool) GetValue(IsTabFillEnabledProperty); | |||||
set => SetValue(IsTabFillEnabledProperty, ValueBoxes.BooleanBox(value)); | |||||
} | |||||
/// <summary> | |||||
/// 标签宽度 | |||||
/// </summary> | |||||
public static readonly DependencyProperty TabItemWidthProperty = DependencyProperty.Register( | |||||
"TabItemWidth", typeof(double), typeof(TabPanel), new PropertyMetadata(200.0)); | |||||
/// <summary> | |||||
/// 标签宽度 | |||||
/// </summary> | |||||
public double TabItemWidth | |||||
{ | |||||
get => (double) GetValue(TabItemWidthProperty); | |||||
set => SetValue(TabItemWidthProperty, value); | |||||
} | |||||
/// <summary> | |||||
/// 标签高度 | |||||
/// </summary> | |||||
public static readonly DependencyProperty TabItemHeightProperty = DependencyProperty.Register( | |||||
"TabItemHeight", typeof(double), typeof(TabPanel), new PropertyMetadata(30.0)); | |||||
/// <summary> | |||||
/// 标签高度 | |||||
/// </summary> | |||||
public double TabItemHeight | |||||
{ | |||||
get => (double) GetValue(TabItemHeightProperty); | |||||
set => SetValue(TabItemHeightProperty, value); | |||||
} | |||||
/// <summary> | |||||
/// 是否可以强制更新 | |||||
/// </summary> | |||||
internal bool ForceUpdate; | |||||
private Size _oldSize; | |||||
/// <summary> | |||||
/// 是否已经加载 | |||||
/// </summary> | |||||
private bool _isLoaded; | |||||
protected override Size MeasureOverride(Size constraint) | |||||
{ | |||||
if ((_itemCount == InternalChildren.Count || !CanUpdate) && !ForceUpdate && !IsTabFillEnabled) return _oldSize; | |||||
constraint.Height = TabItemHeight; | |||||
_itemCount = InternalChildren.Count; | |||||
var size = new Size(); | |||||
ItemDic.Clear(); | |||||
var count = InternalChildren.Count; | |||||
if (count == 0) | |||||
{ | |||||
_oldSize = new Size(); | |||||
return _oldSize; | |||||
} | |||||
constraint.Width += InternalChildren.Count; | |||||
var itemWidth = .0; | |||||
var arr = new int[count]; | |||||
if (!IsTabFillEnabled) | |||||
{ | |||||
itemWidth = TabItemWidth; | |||||
} | |||||
else | |||||
{ | |||||
if (TemplatedParent is TabControl tabControl) | |||||
{ | |||||
arr = DivideInt2Arr((int) tabControl.ActualWidth + InternalChildren.Count, count); | |||||
} | |||||
} | |||||
for (var index = 0; index < count; index++) | |||||
{ | |||||
if (IsTabFillEnabled) | |||||
{ | |||||
itemWidth = arr[index]; | |||||
} | |||||
if (InternalChildren[index] is TabItem tabItem) | |||||
{ | |||||
tabItem.RenderTransform = new TranslateTransform(); | |||||
tabItem.MaxWidth = itemWidth; | |||||
var rect = new Rect | |||||
{ | |||||
X = size.Width - tabItem.BorderThickness.Left, | |||||
Width = itemWidth, | |||||
Height = TabItemHeight | |||||
}; | |||||
tabItem.Arrange(rect); | |||||
tabItem.ItemWidth = itemWidth - tabItem.BorderThickness.Left; | |||||
tabItem.CurrentIndex = index; | |||||
tabItem.TargetOffsetX = 0; | |||||
ItemDic[index] = tabItem; | |||||
size.Width += tabItem.ItemWidth; | |||||
} | |||||
} | |||||
size.Height = constraint.Height; | |||||
_oldSize = size; | |||||
return _oldSize; | |||||
} | |||||
/// <summary> | |||||
/// 平分一个整数到一个数组中 | |||||
/// </summary> | |||||
/// <param name="num"></param> | |||||
/// <param name="count"></param> | |||||
/// <returns></returns> | |||||
public static int[] DivideInt2Arr(int num, int count) | |||||
{ | |||||
var arr = new int[count]; | |||||
var div = num / count; | |||||
var rest = num % count; | |||||
for (var i = 0; i < count; i++) | |||||
{ | |||||
arr[i] = div; | |||||
} | |||||
for (var i = 0; i < rest; i++) | |||||
{ | |||||
arr[i] += 1; | |||||
} | |||||
return arr; | |||||
} | |||||
public TabPanel() | |||||
{ | |||||
Loaded += (s, e) => | |||||
{ | |||||
if (_isLoaded) return; | |||||
ForceUpdate = true; | |||||
Measure(new Size(DesiredSize.Width, ActualHeight)); | |||||
ForceUpdate = false; | |||||
foreach (var item in ItemDic.Values) | |||||
{ | |||||
item.TabPanel = this; | |||||
} | |||||
_isLoaded = true; | |||||
}; | |||||
} | |||||
} |
@@ -0,0 +1,12 @@ | |||||
using System.Windows; | |||||
namespace BPASmartClient.MilkWithTea.Data; | |||||
public class CancelRoutedEventArgs : RoutedEventArgs | |||||
{ | |||||
public CancelRoutedEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source) | |||||
{ | |||||
} | |||||
public bool Cancel { get; set; } | |||||
} |
@@ -0,0 +1,69 @@ | |||||
using System; | |||||
using System.Windows; | |||||
using System.Windows.Controls; | |||||
namespace BPASmartClient.MilkWithTea.Data; | |||||
/// <summary> | |||||
/// 装箱后的值类型(用于提高效率) | |||||
/// </summary> | |||||
internal static class ValueBoxes | |||||
{ | |||||
internal static object TrueBox = true; | |||||
internal static object FalseBox = false; | |||||
internal static object VerticalBox = Orientation.Vertical; | |||||
internal static object HorizontalBox = Orientation.Horizontal; | |||||
internal static object VisibleBox = Visibility.Visible; | |||||
internal static object CollapsedBox = Visibility.Collapsed; | |||||
internal static object HiddenBox = Visibility.Hidden; | |||||
internal static object Double01Box = .1; | |||||
internal static object Double0Box = .0; | |||||
internal static object Double1Box = 1.0; | |||||
internal static object Double10Box = 10.0; | |||||
internal static object Double20Box = 20.0; | |||||
internal static object Double100Box = 100.0; | |||||
internal static object Double200Box = 200.0; | |||||
internal static object Double300Box = 300.0; | |||||
internal static object DoubleNeg1Box = -1.0; | |||||
internal static object Int0Box = 0; | |||||
internal static object Int1Box = 1; | |||||
internal static object Int2Box = 2; | |||||
internal static object Int5Box = 5; | |||||
internal static object Int99Box = 99; | |||||
internal static object BooleanBox(bool value) => value ? TrueBox : FalseBox; | |||||
internal static object OrientationBox(Orientation value) => | |||||
value == Orientation.Horizontal ? HorizontalBox : VerticalBox; | |||||
internal static object VisibilityBox(Visibility value) | |||||
{ | |||||
return value switch | |||||
{ | |||||
Visibility.Visible => VisibleBox, | |||||
Visibility.Hidden => HiddenBox, | |||||
Visibility.Collapsed => CollapsedBox, | |||||
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null) | |||||
}; | |||||
} | |||||
} |
@@ -1,5 +1,5 @@ | |||||
using BPASmartClient.Model; | using BPASmartClient.Model; | ||||
using Model; | |||||
using BPASmartClient.MorkMOC; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -17,46 +17,15 @@ namespace BPASmartClient.MilkWithTea | |||||
public static string recipePath = string.Empty; | public static string recipePath = string.Empty; | ||||
public static string posionPath = string.Empty; | public static string posionPath = string.Empty; | ||||
public static bool makeEnable = false; | |||||
public static ObservableCollection<LocalTeaWithMilkConfig> MaterialRecipes { get; set; } = new ObservableCollection<LocalTeaWithMilkConfig>(); | |||||
public static bool makeEnable = true; | |||||
/// <summary> | /// <summary> | ||||
/// 设备信息列表 | |||||
/// 设备信息集合 | |||||
/// </summary> | /// </summary> | ||||
public static ObservableCollection<DeviceConfigModelJson> deviceConfig { get; set; } = new ObservableCollection<DeviceConfigModelJson>(); | public static ObservableCollection<DeviceConfigModelJson> deviceConfig { get; set; } = new ObservableCollection<DeviceConfigModelJson>(); | ||||
/// <summary> | |||||
/// 获取Json文件内容,转换成ObservableCollection | |||||
/// </summary> | |||||
/// <typeparam name="T"></typeparam> | |||||
/// <param name="path"></param> | |||||
/// <returns></returns> | |||||
public static ObservableCollection<T> GetJsonToT<T>(string path) | |||||
{ | |||||
if (!File.Exists(path)) | |||||
{ | |||||
//创建该文件 | |||||
File.Create(path); | |||||
return default; | |||||
} | |||||
else | |||||
{ | |||||
using (StreamReader recipeReader = new StreamReader(path))//读取json文件 | |||||
{ | |||||
string datacache = ""; | |||||
string line; | |||||
while ((line = recipeReader.ReadLine()) != null) //循环将每一行数据拼接为一个完整的字符串 | |||||
{ | |||||
datacache = datacache + line; | |||||
} | |||||
var res = JsonConvert.DeserializeObject<ObservableCollection<T>>(datacache); //将string转换为class类,从而达到json文件转换的目的 | |||||
if (res != null) | |||||
return res; | |||||
else return new ObservableCollection<T> { }; | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
} | } |
@@ -7,6 +7,7 @@ using BPASmartClient.IoT; | |||||
using BPASmartClient.Message; | using BPASmartClient.Message; | ||||
using BPASmartClient.Peripheral; | using BPASmartClient.Peripheral; | ||||
using BPASmartClient.ViewModel; | using BPASmartClient.ViewModel; | ||||
using Newtonsoft.Json; | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.IO; | using System.IO; | ||||
@@ -36,8 +37,10 @@ namespace BPASmartClient.MilkWithTea | |||||
public MainWindow() | public MainWindow() | ||||
{ | { | ||||
InitializeComponent(); | InitializeComponent(); | ||||
Initialize(); | |||||
TextHelper.GetInstance.WriteTextInfo("MOC", "StartShop", "DeviceConfig"); | |||||
CreateDevice(); | |||||
//Initialize(); | |||||
} | } | ||||
@@ -45,6 +48,50 @@ namespace BPASmartClient.MilkWithTea | |||||
DoubleAnimation yd1 = new DoubleAnimation();//实例化浮点动画 | DoubleAnimation yd1 = new DoubleAnimation();//实例化浮点动画 | ||||
DoubleAnimation yd2 = new DoubleAnimation(); | DoubleAnimation yd2 = new DoubleAnimation(); | ||||
private void CreateDevice() | |||||
{ | |||||
DirectoryInfo directoryInfo = new DirectoryInfo(LocaPath.GetInstance().GetDeviceConfigPath); | |||||
if(!File.Exists($"{directoryInfo}Moc.json")) | |||||
{ | |||||
File.WriteAllText($"{directoryInfo}Moc.json", JsonConvert.SerializeObject(GLobal.deviceConfig)); | |||||
} | |||||
string JsonString = File.ReadAllText($"{directoryInfo}MOC.json"); | |||||
var result = JsonConvert.DeserializeObject<ObservableCollection<DeviceConfigModelJson>>(JsonString); | |||||
if (result != null) | |||||
{ | |||||
ShopDeviceConfigViewModel.deviceConfig.Clear(); | |||||
foreach (var item in result) | |||||
{ | |||||
GLobal.deviceConfig.Add(item); | |||||
} | |||||
} | |||||
if(GLobal.deviceConfig.Count <1) | |||||
{ | |||||
GLobal.deviceConfig.Add(new DeviceConfigModelJson()); | |||||
if(GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.Count <1) | |||||
{ | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.Add(new DeviceModel()); | |||||
if(GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).communicationDevcies.Count <1) | |||||
{ | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).communicationDevcies.Add(new CommunicationModel()); | |||||
} | |||||
} | |||||
} | |||||
if (GLobal.deviceConfig.ElementAt(0).deviceModels.ElementAt(0).communicationDevcies.ElementAt(0).variables.Count < 1) | |||||
{ | |||||
for (int i = 0; i < 20; i++) | |||||
{ | |||||
GLobal.deviceConfig.ElementAt(0).deviceModels.ElementAt(0).communicationDevcies.ElementAt(0).variables.Add(new Variable() | |||||
{ | |||||
Id = GLobal.deviceConfig.ElementAt(0).deviceModels.ElementAt(0).communicationDevcies.ElementAt(0).variables.Count, | |||||
Address = string.Empty, | |||||
ReadLeng = 0 | |||||
}); | |||||
} | |||||
File.WriteAllText($"{LocaPath.GetInstance().GetDeviceConfigPath}MOC.json", JsonConvert.SerializeObject(GLobal.deviceConfig)); | |||||
} | |||||
} | |||||
private void Initialize() | private void Initialize() | ||||
{ | { | ||||
@@ -0,0 +1,13 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace BPASmartClient.MilkWithTea.Model | |||||
{ | |||||
public class JsonDeviceConfig | |||||
{ | |||||
public ObservableCollection<DeviceConfigModelJson> deviceConfig { get; set; } = new ObservableCollection<DeviceConfigModelJson>(); | |||||
} | |||||
} |
@@ -0,0 +1,23 @@ | |||||
using BPASmartClient.MorkMOC; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.ObjectModel; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace BPASmartClient.MilkWithTea.Model | |||||
{ | |||||
partial class JsonLocalRecipes | |||||
{ | |||||
/// <summary> | |||||
/// 本地奶茶配方 | |||||
/// </summary> | |||||
public ObservableCollection<LocalRecipe> localRecipes { get; set; } = new ObservableCollection<LocalRecipe>(); | |||||
/// <summary> | |||||
/// 本地原料 | |||||
/// </summary> | |||||
public ObservableCollection<LocalMaterail> localMaterails { get; set; } = new ObservableCollection<LocalMaterail>(); | |||||
} | |||||
} |
@@ -11,48 +11,6 @@ | |||||
<vm:LocalConfigureViewModel/> | <vm:LocalConfigureViewModel/> | ||||
</UserControl.DataContext> | </UserControl.DataContext> | ||||
<UserControl.Resources> | <UserControl.Resources> | ||||
<Style TargetType="{x:Type DataGridCell}"> | |||||
<Setter Property="FocusVisualStyle" Value="{x:Null}"/> | |||||
<Setter Property="TextBlock.FontSize" Value="13" /> | |||||
<Setter Property="Background" Value="Transparent"/> | |||||
<Setter Property="BorderBrush" Value="Transparent"/> | |||||
<Setter Property="BorderThickness" Value="0"/> | |||||
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Mode=Self},Path=Content.Text}" /> | |||||
<Setter Property="Template"> | |||||
<Setter.Value> | |||||
<ControlTemplate TargetType="{x:Type DataGridCell}"> | |||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> | |||||
<!--HorizontalAlignment 可以设置内容展示位置--> | |||||
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" HorizontalAlignment="Center" | |||||
Margin="{TemplateBinding Padding}"/> | |||||
</Border> | |||||
</ControlTemplate> | |||||
</Setter.Value> | |||||
</Setter> | |||||
<Style.Triggers> | |||||
<Trigger Property="IsEnabled" Value="False"> | |||||
<Setter Property="Opacity" Value=".56"/> | |||||
</Trigger> | |||||
</Style.Triggers> | |||||
</Style> | |||||
<Style TargetType="DataGridRow"> | |||||
<Setter Property="FontSize" Value="16"/> | |||||
<Setter Property="VerticalAlignment" Value="Center"/> | |||||
<Setter Property="Margin" Value="0,5"/> | |||||
<Style.Triggers> | |||||
<!-- 隔行换色 --> | |||||
<Trigger Property="AlternationIndex" Value="0"> | |||||
<Setter Property="Background" Value="#FFFAFAFA" /> | |||||
</Trigger> | |||||
<Trigger Property="AlternationIndex" Value="1"> | |||||
<Setter Property="Background" Value="#FFF5F5F7" /> | |||||
</Trigger> | |||||
<Trigger Property="IsMouseOver" Value="True"> | |||||
<Setter Property="Background" Value="#87CEFA" /> | |||||
</Trigger> | |||||
</Style.Triggers> | |||||
</Style> | |||||
<Style TargetType="Button"> | <Style TargetType="Button"> | ||||
<Setter Property="Width" Value="90"/> | <Setter Property="Width" Value="90"/> | ||||
<Setter Property="Height" Value="20"/> | <Setter Property="Height" Value="20"/> | ||||
@@ -78,12 +36,47 @@ | |||||
</Setter.Value> | </Setter.Value> | ||||
</Setter> | </Setter> | ||||
</Style> | </Style> | ||||
<Style TargetType="ListViewItem" > | |||||
<Setter Property="Margin" Value="60,20"/> | |||||
<Setter Property="Template"> | |||||
<Setter.Value> | |||||
<ControlTemplate TargetType="ListViewItem"> | |||||
<Border Padding="4" x:Name="mborder" BorderBrush="Transparent" BorderThickness="1"> | |||||
<Border > | |||||
<Grid Width="250" > | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition Width="auto"/> | |||||
<ColumnDefinition Width="*"/> | |||||
</Grid.ColumnDefinitions> | |||||
<TextBlock Text="{Binding MaterialPosition}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10,0"/> | |||||
<TextBox Text="{Binding MaterialName}" Grid.Column="1" Width="140" | |||||
HorizontalAlignment="Center" VerticalAlignment="Center"></TextBox> | |||||
</Grid> | |||||
</Border> | |||||
</Border> | |||||
<ControlTemplate.Triggers> | |||||
<Trigger Property="IsMouseOver" Value="True"> | |||||
</Trigger> | |||||
</ControlTemplate.Triggers> | |||||
</ControlTemplate> | |||||
</Setter.Value> | |||||
</Setter> | |||||
</Style> | |||||
</UserControl.Resources> | </UserControl.Resources> | ||||
<Grid Background="#F3F6F9" Margin="20"> | <Grid Background="#F3F6F9" Margin="20"> | ||||
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible"> | |||||
<StackPanel> | |||||
<!--奶茶配方录入--> | |||||
<Expander Style="{StaticResource ExpanderStyle}"> | |||||
<Grid> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="40"/> | |||||
<RowDefinition Height="*"/> | |||||
</Grid.RowDefinitions> | |||||
<Button Content="奶茶配方录入" HorizontalAlignment="Right" VerticalAlignment="Center" Width="150" Click="Button_Click"/> | |||||
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" Grid.Row="1"> | |||||
<StackPanel> | |||||
<!--奶茶配方录入--> | |||||
<!--<Expander Style="{StaticResource ExpanderStyle}"> | |||||
<Expander.Header> | <Expander.Header> | ||||
<TextBlock Text="奶茶配方录入" /> | <TextBlock Text="奶茶配方录入" /> | ||||
</Expander.Header> | </Expander.Header> | ||||
@@ -154,128 +147,74 @@ | |||||
</DataGrid> | </DataGrid> | ||||
</Grid> | </Grid> | ||||
</Expander.Content> | </Expander.Content> | ||||
</Expander> | |||||
<!--配料录入--> | |||||
<Expander Grid.Row="1" Style="{StaticResource ExpanderStyle}"> | |||||
<Expander.Header> | |||||
<TextBlock Text="本地配料录入" /> | |||||
</Expander.Header> | |||||
<Expander.Content> | |||||
<Grid> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="70"/> | |||||
<RowDefinition Height="*"/> | |||||
</Grid.RowDefinitions> | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition Width="*"/> | |||||
<ColumnDefinition Width="*"/> | |||||
</Grid.ColumnDefinitions> | |||||
<Button Content="保存物料位置名称" Grid.ColumnSpan="2" Style="{StaticResource buttonNormal}" Height="34" Width="200" Command="{Binding UpdateMaterialPosionCommand}"/> | |||||
<DataGrid Grid.Row="1" Margin="50,5" AutoGenerateColumns="False" ItemsSource="{Binding materail1,Mode=TwoWay}" | |||||
FrozenColumnCount="1" RowHeight="34" | |||||
VerticalAlignment="Top" HorizontalAlignment="Right" | |||||
IsReadOnly="True" | |||||
CanUserResizeColumns="False" CanUserResizeRows="False" SelectionMode="Single" | |||||
CanUserReorderColumns="False" AlternationCount="2" RowHeaderWidth="0" CanUserAddRows="False"> | |||||
<DataGrid.Columns> | |||||
<DataGridTemplateColumn Header="物料位置" Width="170"> | |||||
<DataGridTemplateColumn.CellTemplate> | |||||
<DataTemplate> | |||||
<StackPanel Orientation="Horizontal" > | |||||
<TextBlock Foreground="Black" Text="{Binding MaterialPosion}" | |||||
VerticalAlignment="Center" HorizontalAlignment="Left" | |||||
Margin="5,0" FontSize="16"/> | |||||
</StackPanel> | |||||
</DataTemplate> | |||||
</DataGridTemplateColumn.CellTemplate> | |||||
</DataGridTemplateColumn> | |||||
<DataGridTemplateColumn Header="物料" Width="250"> | |||||
<DataGridTemplateColumn.CellTemplate> | |||||
<DataTemplate> | |||||
<TextBox Text="{Binding MaterialName ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" | |||||
VerticalAlignment="Center" HorizontalContentAlignment="Center" | |||||
VerticalContentAlignment="Center" | |||||
Margin="2" FontSize="16" | |||||
Width="160" Height="28" /> | |||||
</DataTemplate> | |||||
</DataGridTemplateColumn.CellTemplate> | |||||
</DataGridTemplateColumn> | |||||
</DataGrid.Columns> | |||||
</DataGrid> | |||||
<DataGrid Grid.Row="1" Grid.Column="1" Margin="50,5" AutoGenerateColumns="False" ItemsSource="{Binding materail2,Mode=TwoWay}" | |||||
FrozenColumnCount="1" RowHeight="34" | |||||
VerticalAlignment="Top" HorizontalAlignment="Left" | |||||
IsReadOnly="True" | |||||
CanUserResizeColumns="False" CanUserResizeRows="False" SelectionMode="Single" | |||||
CanUserReorderColumns="False" AlternationCount="2" RowHeaderWidth="0" CanUserAddRows="False"> | |||||
</Expander>--> | |||||
<!--配料录入--> | |||||
<Expander Grid.Row="1" Style="{StaticResource ExpanderStyle}"> | |||||
<Expander.Header> | |||||
<TextBlock Text="本地配料录入" /> | |||||
</Expander.Header> | |||||
<Expander.Content> | |||||
<Grid> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="70"/> | |||||
<RowDefinition Height="*"/> | |||||
</Grid.RowDefinitions> | |||||
<Button Content="保存物料位置名称" Grid.ColumnSpan="2" Style="{StaticResource buttonNormal}" Height="34" Width="200" | |||||
Command="{Binding UpdateMaterialPosionCommand}"/> | |||||
<ListView ItemsSource="{Binding localMaterails}" Grid.Row="1" | |||||
Width="800" ScrollViewer.HorizontalScrollBarVisibility="Disabled" | |||||
HorizontalAlignment="Center" VerticalAlignment="Center"> | |||||
<ListView.ItemsPanel> | |||||
<ItemsPanelTemplate> | |||||
<WrapPanel Margin="10"/> | |||||
</ItemsPanelTemplate> | |||||
</ListView.ItemsPanel> | |||||
</ListView> | |||||
</Grid> | |||||
</Expander.Content> | |||||
</Expander> | |||||
<!--奶茶清单--> | |||||
<Expander Grid.Row="2" Style="{StaticResource ExpanderStyle}" > | |||||
<Expander.Header> | |||||
<TextBlock Text="本地奶茶配方"/> | |||||
</Expander.Header> | |||||
<Expander.Content> | |||||
<DataGrid Grid.Row="4" Margin="100,5" AutoGenerateColumns="False" RowHeight="32" ItemsSource="{Binding localMaterialRecipes}" Width="500" | |||||
FrozenColumnCount="1" | |||||
VerticalAlignment="Top" | |||||
IsReadOnly="True" | |||||
CanUserResizeColumns="False" CanUserResizeRows="False" SelectionMode="Single" | |||||
CanUserReorderColumns="False" AlternationCount="2" RowHeaderWidth="0" CanUserAddRows="False"> | |||||
<DataGrid.Columns> | <DataGrid.Columns> | ||||
<DataGridTemplateColumn Header="物料位置" Width="170"> | |||||
<DataGridTemplateColumn Header="奶茶" Width="200"> | |||||
<DataGridTemplateColumn.CellTemplate> | <DataGridTemplateColumn.CellTemplate> | ||||
<DataTemplate> | <DataTemplate> | ||||
<StackPanel Orientation="Horizontal" > | <StackPanel Orientation="Horizontal" > | ||||
<TextBlock Foreground="Black" Text="{Binding MaterialPosion}" | |||||
VerticalAlignment="Center" HorizontalAlignment="Left" | |||||
Margin="5,0" FontSize="16"/> | |||||
<TextBlock Text="{Binding RecipeName}" Foreground="Black" | |||||
VerticalAlignment="Center" HorizontalAlignment="Center" | |||||
Margin="5,2" FontSize="16"/> | |||||
</StackPanel> | </StackPanel> | ||||
</DataTemplate> | </DataTemplate> | ||||
</DataGridTemplateColumn.CellTemplate> | </DataGridTemplateColumn.CellTemplate> | ||||
</DataGridTemplateColumn> | </DataGridTemplateColumn> | ||||
<DataGridTemplateColumn Header="物料" Width="250"> | |||||
<DataGridTemplateColumn Header="操作" Width="*"> | |||||
<DataGridTemplateColumn.CellTemplate> | <DataGridTemplateColumn.CellTemplate> | ||||
<DataTemplate> | <DataTemplate> | ||||
<TextBox Text="{Binding MaterialName ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" | |||||
VerticalAlignment="Center" HorizontalContentAlignment="Center" | |||||
VerticalContentAlignment="Center" | |||||
Margin="2" Height="28" | |||||
Width="160" FontSize="16"/> | |||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"> | |||||
<Button Content="删除" Margin="2" | |||||
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.DeleteRecipeCommand}" | |||||
CommandParameter="{Binding RecipeID}"/> | |||||
</StackPanel> | |||||
</DataTemplate> | </DataTemplate> | ||||
</DataGridTemplateColumn.CellTemplate> | </DataGridTemplateColumn.CellTemplate> | ||||
</DataGridTemplateColumn> | </DataGridTemplateColumn> | ||||
</DataGrid.Columns> | </DataGrid.Columns> | ||||
</DataGrid> | </DataGrid> | ||||
</Grid> | |||||
</Expander.Content> | |||||
</Expander> | |||||
<!--奶茶清单--> | |||||
<Expander Grid.Row="2" Style="{StaticResource ExpanderStyle}" > | |||||
<Expander.Header> | |||||
<TextBlock Text="本地奶茶配方"/> | |||||
</Expander.Header> | |||||
<Expander.Content> | |||||
<DataGrid Grid.Row="4" Margin="100,5" AutoGenerateColumns="False" RowHeight="32" ItemsSource="{Binding localMaterialRecipes}" Width="500" | |||||
FrozenColumnCount="1" | |||||
VerticalAlignment="Top" | |||||
IsReadOnly="True" | |||||
CanUserResizeColumns="False" CanUserResizeRows="False" SelectionMode="Single" | |||||
CanUserReorderColumns="False" AlternationCount="2" RowHeaderWidth="0" CanUserAddRows="False"> | |||||
<DataGrid.Columns> | |||||
<DataGridTemplateColumn Header="奶茶" Width="200"> | |||||
<DataGridTemplateColumn.CellTemplate> | |||||
<DataTemplate> | |||||
<StackPanel Orientation="Horizontal" > | |||||
<TextBlock Text="{Binding GoodNames}" Foreground="Black" | |||||
VerticalAlignment="Center" HorizontalAlignment="Center" | |||||
Margin="5,2" FontSize="16"/> | |||||
</StackPanel> | |||||
</DataTemplate> | |||||
</DataGridTemplateColumn.CellTemplate> | |||||
</DataGridTemplateColumn> | |||||
<DataGridTemplateColumn Header="操作" Width="*"> | |||||
<DataGridTemplateColumn.CellTemplate> | |||||
<DataTemplate> | |||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"> | |||||
<Button Content="删除" Margin="2" | |||||
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.DeleteRecipeCommand}" | |||||
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=SelectedIndex}" /> | |||||
</StackPanel> | |||||
</DataTemplate> | |||||
</DataGridTemplateColumn.CellTemplate> | |||||
</DataGridTemplateColumn> | |||||
</DataGrid.Columns> | |||||
</DataGrid> | |||||
</Expander.Content> | |||||
</Expander> | |||||
</StackPanel> | |||||
</ScrollViewer> | |||||
</Expander.Content> | |||||
</Expander> | |||||
</StackPanel> | |||||
</ScrollViewer> | |||||
</Grid> | |||||
</Grid> | </Grid> | ||||
</UserControl> | </UserControl> |
@@ -1,4 +1,5 @@ | |||||
using System; | |||||
using BPASmartClient.MilkWithTea.ViewModel; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | using System.Linq; | ||||
using System.Text; | using System.Text; | ||||
@@ -24,5 +25,11 @@ namespace BPASmartClient.MilkWithTea.View | |||||
{ | { | ||||
InitializeComponent(); | InitializeComponent(); | ||||
} | } | ||||
private void Button_Click(object sender, RoutedEventArgs e) | |||||
{ | |||||
RecipeConfige recipeConfige = new RecipeConfige(); | |||||
recipeConfige.ShowDialog(); | |||||
} | |||||
} | } | ||||
} | } |
@@ -168,11 +168,11 @@ | |||||
<TextBlock Text="配方" Grid.Row="2" Grid.Column="1" Margin="10" FontSize="22" /> | <TextBlock Text="配方" Grid.Row="2" Grid.Column="1" Margin="10" FontSize="22" /> | ||||
<Border BorderBrush="#D5DFE5" BorderThickness="4" Grid.Row="3" Margin="20,0,0,0"> | <Border BorderBrush="#D5DFE5" BorderThickness="4" Grid.Row="3" Margin="20,0,0,0"> | ||||
<ListBox ItemsSource="{Binding localTeaWithMilks}" SelectionChanged="ListBox_SelectionChanged" IsEnabled="{Binding MakeEnable}" | <ListBox ItemsSource="{Binding localTeaWithMilks}" SelectionChanged="ListBox_SelectionChanged" IsEnabled="{Binding MakeEnable}" | ||||
Foreground="LightSlateGray"> | |||||
Foreground="LightSlateGray" SelectedValue="{Binding SelectedRecipe,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> | |||||
<ListBox.ItemTemplate> | <ListBox.ItemTemplate> | ||||
<DataTemplate > | <DataTemplate > | ||||
<Grid> | <Grid> | ||||
<TextBlock Text="{Binding GoodNames}" Margin="5,10" FontSize="22" | |||||
<TextBlock Text="{Binding RecipeName}" Margin="5,10" FontSize="22" | |||||
Background="Transparent" /> | Background="Transparent" /> | ||||
</Grid> | </Grid> | ||||
</DataTemplate> | </DataTemplate> | ||||
@@ -181,7 +181,7 @@ | |||||
</Border> | </Border> | ||||
<ListBox x:Name="recipeList" Grid.Row="3" Grid.Column="1" Margin="5,10" | <ListBox x:Name="recipeList" Grid.Row="3" Grid.Column="1" Margin="5,10" | ||||
ItemsSource="{Binding materialRecipes}" FontSize="18" | |||||
ItemsSource="{Binding localMaterails}" FontSize="18" | |||||
Width="200" HorizontalAlignment="Left" Foreground="LightSlateGray"> | Width="200" HorizontalAlignment="Left" Foreground="LightSlateGray"> | ||||
<ListBox.ItemTemplate> | <ListBox.ItemTemplate> | ||||
<DataTemplate > | <DataTemplate > | ||||
@@ -191,7 +191,7 @@ | |||||
<ColumnDefinition Width="40"/> | <ColumnDefinition Width="40"/> | ||||
<ColumnDefinition Width="15"/> | <ColumnDefinition Width="15"/> | ||||
</Grid.ColumnDefinitions> | </Grid.ColumnDefinitions> | ||||
<TextBlock Text="{Binding Material}" Margin="20,10" FontSize="16"/> | |||||
<TextBlock Text="{Binding MaterialName}" Margin="20,10" FontSize="16"/> | |||||
<TextBlock Text="{Binding MaterialWeight}" Margin="5,10,0,10" Grid.Column="1" HorizontalAlignment="Left" /> | <TextBlock Text="{Binding MaterialWeight}" Margin="5,10,0,10" Grid.Column="1" HorizontalAlignment="Left" /> | ||||
<TextBlock Text="g" Margin="0,10" HorizontalAlignment="Right" Grid.Column="2"/> | <TextBlock Text="g" Margin="0,10" HorizontalAlignment="Right" Grid.Column="2"/> | ||||
</Grid> | </Grid> | ||||
@@ -1,5 +1,4 @@ | |||||
using BPASmartClient.MilkWithTea.ViewModel; | using BPASmartClient.MilkWithTea.ViewModel; | ||||
using Model; | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | using System.Linq; | ||||
@@ -29,9 +28,9 @@ namespace BPASmartClient.MilkWithTea.View | |||||
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) | private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) | ||||
{ | { | ||||
if((sender as ListBox).SelectedItem is LocalTeaWithMilkConfig config) | |||||
if((sender as ListBox).SelectedItem is LocalRecipe config) | |||||
{ | { | ||||
recipeList.ItemsSource = config.materialRecipes; | |||||
recipeList.ItemsSource = config.localMaterails; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -11,13 +11,7 @@ | |||||
<vm:PatrameterSettiongViewModel/> | <vm:PatrameterSettiongViewModel/> | ||||
</UserControl.DataContext> | </UserControl.DataContext> | ||||
<UserControl.Resources> | <UserControl.Resources> | ||||
<Style TargetType="TextBlock"> | |||||
<Setter Property="FontSize" Value="18"/> | |||||
<Setter Property="Foreground" Value="DarkSlateGray"/> | |||||
<Setter Property="VerticalAlignment" Value="Center"/> | |||||
<Setter Property="HorizontalAlignment" Value="Center"/> | |||||
<Setter Property="FontSize" Value="18"/> | |||||
</Style> | |||||
</UserControl.Resources> | </UserControl.Resources> | ||||
<Grid Background="#F3F6F9" Margin="20" > | <Grid Background="#F3F6F9" Margin="20" > | ||||
<Grid.ColumnDefinitions> | <Grid.ColumnDefinitions> | ||||
@@ -40,18 +34,18 @@ | |||||
<StackPanel Orientation="Horizontal"> | <StackPanel Orientation="Horizontal"> | ||||
<TextBlock Text="通道口:"/> | <TextBlock Text="通道口:"/> | ||||
<ComboBox ItemsSource="{Binding materialPosions}" | <ComboBox ItemsSource="{Binding materialPosions}" | ||||
SelectedIndex="{Binding MaterialID ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" | |||||
SelectedValue="{Binding MaterialID ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" | |||||
Margin="10,0" Width="120 " Style="{StaticResource cmbstyle}"/> | Margin="10,0" Width="120 " Style="{StaticResource cmbstyle}"/> | ||||
<TextBlock Text="出料量:" Margin="10,0,0,0" /> | <TextBlock Text="出料量:" Margin="10,0,0,0" /> | ||||
<TextBox Text="{Binding OutMaterailWeight}" Width="60" Margin="10,0" VerticalContentAlignment="Center"/> | <TextBox Text="{Binding OutMaterailWeight}" Width="60" Margin="10,0" VerticalContentAlignment="Center"/> | ||||
<TextBlock Text="g" Margin="2,0"/> | <TextBlock Text="g" Margin="2,0"/> | ||||
<Button Content="出料" Style="{StaticResource buttonNormal}" Height="36" Width="100" Margin="30,0" Command="{Binding OutMaterailCommad}"/> | <Button Content="出料" Style="{StaticResource buttonNormal}" Height="36" Width="100" Margin="30,0" Command="{Binding OutMaterailCommad}"/> | ||||
<TextBlock Text="转盘位置:" Margin="60,0,10,0"/> | |||||
<ComboBox ItemsSource="{Binding TurntablePosion}" | |||||
<!--<TextBlock Text="转盘位置:" Margin="60,0,10,0"/>--> | |||||
<!--<ComboBox ItemsSource="{Binding TurntablePosion}" | |||||
SelectedIndex="{Binding TurntableID,Mode=TwoWay ,UpdateSourceTrigger=PropertyChanged}" | SelectedIndex="{Binding TurntableID,Mode=TwoWay ,UpdateSourceTrigger=PropertyChanged}" | ||||
Margin="10,0" Width="100 " Style="{StaticResource cmbstyle}"/> | Margin="10,0" Width="100 " Style="{StaticResource cmbstyle}"/> | ||||
<Button Content="转动" Style="{StaticResource buttonNormal}" Height="36" Width="80" Margin="30,0" | <Button Content="转动" Style="{StaticResource buttonNormal}" Height="36" Width="80" Margin="30,0" | ||||
Command="{Binding TurntableCommad}"/> | |||||
Command="{Binding TurntableCommad}"/>--> | |||||
</StackPanel> | </StackPanel> | ||||
<CheckBox Grid.Row="2" Content="禁用本地奶茶下单" HorizontalAlignment="Left" Margin="0,10" | <CheckBox Grid.Row="2" Content="禁用本地奶茶下单" HorizontalAlignment="Left" Margin="0,10" | ||||
HorizontalContentAlignment="Center" VerticalContentAlignment="Center" | HorizontalContentAlignment="Center" VerticalContentAlignment="Center" | ||||
@@ -84,7 +78,7 @@ | |||||
<TextBlock Text="校正后的重量" Grid.Column="5"/> | <TextBlock Text="校正后的重量" Grid.Column="5"/> | ||||
<TextBlock Text="出料时间" Grid.Column="3"/> | <TextBlock Text="出料时间" Grid.Column="3"/> | ||||
<ComboBox Grid.Row="1" Width="100" Style="{StaticResource cmbstyle}" ItemsSource="{Binding materialPosions}" | |||||
<ComboBox Grid.Row="1" Width="100" Style="{StaticResource cmbstyle}" ItemsSource="{Binding materialPosions}" Height="30" | |||||
SelectedIndex="{Binding CorrectPassway ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectionChanged="ComboBox_SelectionChanged" /> | SelectedIndex="{Binding CorrectPassway ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectionChanged="ComboBox_SelectionChanged" /> | ||||
<TextBlock Grid.Row="1" Grid.Column="1" ></TextBlock> | <TextBlock Grid.Row="1" Grid.Column="1" ></TextBlock> | ||||
<CheckBox x:Name="OpenIsCheck" | <CheckBox x:Name="OpenIsCheck" | ||||
@@ -126,16 +120,31 @@ | |||||
<RowDefinition Height="*"/> | <RowDefinition Height="*"/> | ||||
<RowDefinition Height="*"/> | <RowDefinition Height="*"/> | ||||
<RowDefinition Height="*"/> | <RowDefinition Height="*"/> | ||||
<RowDefinition Height="10"/> | |||||
</Grid.RowDefinitions> | </Grid.RowDefinitions> | ||||
<TextBlock Text="店铺名称:" Grid.ColumnSpan="2" FontSize="22" Height="28" Width="94" HorizontalAlignment="Left" Margin="20,0"/> | <TextBlock Text="店铺名称:" Grid.ColumnSpan="2" FontSize="22" Height="28" Width="94" HorizontalAlignment="Left" Margin="20,0"/> | ||||
<TextBox Text="{Binding ShopName}" Grid.Column="2" Grid.ColumnSpan="2" Margin="-20,10,30,10" VerticalContentAlignment="Center"/> | <TextBox Text="{Binding ShopName}" Grid.Column="2" Grid.ColumnSpan="2" Margin="-20,10,30,10" VerticalContentAlignment="Center"/> | ||||
<TextBlock Text="店铺ID:" Grid.Row="1" Height="23" Width="60" HorizontalAlignment="Left" Margin="20,0"/> | <TextBlock Text="店铺ID:" Grid.Row="1" Height="23" Width="60" HorizontalAlignment="Left" Margin="20,0"/> | ||||
<TextBlock Text="设备ID:" Grid.Column="2" Grid.Row="1" Height="23" Width="60" /> | <TextBlock Text="设备ID:" Grid.Column="2" Grid.Row="1" Height="23" Width="60" /> | ||||
<TextBlock Text="PLC地址:" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Height="23" Width="72" HorizontalAlignment="Left" Margin="20,0"/> | |||||
<TextBox Text="{Binding ShopID}" Width="60" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalContentAlignment="Center" Margin="0,12"/> | <TextBox Text="{Binding ShopID}" Width="60" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalContentAlignment="Center" Margin="0,12"/> | ||||
<TextBox Text="{Binding DeviceID}" Width="60" Grid.Column="3" Grid.Row="1" HorizontalAlignment="Left" VerticalContentAlignment="Center" Margin="0,12"/> | <TextBox Text="{Binding DeviceID}" Width="60" Grid.Column="3" Grid.Row="1" HorizontalAlignment="Left" VerticalContentAlignment="Center" Margin="0,12"/> | ||||
<TextBox Text="{Binding PLCAdress}" Grid.Column="2" Grid.Row="2" Grid.ColumnSpan="2" Margin="-20,10,30,10" | |||||
<RadioButton Content="网口" GroupName="a" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" | |||||
Command="{Binding ChangeCommunationCommand}"/> | |||||
<StackPanel Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Orientation="Horizontal" Visibility="{Binding VsIP}" | |||||
HorizontalAlignment="Center" VerticalAlignment="Center"> | |||||
<TextBlock Text="IP:" Height="23" Margin="20,0"/> | |||||
<TextBox Text="{Binding PLCAdress}" Margin="0,10,30,10" Width="160" | |||||
VerticalContentAlignment="Center"/> | VerticalContentAlignment="Center"/> | ||||
</StackPanel> | |||||
<RadioButton Content="串口" GroupName="a" Grid.Row="3" HorizontalAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" | |||||
IsChecked="{Binding IsPort}" Command="{Binding ChangeCommunationCommand}"/> | |||||
<StackPanel Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3" Orientation="Horizontal" Visibility="{Binding VsPort}"> | |||||
<TextBlock Text="串口号:" /> | |||||
<ComboBox Style="{DynamicResource cmbstyle}" Height="26" Width="100" ItemsSource="{Binding Ports}" | |||||
SelectedValue="{Binding Prot}"/> | |||||
</StackPanel> | |||||
<Button Style="{StaticResource buttonNormal}" | <Button Style="{StaticResource buttonNormal}" | ||||
Grid.Column="4" Grid.ColumnSpan="2" Grid.Row="0" Grid.RowSpan="3" | Grid.Column="4" Grid.ColumnSpan="2" Grid.Row="0" Grid.RowSpan="3" | ||||
@@ -0,0 +1,135 @@ | |||||
<Window x:Class="BPASmartClient.MilkWithTea.View.RecipeConfige" | |||||
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:BPASmartClient.MilkWithTea.View" | |||||
xmlns:vm="clr-namespace:BPASmartClient.MilkWithTea.ViewModel" | |||||
mc:Ignorable="d" | |||||
Title="RecipeConfige" | |||||
Height="800" Width="800" WindowStartupLocation="CenterScreen" WindowStyle="None" AllowsTransparency="True" | |||||
> | |||||
<Window.DataContext> | |||||
<vm:RecipeConfigeViewModel/> | |||||
</Window.DataContext> | |||||
<Window.Resources> | |||||
</Window.Resources> | |||||
<Grid> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="60"/> | |||||
<RowDefinition Height="*"/> | |||||
<RowDefinition Height="*"/> | |||||
</Grid.RowDefinitions> | |||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"> | |||||
<TextBlock Text="奶茶名称" Margin="10,0" /> | |||||
<TextBox Text="{Binding Name}" Width="120" Foreground="DarkSlateGray" Margin="10,0"/> | |||||
<Button Content="添加配料" Margin="10,0" Width="100" Command="{Binding AddMaterialCommand}"/> | |||||
<Button Content="保存" Margin="10,0" Width="100" Command="{Binding SaveCommand}"/> | |||||
<Button Content="取消" Margin="10,0" Width="100" Click="Button_Click"/> | |||||
</StackPanel> | |||||
<Grid Grid.Row="1"> | |||||
<ScrollViewer | |||||
HorizontalScrollBarVisibility="Hidden" | |||||
VerticalScrollBarVisibility="Auto"> | |||||
<ItemsControl ItemsSource="{Binding Materails}" > | |||||
<ItemsControl.ItemTemplate> | |||||
<DataTemplate> | |||||
<RadioButton GroupName="all"> | |||||
<RadioButton.Template> | |||||
<ControlTemplate TargetType="RadioButton"> | |||||
<Grid Name="gr" Height="40" Margin="20,0"> | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition Width="2*"/> | |||||
<ColumnDefinition Width="2*"/> | |||||
<ColumnDefinition Width="2*" /> | |||||
</Grid.ColumnDefinitions> | |||||
<ComboBox Name="cb" Width="120" Height="30" | |||||
ItemsSource="{Binding DataContext.materialNames, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}" | |||||
SelectedValue="{Binding MaterialID}" | |||||
SelectedValuePath="Key" DisplayMemberPath="Value"/> | |||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> | |||||
<TextBox Text="{Binding MaterialWeight}" Width="120" Margin="10,0"/> | |||||
<TextBlock Text="g" /> | |||||
</StackPanel> | |||||
<Button Grid.Column="2" | |||||
Width="70" | |||||
Height="25" | |||||
Margin="15,0,0,0" | |||||
FontSize="16" | |||||
BorderBrush="#FF2AB2E7" | |||||
BorderThickness="1" | |||||
HorizontalAlignment="Left" | |||||
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}" | |||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" | |||||
Content="删 除" /> | |||||
</Grid> | |||||
</ControlTemplate> | |||||
</RadioButton.Template> | |||||
</RadioButton> | |||||
</DataTemplate> | |||||
</ItemsControl.ItemTemplate> | |||||
</ItemsControl> | |||||
</ScrollViewer> | |||||
</Grid> | |||||
<Grid Grid.Row="2"> | |||||
<ListBox x:Name="listview1" AllowDrop="True" SelectionMode="Extended" MouseMove="listview1_MouseMove" | |||||
ItemsSource="{Binding Materails}" PreviewMouseLeftButtonUp="listview1_MouseLeftButtonUp"> | |||||
<ListBox.ItemTemplate> | |||||
<DataTemplate> | |||||
<Border PreviewMouseLeftButtonDown="listview1_MouseLeftButtonDown" Width="800" BorderBrush="Black" BorderThickness="1" Background="White" | |||||
> | |||||
<RadioButton GroupName="all" > | |||||
<RadioButton.Template> | |||||
<ControlTemplate TargetType="RadioButton"> | |||||
<Grid Name="gr" Height="40" Margin="20,0"> | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition Width="2*"/> | |||||
<ColumnDefinition Width="2*"/> | |||||
<ColumnDefinition Width="2*" /> | |||||
</Grid.ColumnDefinitions> | |||||
<ComboBox Name="cb" Width="120" Height="30" | |||||
ItemsSource="{Binding DataContext.materialNames, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}" | |||||
SelectedValue="{Binding MaterialID }" | |||||
SelectedValuePath="Key" DisplayMemberPath="Value"/> | |||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> | |||||
<TextBox Text="{Binding MaterialWeight}" Width="120" Margin="10,0"/> | |||||
<TextBlock Text="g" /> | |||||
</StackPanel> | |||||
<Button Grid.Column="2" | |||||
Width="70" | |||||
Height="25" | |||||
Margin="15,0,0,0" | |||||
FontSize="16" | |||||
BorderBrush="#FF2AB2E7" | |||||
BorderThickness="1" | |||||
HorizontalAlignment="Left" | |||||
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}" | |||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" | |||||
Content="删 除" /> | |||||
</Grid> | |||||
</ControlTemplate> | |||||
</RadioButton.Template> | |||||
</RadioButton> | |||||
</Border> | |||||
</DataTemplate> | |||||
</ListBox.ItemTemplate> | |||||
</ListBox> | |||||
</Grid> | |||||
</Grid> | |||||
</Window> |
@@ -0,0 +1,174 @@ | |||||
using BPASmartClient.MilkWithTea.ViewModel; | |||||
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.Controls.Primitives; | |||||
using System.Windows.Data; | |||||
using System.Windows.Documents; | |||||
using System.Windows.Input; | |||||
using System.Windows.Media; | |||||
using System.Windows.Media.Effects; | |||||
using System.Windows.Media.Imaging; | |||||
using System.Windows.Shapes; | |||||
namespace BPASmartClient.MilkWithTea.View | |||||
{ | |||||
/// <summary> | |||||
/// RecipeConfige.xaml 的交互逻辑 | |||||
/// </summary> | |||||
public partial class RecipeConfige : Window | |||||
{ | |||||
double X,Y; | |||||
Border ultUE; | |||||
Popup mypopup; | |||||
ListBoxItem OldItem; | |||||
public RecipeConfige() | |||||
{ | |||||
InitializeComponent(); | |||||
ActionManage.GetInstance.CancelRegister("RecipeConfigeViewClose"); | |||||
ActionManage.GetInstance.Register(new Action(()=> this.Close()), "RecipeConfigeViewClose"); | |||||
} | |||||
private void Button_Click(object sender, RoutedEventArgs e) | |||||
{ | |||||
this.Close(); | |||||
} | |||||
private int GetCurrentIndex(GetPositionDelegate getPosition) | |||||
{ | |||||
int index = -1; | |||||
for (int i = 0; i < listview1.Items.Count; ++i) | |||||
{ | |||||
ListViewItem item = GetListViewItem(i); | |||||
if (item != null && this.IsMouseOverTarget(item, getPosition)) | |||||
{ | |||||
index = i; | |||||
break; | |||||
} | |||||
} | |||||
return index; | |||||
} | |||||
private bool IsMouseOverTarget(Visual target, GetPositionDelegate getPosition) | |||||
{ | |||||
Rect bounds = VisualTreeHelper.GetDescendantBounds(target); | |||||
Point mousePos = getPosition((IInputElement)target); | |||||
return bounds.Contains(mousePos); | |||||
} | |||||
delegate Point GetPositionDelegate(IInputElement element); | |||||
ListViewItem GetListViewItem(int index) | |||||
{ | |||||
if (listview1.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) | |||||
return null; | |||||
return listview1.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem; | |||||
} | |||||
private void CloneVisual(Border border, MouseButtonEventArgs e) | |||||
{ | |||||
ListBoxItem listBoxItem = new ListBoxItem(); | |||||
Point ptLeftUp = new Point(0, 0); | |||||
ptLeftUp = listview1.PointToScreen(ptLeftUp); | |||||
mypopup = new Popup(); | |||||
double y = e.GetPosition(listview1).Y; | |||||
double x = e.GetPosition(listview1).X; | |||||
VisualBrush brush = new VisualBrush(border); | |||||
Rectangle rect = new Rectangle(); | |||||
rect.Width = border.ActualWidth; | |||||
rect.Height = border.ActualHeight; | |||||
rect.Fill = brush; | |||||
rect.Opacity = border.Opacity; | |||||
border.Opacity = 0.8; | |||||
mypopup.Child = rect; | |||||
mypopup.AllowsTransparency = true; | |||||
mypopup.HorizontalOffset = ptLeftUp.X + x - ((FrameworkElement)ultUE).ActualWidth / 2; | |||||
mypopup.VerticalOffset = ptLeftUp.Y + y - ((FrameworkElement)ultUE).ActualHeight / 2; | |||||
mypopup.IsOpen = true; | |||||
} | |||||
private void listview1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) | |||||
{ | |||||
var pos = e.GetPosition(listview1); | |||||
HitTestResult result = VisualTreeHelper.HitTest(listview1, pos); | |||||
OldItem = Utils.FindVisualParent<ListBoxItem>(result.VisualHit); | |||||
if(OldItem != null) | |||||
{ | |||||
if (e.Source is Border) | |||||
{ | |||||
ultUE = (Border)e.Source; | |||||
ultUE.CaptureMouse(); | |||||
ultUE.Visibility = Visibility.Collapsed; | |||||
CloneVisual(ultUE, e); | |||||
} | |||||
} | |||||
} | |||||
private void listview1_MouseMove(object sender, MouseEventArgs e) | |||||
{ | |||||
Point ptLeftUp = new Point(0, 0); | |||||
Point ptRightDown = new Point(this.ActualWidth, this.ActualHeight); | |||||
ptLeftUp = listview1.PointToScreen(ptLeftUp); | |||||
ptRightDown = listview1.PointToScreen(ptRightDown); | |||||
double y = e.GetPosition(listview1).Y; | |||||
double x = e.GetPosition(listview1).X; | |||||
if (mypopup != null) | |||||
{ | |||||
mypopup.HorizontalOffset = ptLeftUp.X + x - ((FrameworkElement)ultUE).ActualWidth / 2; | |||||
mypopup.VerticalOffset = ptLeftUp.Y + y - ((FrameworkElement)ultUE).ActualHeight / 2; | |||||
} | |||||
} | |||||
private void listview1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) | |||||
{ | |||||
if(mypopup != null) | |||||
{ | |||||
mypopup.IsOpen = false; | |||||
mypopup = null; | |||||
} | |||||
if (OldItem == null) return; | |||||
var pos = e.GetPosition(listview1); | |||||
HitTestResult result = VisualTreeHelper.HitTest(listview1, pos); | |||||
if(result == null) return; | |||||
var Newitem = Utils.FindVisualParent<ListBoxItem>(result.VisualHit); | |||||
if (Newitem == null) return; | |||||
if (OldItem == Newitem) return; | |||||
int iold = listview1.Items.IndexOf((LocalMaterail)OldItem.DataContext); | |||||
int inew = listview1.Items.IndexOf((LocalMaterail)Newitem.DataContext); | |||||
RecipeConfigeViewModel.Materails.Move(iold,inew); | |||||
} | |||||
} | |||||
internal static class Utils | |||||
{ | |||||
//根据子元素查找父元素 | |||||
public static T FindVisualParent<T>(DependencyObject obj) where T : class | |||||
{ | |||||
while (obj != null) | |||||
{ | |||||
if (obj is T) | |||||
return obj as T; | |||||
obj = VisualTreeHelper.GetParent(obj); | |||||
} | |||||
return null; | |||||
} | |||||
} | |||||
} |
@@ -1,7 +1,5 @@ | |||||
using BPASmartClient.MorkTM; | |||||
using Microsoft.Toolkit.Mvvm.ComponentModel; | |||||
using Microsoft.Toolkit.Mvvm.Input; | |||||
using Model; | |||||
using BPASmartClient.MorkMOC; | |||||
using CommunityToolkit.Mvvm.Input; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -14,56 +12,34 @@ using System.Windows; | |||||
namespace BPASmartClient.MilkWithTea.ViewModel | namespace BPASmartClient.MilkWithTea.ViewModel | ||||
{ | { | ||||
public class LocalConfigureViewModel : ObservableObject | |||||
partial class LocalConfigureViewModel : ObservableObject | |||||
{ | { | ||||
#region 奶茶配方录入 | |||||
/// <summary> | |||||
/// 奶茶配方 | |||||
/// </summary> | |||||
public ObservableCollection<MaterialRecipe> materialRecipes { get => materialRecipes1; set => materialRecipes1 = value; } | |||||
/// <summary> | |||||
/// 出料集合 | |||||
/// </summary> | |||||
public ObservableCollection<string> MaterailList { get; set; } = new ObservableCollection<string>(); | |||||
/// <summary> | |||||
/// 奶茶名称 | |||||
/// </summary> | |||||
public string LocalGoodName { get { return _localGoodName; } set { _localGoodName = value; OnPropertyChanged(); } } | |||||
private string _localGoodName; | |||||
private ObservableCollection<MaterialRecipe> materialRecipes1 = new ObservableCollection<MaterialRecipe>(); | |||||
/// <summary> | |||||
/// 添加一条配方 | |||||
/// </summary> | |||||
public RelayCommand AddRecipeCommand { get; set; } | |||||
/// <summary> | |||||
/// 删除一条配方 | |||||
/// </summary> | |||||
public RelayCommand<object> RemoveRecipeCommand { get; set; } | |||||
/// <summary> | |||||
/// 取消配方 | |||||
/// </summary> | |||||
public RelayCommand RecipeCancelCommand { get; set; } | |||||
/// <summary> | |||||
/// 保存配方 | |||||
/// </summary> | |||||
public RelayCommand SaveRecipeCommand { get; set; } | |||||
#endregion | |||||
#region 本地奶茶配方 | #region 本地奶茶配方 | ||||
/// <summary> | /// <summary> | ||||
/// 本地奶茶配方列表 | /// 本地奶茶配方列表 | ||||
/// </summary> | /// </summary> | ||||
public ObservableCollection<LocalTeaWithMilkConfig> localMaterialRecipes { get; set; } = GLobal.MaterialRecipes; | |||||
public ObservableCollection<LocalRecipe> localMaterialRecipes { get; set; } = Json<JsonLocalRecipes>.Data.localRecipes; | |||||
/// <summary> | /// <summary> | ||||
/// 删除配方奶茶 | /// 删除配方奶茶 | ||||
/// </summary> | /// </summary> | ||||
public RelayCommand<object> DeleteRecipeCommand { get; set; } | |||||
[RelayCommand] | |||||
private void DeleteRecipe(object o) | |||||
{ | |||||
if (o == null) return; | |||||
if(o is string id) | |||||
{ | |||||
var res = localMaterialRecipes.FirstOrDefault(p => p.RecipeID == id); | |||||
if (res != null) | |||||
{ | |||||
localMaterialRecipes.Remove(res); | |||||
Json<JsonLocalRecipes>.Save(); | |||||
} | |||||
} | |||||
} | |||||
#endregion | #endregion | ||||
@@ -71,141 +47,26 @@ namespace BPASmartClient.MilkWithTea.ViewModel | |||||
/// <summary> | /// <summary> | ||||
/// 物料位置名称集合 | /// 物料位置名称集合 | ||||
/// </summary> | /// </summary> | ||||
public ObservableCollection<MaterailNameAndPosion> materailNameAndPosions { get; set; } = new ObservableCollection<MaterailNameAndPosion>(); | |||||
public List<MaterailNameAndPosion> materail1 { get; set; } = new List<MaterailNameAndPosion>(); | |||||
public List<MaterailNameAndPosion> materail2 { get; set; } = new List<MaterailNameAndPosion>(); | |||||
public ObservableCollection<LocalMaterail> localMaterails { get; set; } = Json<JsonLocalRecipes>.Data.localMaterails; | |||||
/// <summary> | /// <summary> | ||||
/// 更新物料位置 | /// 更新物料位置 | ||||
/// </summary> | /// </summary> | ||||
public RelayCommand UpdateMaterialPosionCommand { get; set; } | |||||
[RelayCommand] | |||||
private void UpdateMaterialPosion() | |||||
{ | |||||
Json<JsonLocalRecipes>.Save(); | |||||
} | |||||
#endregion | #endregion | ||||
public LocalConfigureViewModel() | public LocalConfigureViewModel() | ||||
{ | { | ||||
materialRecipes.Add(new MaterialRecipe() | |||||
{ | |||||
MaterialWeight = 10 | |||||
}); | |||||
AddRecipeCommand = new RelayCommand(new Action(() => | |||||
{ | |||||
materialRecipes.Add(new MaterialRecipe() | |||||
{ | |||||
MaterialID = materialRecipes.Count() + 1 | |||||
}); | |||||
})); | |||||
RemoveRecipeCommand = new RelayCommand<object>((o => | |||||
{ | |||||
if (o != null && o is int index) | |||||
{ | |||||
materialRecipes.RemoveAt(index); | |||||
for (int i = 0; i < materialRecipes.Count; i++)//ID排序 | |||||
{ | |||||
materialRecipes[i].MaterialID = i + 1; | |||||
} | |||||
} | |||||
})); | |||||
RecipeCancelCommand = new RelayCommand(new Action(() => | |||||
{ | |||||
materialRecipes.Clear(); | |||||
LocalGoodName = String.Empty; | |||||
})); | |||||
SaveRecipeCommand = new RelayCommand(new Action(() => | |||||
{ | |||||
if (LocalGoodName == "" || LocalGoodName == null) return; | |||||
if (materialRecipes.Count == 0) return; | |||||
localMaterialRecipes.Insert(0, new LocalTeaWithMilkConfig() | |||||
{ | |||||
GoodNames = LocalGoodName, | |||||
materialRecipes = materialRecipes | |||||
}); | |||||
UpdateLocalJosnData<LocalTeaWithMilkConfig>(GLobal.recipePath, localMaterialRecipes);//更新奶茶配方json文件 | |||||
MessageBox.Show("保存成功"); | |||||
})); | |||||
DeleteRecipeCommand = new RelayCommand<object>((o => | |||||
{ | |||||
if (o != null && o is int index) | |||||
{ | |||||
localMaterialRecipes.RemoveAt(index); | |||||
UpdateLocalJosnData<LocalTeaWithMilkConfig>(GLobal.recipePath, localMaterialRecipes);//更新奶茶配方json文件 | |||||
} | |||||
})); | |||||
UpdateMaterialPosionCommand = new RelayCommand(new Action(() => | |||||
{ | |||||
materailNameAndPosions.Clear(); | |||||
foreach(var item in materail1) | |||||
{ | |||||
materailNameAndPosions.Add(item); | |||||
} | |||||
foreach (var item in materail2) | |||||
{ | |||||
materailNameAndPosions.Add(item); | |||||
} | |||||
UpdateLocalJosnData<MaterailNameAndPosion>(GLobal.posionPath, materailNameAndPosions);//更新物料位置名称 | |||||
MaterailList.Clear(); | |||||
foreach (MaterailNameAndPosion m in materailNameAndPosions) | |||||
{ | |||||
if (m.MaterialName != null) MaterailList.Add(m.MaterialName); | |||||
} | |||||
})); | |||||
Init(); | |||||
} | |||||
/// <summary> | |||||
/// 界面初始化加载 | |||||
/// </summary> | |||||
private void Init() | |||||
{ | |||||
materailNameAndPosions = GLobal.GetJsonToT<MaterailNameAndPosion>(GLobal.posionPath); | |||||
if (materailNameAndPosions.Count == 0) | |||||
{ | |||||
foreach (MaterialPosion item in Enum.GetValues(typeof(MaterialPosion))) | |||||
{ | |||||
materailNameAndPosions.Add(new MaterailNameAndPosion() | |||||
{ | |||||
MaterialPosion = item.ToString() | |||||
}); | |||||
} | |||||
} | |||||
materail1 = materailNameAndPosions.Take<MaterailNameAndPosion>(14).ToList(); | |||||
materail2 = materailNameAndPosions.TakeLast<MaterailNameAndPosion>(14).ToList(); | |||||
foreach (MaterailNameAndPosion m in materailNameAndPosions) | |||||
{ | |||||
if (m.MaterialName != null) MaterailList.Add(m.MaterialName); | |||||
} | |||||
} | } | ||||
/// <summary> | |||||
/// 更新Json文件数据 | |||||
/// </summary> | |||||
/// <typeparam name="T"></typeparam> | |||||
/// <param name="path"></param> | |||||
/// <param name="ts"></param> | |||||
private void UpdateLocalJosnData<T>(string path, ObservableCollection<T> ts) | |||||
{ | |||||
if (ts != null) File.WriteAllText(path, JsonConvert.SerializeObject(ts)); | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,29 +1,22 @@ | |||||
using BPA.Message; | |||||
using BPA.Message.Enum; | |||||
using BPASmartClient.Device; | |||||
using BPASmartClient.EventBus; | |||||
| |||||
global using CommunityToolkit.Mvvm.Input; | |||||
using BPASmartClient.Helper; | using BPASmartClient.Helper; | ||||
using BPASmartClient.Model; | |||||
using Microsoft.Toolkit.Mvvm.ComponentModel; | |||||
using Microsoft.Toolkit.Mvvm.Input; | |||||
using Model; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.ObjectModel; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using System.Windows; | |||||
using BPASmartClient.Message; | |||||
namespace BPASmartClient.MilkWithTea.ViewModel | namespace BPASmartClient.MilkWithTea.ViewModel | ||||
{ | { | ||||
public class MainControlViewModel: ObservableObject | |||||
partial class MainControlViewModel: ObservableObject | |||||
{ | { | ||||
public ObservableCollection<LocalTeaWithMilkConfig> localTeaWithMilks { get; set; } = GLobal.MaterialRecipes; | |||||
/// <summary> | |||||
/// 本地奶茶列表 | |||||
/// </summary> | |||||
public ObservableCollection<LocalRecipe> localTeaWithMilks { get; set; } = Json<JsonLocalRecipes>.Data.localRecipes; | |||||
public ObservableCollection<MaterialRecipe> materialRecipes { get; set; } = new ObservableCollection<MaterialRecipe>(); | |||||
/// <summary> | |||||
/// 奶茶对应的原料列表 | |||||
/// </summary> | |||||
public ObservableCollection<LocalMaterail> materialRecipes { get; set; } = new ObservableCollection<LocalMaterail>(); | |||||
/// <summary> | /// <summary> | ||||
/// 订单状态列表 | /// 订单状态列表 | ||||
@@ -38,15 +31,16 @@ namespace BPASmartClient.MilkWithTea.ViewModel | |||||
/// <summary> | /// <summary> | ||||
/// 当前正在制作的奶茶 | /// 当前正在制作的奶茶 | ||||
/// </summary> | /// </summary> | ||||
public string CurrentGood { get { return _currentGood; } set { _currentGood = value; OnPropertyChanged(); } } | |||||
[ObservableProperty] | |||||
private string _currentGood = "茉莉花茶"; | private string _currentGood = "茉莉花茶"; | ||||
/// <summary> | /// <summary> | ||||
/// 奶茶制作百分比 | /// 奶茶制作百分比 | ||||
/// </summary> | /// </summary> | ||||
public string MakePercent { get { return _makePercent; } set { _makePercent = value; OnPropertyChanged(); } } | |||||
[ObservableProperty] | |||||
private string _makePercent = "0"; | private string _makePercent = "0"; | ||||
[ObservableProperty] | |||||
private LocalRecipe _selectedRecipe; | |||||
/// <summary> | /// <summary> | ||||
/// 当前正在制作的奶茶 | /// 当前正在制作的奶茶 | ||||
@@ -56,16 +50,31 @@ namespace BPASmartClient.MilkWithTea.ViewModel | |||||
/// <summary> | /// <summary> | ||||
/// 本地奶茶制作 | /// 本地奶茶制作 | ||||
/// </summary> | /// </summary> | ||||
public RelayCommand MakeGoodCommand { get; set; } | |||||
[RelayCommand] | |||||
private void MakeGood() | |||||
{ | |||||
if(SelectedRecipe == null) return; | |||||
foreach(var item in SelectedRecipe.localMaterails) | |||||
{ | |||||
var res = Json<JsonLocalRecipes>.Data.localMaterails.FirstOrDefault(p => p.MaterialID == item.MaterialID); | |||||
if ( res!= null) | |||||
{ | |||||
item.MaterialPosition = res.MaterialPosition; | |||||
} | |||||
else | |||||
{ | |||||
MessageLog.GetInstance.ShowEx($"配料:{item.MaterialName}不存在,下单失败"); | |||||
return; | |||||
} | |||||
} | |||||
ActionManage.GetInstance.Send( "MakeGoods",SelectedRecipe); | |||||
} | |||||
public MainControlViewModel() | public MainControlViewModel() | ||||
{ | { | ||||
MakeGoodCommand = new RelayCommand(new Action(() => | |||||
{ | |||||
})); | |||||
Init(); | Init(); | ||||
MorkOrderPush morkOrderPush = new MorkOrderPush() { GoodsName = "珍珠奶茶", SortNum = 1 }; | MorkOrderPush morkOrderPush = new MorkOrderPush() { GoodsName = "珍珠奶茶", SortNum = 1 }; | ||||
MorkOrderPush morkOrderPush1 = new MorkOrderPush() { GoodsName = "茉莉花茶", SortNum = 2 }; | MorkOrderPush morkOrderPush1 = new MorkOrderPush() { GoodsName = "茉莉花茶", SortNum = 2 }; | ||||
@@ -1,7 +1,6 @@ | |||||
using BPASmartClient.Helper; | |||||
global using Microsoft.Toolkit.Mvvm.ComponentModel; | |||||
using BPASmartClient.Helper; | |||||
using BPASmartClient.Model; | using BPASmartClient.Model; | ||||
using Microsoft.Toolkit.Mvvm.ComponentModel; | |||||
using Model; | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.IO; | using System.IO; | ||||
@@ -17,23 +16,23 @@ namespace BPASmartClient.MilkWithTea.ViewModel | |||||
public MainWindowVeiwModel() | public MainWindowVeiwModel() | ||||
{ | { | ||||
init(); | |||||
} | |||||
private void init() | |||||
{ | |||||
string path = Path.Combine(Environment.CurrentDirectory, "AccessFile", "Recipes"); | |||||
//判断文件夹是否存在,如果不存在就创建file文件夹 | |||||
if (!Directory.Exists(path)) | |||||
Json<JsonLocalRecipes>.Read(); | |||||
Json<JsonDeviceConfig>.Read(); | |||||
if (Json<JsonLocalRecipes>.Data.localMaterails.Count<14) | |||||
{ | { | ||||
Directory.CreateDirectory(path); | |||||
Json<JsonLocalRecipes>.Data.localMaterails.Clear(); | |||||
for (int i = 1; i < 15; i++) | |||||
{ | |||||
Json<JsonLocalRecipes>.Data.localMaterails.Add(new LocalMaterail | |||||
{ | |||||
MaterialID = Guid.NewGuid().ToString(), | |||||
MaterialPosition = i | |||||
});; | |||||
} | |||||
} | } | ||||
GLobal.recipePath = Path.Combine(path, "LocalRecipes.json"); | |||||
GLobal.posionPath = Path.Combine(path, "MaterialPosion.json"); | |||||
GLobal.MaterialRecipes = GLobal.GetJsonToT<LocalTeaWithMilkConfig>(GLobal.recipePath); | |||||
GLobal.deviceConfig = GLobal.GetJsonToT<DeviceConfigModelJson>($"{LocaPath.GetInstance().GetDeviceConfigPath}奶茶味魔方.json"); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,9 +1,7 @@ | |||||
using BPASmartClient.Helper; | using BPASmartClient.Helper; | ||||
using BPASmartClient.Message; | using BPASmartClient.Message; | ||||
using BPASmartClient.Model; | using BPASmartClient.Model; | ||||
using BPASmartClient.MorkTM; | |||||
using Microsoft.Toolkit.Mvvm.ComponentModel; | |||||
using Microsoft.Toolkit.Mvvm.Input; | |||||
using CommunityToolkit.Mvvm.Input; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -15,164 +13,185 @@ using System.Threading.Tasks; | |||||
namespace BPASmartClient.MilkWithTea.ViewModel | namespace BPASmartClient.MilkWithTea.ViewModel | ||||
{ | { | ||||
public class PatrameterSettiongViewModel: ObservableObject | |||||
partial class PatrameterSettiongViewModel: ObservableObject | |||||
{ | { | ||||
string FileName => GLobal.deviceConfig.Count > 0 ? GLobal.deviceConfig[0].ShopName : string.Empty; | |||||
/// <summary> | /// <summary> | ||||
/// 物料通道口列表 | /// 物料通道口列表 | ||||
/// </summary> | /// </summary> | ||||
public ObservableCollection<MaterialPosion> materialPosions { get; set; } = new ObservableCollection<MaterialPosion>(); | |||||
/// <summary> | |||||
/// 转盘位置列表 | |||||
/// </summary> | |||||
public ObservableCollection<OutMaterialPosion> TurntablePosion { get; set; } = new ObservableCollection<OutMaterialPosion>(); | |||||
public ObservableCollection<int> materialPosions { get; set; } = new ObservableCollection<int>(); | |||||
/// <summary> | |||||
/// 出料位置ID | |||||
/// </summary> | |||||
public int MaterialID { get { return _materialID; } set { _materialID = value; OnPropertyChanged(); } } | |||||
[ObservableProperty] | |||||
private int _materialID = 0; | private int _materialID = 0; | ||||
/// <summary> | /// <summary> | ||||
/// 出料重量 | /// 出料重量 | ||||
/// </summary> | /// </summary> | ||||
public float OutMaterailWeight { get { return _outMaterilWeight; } set { _outMaterilWeight = value; OnPropertyChanged(); } } | |||||
private float _outMaterilWeight; | |||||
/// <summary> | |||||
/// 装盘ID | |||||
/// </summary> | |||||
public int TurntableID { get { return _turntableID; } set { _turntableID = value; OnPropertyChanged(); } } | |||||
private int _turntableID = 0; | |||||
[ObservableProperty] | |||||
private int _outMaterilWeight; | |||||
/// <summary> | /// <summary> | ||||
/// 矫正的通道号 | /// 矫正的通道号 | ||||
/// </summary> | /// </summary> | ||||
public int CorrectPassway { get { return _CorrectPassway; } set { _CorrectPassway = value; OnPropertyChanged(); } } | |||||
[ObservableProperty] | |||||
private int _CorrectPassway = 0; | private int _CorrectPassway = 0; | ||||
/// <summary> | /// <summary> | ||||
/// 通道是否开启 | /// 通道是否开启 | ||||
/// </summary> | /// </summary> | ||||
public bool PasswayIsOpen { get { return _passwayIsOpen; } set { _passwayIsOpen = value; OnPropertyChanged(); } } | |||||
[ObservableProperty] | |||||
private bool _passwayIsOpen ; | private bool _passwayIsOpen ; | ||||
/// <summary> | /// <summary> | ||||
/// 矫正重量 | /// 矫正重量 | ||||
/// </summary> | /// </summary> | ||||
public float CorrectMatetailWeight { get { return _CorrectMatetailWeight; } set { _CorrectMatetailWeight = value; OnPropertyChanged(); } } | |||||
private float _CorrectMatetailWeight = 0; | |||||
[ObservableProperty] | |||||
private int _correctMatetailWeight = 0; | |||||
/// <summary> | /// <summary> | ||||
/// 矫正时间 | /// 矫正时间 | ||||
/// </summary> | /// </summary> | ||||
public int OutTime { get { return _0utTime; } set { _0utTime = value; OnPropertyChanged(); } } | |||||
private int _0utTime = 0; | |||||
[ObservableProperty] | |||||
private int _outTime = 0; | |||||
public bool IsEnable { get { return !GLobal.makeEnable; } set { GLobal.makeEnable = !value; OnPropertyChanged(); } } | public bool IsEnable { get { return !GLobal.makeEnable; } set { GLobal.makeEnable = !value; OnPropertyChanged(); } } | ||||
/// <summary> | /// <summary> | ||||
/// 出料动作 | /// 出料动作 | ||||
/// </summary> | /// </summary> | ||||
public RelayCommand OutMaterailCommad { get; set; } | |||||
/// <summary> | |||||
/// 转动转盘 | |||||
/// </summary> | |||||
public RelayCommand TurntableCommad { get; set; } | |||||
[RelayCommand] | |||||
private void OutMaterial() | |||||
{ | |||||
ActionManage.GetInstance.Send("通道口出料", new object[] { MaterialID, OutMaterilWeight }); | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// 开始矫正 | /// 开始矫正 | ||||
/// </summary> | /// </summary> | ||||
public RelayCommand CheckPasswayCommad { get; set; } | |||||
[RelayCommand] | |||||
private void CheckPassway() | |||||
{ | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// 开启通道 | /// 开启通道 | ||||
/// </summary> | /// </summary> | ||||
public RelayCommand OpenPasswayCommand { get; set; } | |||||
[RelayCommand] | |||||
private void OpenPassway() | |||||
{ | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// 确认重量 | /// 确认重量 | ||||
/// </summary> | /// </summary> | ||||
public RelayCommand CheckMaterailWeightCommand { get; set; } | |||||
[RelayCommand] | |||||
private void CheckMaterailWeight() | |||||
{ | |||||
} | |||||
#region 设备配置 | #region 设备配置 | ||||
/// <summary> | /// <summary> | ||||
/// 店铺名称 | /// 店铺名称 | ||||
/// </summary> | /// </summary> | ||||
public string ShopName { get { return _shopName; } set { _shopName = value; OnPropertyChanged(); } } | |||||
private string _shopName; | |||||
[ObservableProperty] | |||||
private string? _shopName = string.Empty; | |||||
/// <summary> | /// <summary> | ||||
/// 店铺ID | /// 店铺ID | ||||
/// </summary> | /// </summary> | ||||
public string ShopID { get { return _shopID; } set { _shopID = value; OnPropertyChanged(); } } | |||||
private string _shopID; | |||||
[ObservableProperty] | |||||
private string? _shopID = string.Empty; | |||||
/// <summary> | /// <summary> | ||||
/// 设备ID | /// 设备ID | ||||
/// </summary> | /// </summary> | ||||
public string DeviceID { get { return _deviceID; } set { _deviceID = value; OnPropertyChanged(); } } | |||||
private string _deviceID; | |||||
[ObservableProperty] | |||||
private string? _deviceID = string.Empty; | |||||
/// <summary> | /// <summary> | ||||
/// PLC地址 | /// PLC地址 | ||||
/// </summary> | /// </summary> | ||||
public string PLCAdress { get { return _pLCAdress; } set { _pLCAdress = value; OnPropertyChanged(); } } | |||||
private string _pLCAdress; | |||||
[ObservableProperty] | |||||
private string? _pLCAdress = string.Empty; | |||||
public RelayCommand SaveDevicesCommand { get; set; } | |||||
#endregion | |||||
[ObservableProperty] | |||||
private bool _isPort = true; | |||||
public PatrameterSettiongViewModel() | |||||
{ | |||||
OutMaterailCommad = new RelayCommand(new Action(() => | |||||
{ | |||||
ActionManage.GetInstance.Send("通道口出料", new object[] { MaterialID +1, OutMaterailWeight }); | |||||
[ObservableProperty] | |||||
private Visibility _vsIP = Visibility.Hidden; | |||||
})); | |||||
[ObservableProperty] | |||||
private Visibility _vsPort = Visibility.Visible; | |||||
TurntableCommad = new RelayCommand(new Action(() => | |||||
{ | |||||
ActionManage.GetInstance.Send("转盘转动", new object[] { TurntableID }); | |||||
})); | |||||
OpenPasswayCommand = new RelayCommand(new Action(() => | |||||
{ | |||||
if(PasswayIsOpen) ActionManage.GetInstance.Send("开启通道", new object[] { CorrectPassway + 1 }); | |||||
[ObservableProperty] | |||||
private string[] _ports; | |||||
})); | |||||
[ObservableProperty] | |||||
private string _prot; | |||||
CheckPasswayCommad = new RelayCommand(new Action(() => | |||||
[RelayCommand] | |||||
private void SaveDevices() | |||||
{ | |||||
SaveDeviceMessage(); | |||||
} | |||||
[RelayCommand] | |||||
private void ChangeCommunation() | |||||
{ | |||||
if(IsPort) | |||||
{ | { | ||||
ActionManage.GetInstance.Send("开始矫正", new object[] { CorrectPassway + 1,OutTime }); | |||||
})); | |||||
CheckMaterailWeightCommand = new RelayCommand(new Action(() => | |||||
VsPort = Visibility.Visible; | |||||
VsIP = Visibility.Hidden; | |||||
} | |||||
else | |||||
{ | { | ||||
ActionManage.GetInstance.Send("矫正重量", new object[] { CorrectPassway + 1, CorrectMatetailWeight }); | |||||
})); | |||||
SaveDevicesCommand = new RelayCommand(SaveDeviceMessage); | |||||
VsIP = Visibility.Visible; | |||||
VsPort = Visibility.Hidden; | |||||
} | |||||
} | |||||
#endregion | |||||
public PatrameterSettiongViewModel() | |||||
{ | |||||
Ports = System.IO.Ports.SerialPort.GetPortNames(); | |||||
init(); | init(); | ||||
} | } | ||||
private void init() | private void init() | ||||
{ | { | ||||
foreach (MaterialPosion materialPosion in Enum.GetValues(typeof(MaterialPosion))) | |||||
for (int i = 1; i < 14; i++) | |||||
{ | { | ||||
materialPosions.Add(materialPosion); | |||||
materialPosions.Add(i); | |||||
} | } | ||||
foreach (OutMaterialPosion outMaterialPosion in Enum.GetValues(typeof(OutMaterialPosion))) | |||||
if (GLobal.deviceConfig.Count > 0) | |||||
{ | { | ||||
TurntablePosion.Add(outMaterialPosion); | |||||
ShopName = GLobal.deviceConfig.ElementAtOrDefault(0).ShopName ; | |||||
ShopID = GLobal.deviceConfig.ElementAtOrDefault(0).ShopId; | |||||
DeviceID = GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAt(0).DeviceId; | |||||
PLCAdress = GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAt(0).communicationDevcies.ElementAt(0).communicationPar.IPAddress; | |||||
} | } | ||||
ShopName = GLobal.deviceConfig.ElementAt(0).ShopName; | |||||
ShopID = GLobal.deviceConfig.ElementAt(0).ShopId; | |||||
DeviceID = GLobal.deviceConfig.ElementAt(0).deviceModels.ElementAt(0).DeviceId; | |||||
PLCAdress = GLobal.deviceConfig.ElementAt(0).deviceModels.ElementAt(0).communicationDevcies.ElementAt(0).communicationPar.IPAddress; | |||||
} | } | ||||
private void SaveDeviceMessage() | private void SaveDeviceMessage() | ||||
{ | { | ||||
if (GLobal.deviceConfig.Count > 0) | if (GLobal.deviceConfig.Count > 0) | ||||
{ | { | ||||
GLobal.deviceConfig.ElementAt(0).ShopName = ShopName; | |||||
GLobal.deviceConfig.ElementAt(0).ShopId = ShopID; | |||||
GLobal.deviceConfig.ElementAt(0).deviceModels.ElementAt(0).DeviceId = DeviceID; | |||||
GLobal.deviceConfig.ElementAt(0).deviceModels.ElementAt(0).Id = Guid.NewGuid().ToString(); | |||||
GLobal.deviceConfig.ElementAt(0).deviceModels.ElementAt(0).communicationDevcies.ElementAt(0).communicationPar.IPAddress = PLCAdress; | |||||
File.WriteAllText($"{LocaPath.GetInstance().GetDeviceConfigPath}奶茶味魔方.json", JsonConvert.SerializeObject(GLobal.deviceConfig)); | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).ShopName = ShopName; | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).ShopId = ShopID; | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).DeviceId = DeviceID; | |||||
if(IsPort) | |||||
{ | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).communicationDevcies.ElementAtOrDefault(0).communicationPar.IsSerialPort = true; | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).communicationDevcies.ElementAtOrDefault(0).communicationPar.SerialPort = Prot; | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).communicationDevcies.ElementAtOrDefault(0).communicationPar.BaudRate = 9600; | |||||
} | |||||
else | |||||
{ | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).communicationDevcies.ElementAtOrDefault(0).communicationPar.IsSerialPort = false; | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).communicationDevcies.ElementAtOrDefault(0).communicationPar.IsNetworkPort = true; | |||||
GLobal.deviceConfig.ElementAtOrDefault(0).deviceModels.ElementAtOrDefault(0).communicationDevcies.ElementAtOrDefault(0).communicationPar.IPAddress = PLCAdress; | |||||
} | |||||
} | } | ||||
File.WriteAllText($"{LocaPath.GetInstance().GetDeviceConfigPath}MOC.json", JsonConvert.SerializeObject(GLobal.deviceConfig)); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -0,0 +1,75 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using System.Windows.Controls; | |||||
namespace BPASmartClient.MilkWithTea.ViewModel | |||||
{ | |||||
partial class RecipeConfigeViewModel:ObservableObject | |||||
{ | |||||
public static ObservableCollection<LocalMaterail> Materails { get; set; } = new ObservableCollection<LocalMaterail>(); | |||||
public Dictionary<string,string> materialNames { get; set; } = new Dictionary<string,string>(); | |||||
[ObservableProperty] | |||||
private string _name = String.Empty; | |||||
[RelayCommand] | |||||
private void AddMaterial() | |||||
{ | |||||
Materails.Add(new LocalMaterail()); | |||||
} | |||||
[RelayCommand] | |||||
private void Delete(object o) | |||||
{ | |||||
if (o == null) return; | |||||
if(o is ListBoxItem id) | |||||
{ | |||||
Materails.Remove((LocalMaterail)id.DataContext); | |||||
} | |||||
} | |||||
[RelayCommand] | |||||
private void Save() | |||||
{ | |||||
if(Name == String.Empty) | |||||
{ | |||||
return; | |||||
} | |||||
if(Json<JsonLocalRecipes>.Data.localRecipes.FirstOrDefault(p=>p.RecipeName == Name)!= null) | |||||
{ | |||||
return; | |||||
} | |||||
foreach(var materail in Materails) | |||||
{ | |||||
materail.MaterialName = materialNames[materail.MaterialID]; | |||||
} | |||||
Json<JsonLocalRecipes>.Data.localRecipes.Add(new LocalRecipe | |||||
{ | |||||
RecipeID = Guid.NewGuid().ToString(), | |||||
RecipeName = Name, | |||||
localMaterails = Materails, | |||||
}); | |||||
Json<JsonLocalRecipes>.Save(); | |||||
ActionManage.GetInstance.Send("RecipeConfigeViewClose"); | |||||
} | |||||
public RecipeConfigeViewModel() | |||||
{ | |||||
if(Json<JsonLocalRecipes>.Data.localMaterails.Count > 0) | |||||
{ | |||||
foreach(var item in Json<JsonLocalRecipes>.Data.localMaterails) | |||||
{ | |||||
if(item.MaterialID!=null&&item.MaterialName!=null) | |||||
{ | |||||
materialNames.Add(item.MaterialID, item.MaterialName); | |||||
} | |||||
} | |||||
} | |||||
Materails.Clear(); | |||||
} | |||||
} | |||||
} |
@@ -21,4 +21,8 @@ | |||||
<PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.1.2" /> | <PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.1.2" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<Folder Include="奶咖一体机\" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -35,55 +35,38 @@ namespace BPASmartClient.MorkF | |||||
#region 调试代码 | #region 调试代码 | ||||
public void CommandRegist() | public void CommandRegist() | ||||
{ | { | ||||
#region 设备控制 | |||||
ActionManage.GetInstance.Register(PLCInite, "InitCommand"); | ActionManage.GetInstance.Register(PLCInite, "InitCommand"); | ||||
ActionManage.GetInstance.Register(InitialData, "SimultaorOrder"); | ActionManage.GetInstance.Register(InitialData, "SimultaorOrder"); | ||||
ActionManage.GetInstance.Register(MaterialOne, "MaterialOne"); | |||||
ActionManage.GetInstance.Register(MaterialTwo, "MaterialTwo"); | |||||
ActionManage.GetInstance.Register(MaterialThree, "MaterialThree"); | |||||
ActionManage.GetInstance.Register(MaterialFour, "MaterialFour"); | |||||
ActionManage.GetInstance.Register(MaterialFive, "MaterialFive"); | |||||
ActionManage.GetInstance.Register(ManualOpenExhaust, "OpenExhaust"); | |||||
ActionManage.GetInstance.Register(CloseExhaust, "CloaseExhaust"); | |||||
ActionManage.GetInstance.Register(StartQX, "StartQXOne"); | |||||
ActionManage.GetInstance.Register(StartQX, "StartQXTwo"); | |||||
#endregion | |||||
ActionManage.GetInstance.Register(ShreddCabbage, "ShreddCabbage"); | ActionManage.GetInstance.Register(ShreddCabbage, "ShreddCabbage"); | ||||
ActionManage.GetInstance.Register(FryPork, "FryPork"); | ActionManage.GetInstance.Register(FryPork, "FryPork"); | ||||
ActionManage.GetInstance.Register(XingBaoGu, "XingBaoGu"); | ActionManage.GetInstance.Register(XingBaoGu, "XingBaoGu"); | ||||
ActionManage.GetInstance.Register(TakePot, "TakePot"); | |||||
ActionManage.GetInstance.Register(TakePotReset, "TakePotReset"); | |||||
ActionManage.GetInstance.Register(TakeMaterial, "TakeMaterial"); | |||||
ActionManage.GetInstance.Register(ManualOutMeal, "OutMeal"); | |||||
#region 配料控制 | |||||
ActionManage.GetInstance.Register(OutMaterials, "OutMaterials"); | |||||
#endregion | |||||
#region 炒锅1 | |||||
ActionManage.GetInstance.Register<Action>(AddOil, "AddOil"); | ActionManage.GetInstance.Register<Action>(AddOil, "AddOil"); | ||||
ActionManage.GetInstance.Register(TakeOff, "TakeOff"); | |||||
ActionManage.GetInstance.Register(OneBlock, "OneBlock"); | |||||
ActionManage.GetInstance.Register(TwoBlock, "TwoBlock"); | |||||
ActionManage.GetInstance.Register(ThreeBlock, "ThreeBlock"); | |||||
ActionManage.GetInstance.Register(OverTurnOff, "OverTurnOff"); | |||||
ActionManage.GetInstance.Register(OverOneBlock, "OverOneBlock"); | |||||
ActionManage.GetInstance.Register(OverTwoBlock, "OverTwoBlock"); | |||||
ActionManage.GetInstance.Register(OverThreeBlock, "OverThreeBlock"); | |||||
ActionManage.GetInstance.Register(OverGoOn, "OverGoOn"); | |||||
ActionManage.GetInstance.Register(OverGoDown, "OverGoDown"); | |||||
ActionManage.GetInstance.Register(AutoModel, "AutoModel"); | |||||
ActionManage.GetInstance.Register(ManualModel, "ManualModel"); | |||||
ActionManage.GetInstance.Register<Action>(AddOil, "SecAddOil"); | |||||
ActionManage.GetInstance.Register(TakeOff, "SecTakeOff"); | |||||
ActionManage.GetInstance.Register(OneBlock, "SecOneBlock"); | |||||
ActionManage.GetInstance.Register(TwoBlock, "SecTwoBlock"); | |||||
ActionManage.GetInstance.Register(ThreeBlock, "SecThreeBlock"); | |||||
ActionManage.GetInstance.Register(OverTurnOff, "SecOverTurnOff"); | |||||
ActionManage.GetInstance.Register(OverOneBlock, "SecOverOneBlock"); | |||||
ActionManage.GetInstance.Register(OverTwoBlock, "SecOverTwoBlock"); | |||||
ActionManage.GetInstance.Register(OverThreeBlock, "SecOverThreeBlock"); | |||||
ActionManage.GetInstance.Register(OverGoOn, "SecOverGoOn"); | |||||
ActionManage.GetInstance.Register(OverGoDown, "SecOverGoDown"); | |||||
ActionManage.GetInstance.Register(AutoModel, "SecAutoModel"); | |||||
ActionManage.GetInstance.Register(ManualModel, "SecManualModel"); | |||||
ActionManage.GetInstance.Register(StartFire, "StartFire"); | |||||
ActionManage.GetInstance.Register(StopFire, "StopFire"); | |||||
ActionManage.GetInstance.Register(StartStir, "StartStir"); | |||||
ActionManage.GetInstance.Register(StopStir, "StopStir"); | |||||
ActionManage.GetInstance.Register(OutFood, "OutFood"); | |||||
ActionManage.GetInstance.Register(StirArmGoOrigin, "StirArmGoOrigin"); | |||||
ActionManage.GetInstance.Register(StirArmGoWork, "StirArmGoWork"); | |||||
ActionManage.GetInstance.Register(HBOTGoWork, "HBOTGoWork"); | |||||
ActionManage.GetInstance.Register(OutMeal, "OutMeal"); | |||||
ActionManage.GetInstance.Register(SetFire, "SetFire"); | |||||
ActionManage.GetInstance.Register(SetStir, "SetStir"); | |||||
#endregion | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// 手撕包菜流程 | /// 手撕包菜流程 | ||||
/// </summary> | /// </summary> | ||||
@@ -161,160 +144,91 @@ namespace BPASmartClient.MorkF | |||||
stirFryBom.AddAction(new StirFryAction() { Time = StirFryTime.T6, PotActions = new List<StirFryPotAction>() { StirFryPotAction.搅拌臂下位, StirFryPotAction.快速旋转 }, During = 55 }); | stirFryBom.AddAction(new StirFryAction() { Time = StirFryTime.T6, PotActions = new List<StirFryPotAction>() { StirFryPotAction.搅拌臂下位, StirFryPotAction.快速旋转 }, During = 55 }); | ||||
stirFryBom.AddAction(new StirFryAction() { Time = StirFryTime.T11, RobotActions = new List<StirFryRobotAction>() { StirFryRobotAction.灶取锅 } }); | stirFryBom.AddAction(new StirFryAction() { Time = StirFryTime.T11, RobotActions = new List<StirFryRobotAction>() { StirFryRobotAction.灶取锅 } }); | ||||
} | } | ||||
public void StartQX(object obj) | |||||
//出配料 | |||||
public void OutMaterials(object o) | |||||
{ | { | ||||
if ((int)obj == 1) | |||||
WriteData("M1.4", true); | |||||
if ((int)obj == 2) | |||||
WriteData("M1.7", true); | |||||
} | |||||
public void ManualOpenExhaust() | |||||
{ | |||||
WriteData("M0.7", true); | |||||
} | |||||
public void CloseExhaust() | |||||
{ | |||||
WriteData("M0.7", false); | |||||
if (o == null) return; | |||||
if (o is List<int> ints && ints.Count == 2) | |||||
{ | |||||
WriteControl(morkF.PassWayValue[ints[0]], ints[1]);//写入通道值 | |||||
Thread.Sleep(500); | |||||
WriteControl(morkF.StartPassWay[ints[0]], true);//开启通道 | |||||
} | |||||
} | } | ||||
public void TakeMaterial() | |||||
#region 炒锅1 | |||||
//加热启动 | |||||
public void StartFire() | |||||
{ | { | ||||
WriteData("M14.1", true); | |||||
WriteControl("M0.1", true); | |||||
} | } | ||||
public void ManualOutMeal() | |||||
//加热停止 | |||||
public void StopFire() | |||||
{ | { | ||||
WriteData("M14.2", true); | |||||
WriteControl("M0.1", false); | |||||
} | } | ||||
public void MaterialOne() | |||||
//搅拌启动 | |||||
public void StartStir() | |||||
{ | { | ||||
WriteData("M13.0", true); | |||||
WriteControl("M0.2", true); | |||||
} | } | ||||
public void MaterialTwo() | |||||
//搅拌启停止 | |||||
public void StopStir() | |||||
{ | { | ||||
WriteData("M13.1", true); | |||||
WriteControl("M0.2", false); | |||||
} | } | ||||
public void MaterialThree() | |||||
//倒菜 | |||||
public void OutFood() | |||||
{ | { | ||||
WriteData("M13.2", true); | |||||
WriteControl("M0.3", true); | |||||
} | } | ||||
public void MaterialFour() | |||||
//搅拌臂去原点位 | |||||
public void StirArmGoOrigin() | |||||
{ | { | ||||
WriteData("M13.3", true); | |||||
WriteControl("M0.5", true); | |||||
} | } | ||||
public void MaterialFive() | |||||
//搅拌臂去炒制位 | |||||
public void StirArmGoWork() | |||||
{ | { | ||||
WriteData("M13.4", true); | |||||
WriteControl("M0.6", true); | |||||
} | } | ||||
public void AutoModel(object obj) | |||||
//HBOT放盒子到位 | |||||
public void HBOTGoWork() | |||||
{ | { | ||||
WriteData("0.3", true); | |||||
WriteControl("M0.7", true); | |||||
} | } | ||||
public void ManualModel() | |||||
//出餐启动 | |||||
public void OutMeal() | |||||
{ | { | ||||
WriteData("0.2", true); | |||||
WriteControl("M0.4", true); | |||||
} | } | ||||
public void AddOil(object obj) | |||||
//加热挡位设定 | |||||
public void SetFire(object o) | |||||
{ | { | ||||
if ((int)obj == 1) | |||||
if(o == null) return; | |||||
if(o is List<int> ints&&ints.Count == 1) | |||||
{ | { | ||||
Task.Run(() => { WriteData("M2.7", true); Task.Delay(4000).Wait(); WriteData("M2.7", false); }); | |||||
WriteControl("VW228",ints[0]); | |||||
} | } | ||||
if ((int)obj == 2) | |||||
{ | |||||
Task.Run(() => { WriteData("M3.1", true); Task.Delay(4000).Wait(); WriteData("M3.1", false); }); | |||||
} | |||||
} | |||||
public void TakePot(object obj) | |||||
{ | |||||
WriteData("M14.0", true); | |||||
} | |||||
public void TakePotReset(object obj) | |||||
{ | |||||
WriteData("M14.0", false); | |||||
} | } | ||||
public void TakeOff(object obj) | |||||
//搅拌挡位设定 | |||||
public void SetStir(object o) | |||||
{ | { | ||||
if ((int)obj == 1) | |||||
WriteData("M4.0", new bool[] { false, false, false, false, false, false, false, false });//0000 0000 | |||||
if ((int)obj == 2) | |||||
WriteData("M5.0", new bool[] { false, false, false, false, false, false, false, false });//0000 0000 | |||||
if (o == null) return; | |||||
if (o is List<int> ints && ints.Count == 1) | |||||
{ | |||||
WriteControl("VW230", ints[0]); | |||||
} | |||||
} | } | ||||
public void OneBlock(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M4.0", new bool[] { true, false, false, false, false, false, false, false });//0000 0001 | |||||
if ((int)obj == 2) | |||||
WriteData("M5.0", new bool[] { true, false, false, false, false, false, false, false });//0000 0001 | |||||
#endregion | |||||
} | |||||
public void TwoBlock(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M4.0", new bool[] { false, true, false, false, false, false, false, false });//0000 0010 | |||||
if ((int)obj == 2) | |||||
WriteData("M5.0", new bool[] { false, true, false, false, false, false, false, false });//0000 0010 | |||||
} | |||||
public void ThreeBlock(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M4.0", new bool[] { true, true, false, false, false, false, false, false });//0000 0011 | |||||
if ((int)obj == 2) | |||||
WriteData("M5.0", new bool[] { true, true, false, false, false, false, false, false });//0000 0011 | |||||
} | |||||
public void OverTurnOff(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M7.0", true); | |||||
if ((int)obj == 2) | |||||
WriteData("M7.4", true); | |||||
} | |||||
public void OverOneBlock(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M7.1", true); | |||||
if ((int)obj == 2) | |||||
WriteData("M7.5", true); | |||||
} | |||||
public void OverTwoBlock(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M7.2", true); | |||||
if ((int)obj == 2) | |||||
WriteData("M7.6", true); | |||||
} | |||||
public void OverThreeBlock(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M7.3", true); | |||||
if ((int)obj == 2) | |||||
WriteData("M7.7", true); | |||||
} | |||||
public void OverGoOn(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M8.0", true); | |||||
if ((int)obj == 2) | |||||
WriteData("M8.4", true); | |||||
} | |||||
public void OverGoDown(object obj) | |||||
{ | |||||
if ((int)obj == 1) | |||||
WriteData("M8.2", true); | |||||
if ((int)obj == 2) | |||||
WriteData("M8.6", true); | |||||
} | |||||
public void FlowInite() | |||||
{ | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// 订单初始化 | /// 订单初始化 | ||||
/// </summary> | /// </summary> | ||||
@@ -594,7 +508,6 @@ namespace BPASmartClient.MorkF | |||||
morkF.TakePlateQueue.Enqueue(new OrderLocInfo() | morkF.TakePlateQueue.Enqueue(new OrderLocInfo() | ||||
{ | { | ||||
SuborderId = order.MorkOrder.SuborderId, | SuborderId = order.MorkOrder.SuborderId, | ||||
}); | }); | ||||
} | } | ||||
//} | //} | ||||
@@ -299,6 +299,44 @@ namespace BPASmartClient.MorkF | |||||
/// </summary> | /// </summary> | ||||
public string CurrentOrderId { get; set; } | public string CurrentOrderId { get; set; } | ||||
#endregion | #endregion | ||||
public Dictionary<int,string> StartPassWay { get; set; } = new Dictionary<int, string>() | |||||
{ | |||||
{1,"M3.0" }, | |||||
{2,"M3.1" }, | |||||
{3,"M3.2" }, | |||||
{4,"M3.3" }, | |||||
{5,"M3.4" }, | |||||
{6,"M3.5" }, | |||||
{7,"M3.6" }, | |||||
{8,"M3.7" }, | |||||
{9,"M4.0" }, | |||||
{10,"M4.1" }, | |||||
{11,"M4.2" }, | |||||
{12,"M4.3" }, | |||||
{13,"M4.4" }, | |||||
{13,"M4.5" }, | |||||
}; | |||||
public Dictionary<int, string> PassWayValue { get; set; } = new Dictionary<int, string>() | |||||
{ | |||||
{1,"VW200" }, | |||||
{2,"VW202" }, | |||||
{3,"VW204" }, | |||||
{4,"VW206" }, | |||||
{5,"VW208" }, | |||||
{6,"VW210" }, | |||||
{7,"VW212" }, | |||||
{8,"VW214" }, | |||||
{9,"VW216" }, | |||||
{10,"VW218" }, | |||||
{11,"VW220" }, | |||||
{12,"VW222" }, | |||||
{13,"VW224" }, | |||||
{13,"VW226" }, | |||||
}; | |||||
} | } | ||||
} | } | ||||
@@ -47,29 +47,49 @@ | |||||
</WrapPanel> | </WrapPanel> | ||||
</GroupBox> | </GroupBox> | ||||
<StackPanel Orientation="Vertical" Grid.Row="2"> | <StackPanel Orientation="Vertical" Grid.Row="2"> | ||||
<GroupBox Header="机器人控制" FontSize="15" Foreground="Aqua" VerticalAlignment="Center" Height="95"> | |||||
<GroupBox Header="配料仓控制" FontSize="15" Foreground="Aqua" VerticalAlignment="Center" Height="95"> | |||||
<WrapPanel Orientation="Horizontal" Grid.RowSpan="2" VerticalAlignment="Top" Margin="0,5,0,0" > | <WrapPanel Orientation="Horizontal" Grid.RowSpan="2" VerticalAlignment="Top" Margin="0,5,0,0" > | ||||
<Button Content="取锅" Command="{Binding TakePot}" Margin="10,0,10,0"></Button> | |||||
<!--<Button Content="取锅复位" Command="{Binding TakePotReset}" Margin="10,0,10,0"></Button>--> | |||||
<Button Content="取料" Command="{Binding TakeMaterial}" Margin="10,0,10,0"></Button> | |||||
<Button Content="出餐" Command="{Binding OutMeal}" Margin="10,0,10,0"></Button> | |||||
<TextBlock Text="通道号" Margin="5,0"/> | |||||
<ComboBox ItemsSource="{Binding PassageWays}" Width="120" Margin="5,0" | |||||
SelectedIndex="{Binding PassagePosition}"/> | |||||
<TextBlock Text="出料量" Margin="5,0"/> | |||||
<TextBox Text="{Binding Weight}" Margin="5,0" Width="100"/> | |||||
<TextBlock Text="g" Margin="0,0,10,0"/> | |||||
<Button Content="出料" Margin="10,0" Command="{Binding OutMaterials}"/> | |||||
</WrapPanel> | </WrapPanel> | ||||
</GroupBox> | </GroupBox> | ||||
<GroupBox Header="炒锅1" FontSize="15" Foreground="Aqua" VerticalAlignment="Center" Height="140"> | <GroupBox Header="炒锅1" FontSize="15" Foreground="Aqua" VerticalAlignment="Center" Height="140"> | ||||
<WrapPanel VerticalAlignment="Top" Margin="0,5,0,0"> | |||||
<Button Content="注油" Command="{Binding AddOil}" Margin="10,0,10,0"></Button> | |||||
<Button Content="加热关闭" Command="{Binding TempTurnOff}" Margin="10,0,10,0"></Button> | |||||
<Button Content="加热1挡" Command="{Binding OneBlock}" Margin="10,0,10,0"></Button> | |||||
<Button Content="加热2挡" Command="{Binding TwoBlock}" Margin="10,0,10,0"></Button> | |||||
<Button Content="加热3挡" Command="{Binding ThreeBlock}" Margin="10,0,10,0"></Button> | |||||
<Button Content="翻炒机关闭" Command="{Binding OverTurnOff}" Margin="10,0,10,0" Cursor="Hand"></Button> | |||||
<Button Content="翻炒机上升" Command="{Binding OverGoOn}" Margin="10,0,15,0" Cursor="Hand"></Button> | |||||
<Button Content="翻炒机下降" Command="{Binding OverGoDown}" Margin="10,0,10,0"></Button> | |||||
<Button Content="翻炒机1挡" Command="{Binding OverOneBlock}" Margin="10,0,10,0"></Button> | |||||
<Button Content="翻炒机2挡" Command="{Binding OverTwoBlock}" Margin="10,0,10,0"></Button> | |||||
<Button Content="翻炒机3挡" Command="{Binding OverThreeBlock}" Margin="10,0,10,0"></Button> | |||||
</WrapPanel> | |||||
<Grid> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="*"/> | |||||
<RowDefinition Height="*"/> | |||||
</Grid.RowDefinitions> | |||||
<WrapPanel VerticalAlignment="Top" Margin="0,5,0,0"> | |||||
<Button Content="注油" Command="{Binding AddOil}" Margin="10,0,10,0"></Button> | |||||
<Button Content="加热启动" Command="{Binding StartFire}" Margin="10,0,10,0"></Button> | |||||
<Button Content="加热停止" Command="{Binding StopFire}" Margin="10,0,10,0"></Button> | |||||
<Button Content="搅拌启动" Command="{Binding StartStir}" Margin="10,0,10,0" Cursor="Hand"></Button> | |||||
<Button Content="搅拌停止" Command="{Binding StopStir}" Margin="10,0,15,0" Cursor="Hand"></Button> | |||||
<Button Content="倒菜启动" Command="{Binding OutFood}" Margin="10,0,15,0" Cursor="Hand"/> | |||||
<Button Content="搅拌臂去原点位" Command="{Binding StirArmGoOrigin}" Margin="10,0,10,0"></Button> | |||||
<Button Content="搅拌臂去炒制位" Command="{Binding StirArmGoWork}" Margin="10,0,10,0"></Button> | |||||
<Button Content="HBOT放盒子到位" Command="{Binding HBOTGoWork}" Margin="10,0,10,0"></Button> | |||||
<Button Content="出餐启动" Command="{Binding OutMeal}" Margin="10,0,10,0"></Button> | |||||
</WrapPanel> | |||||
<WrapPanel Grid.Row="2"> | |||||
<TextBlock Text="加热挡位:" Margin="10,0,0,0" /> | |||||
<ComboBox ItemsSource="{Binding lstFire}" Width="80" Margin="10,0,10,0" HorizontalAlignment="Center" VerticalAlignment="Center" | |||||
SelectedValue="{Binding FireGear}"/> | |||||
<Button Content="设定" Margin="0,0,30,0" Command="{Binding SetFire}"/> | |||||
<TextBlock Text="搅拌挡位:" Margin="10,0,0,0" /> | |||||
<ComboBox ItemsSource="{Binding lstStir}" Width="80" Margin="10,0,10,0" HorizontalAlignment="Center" VerticalAlignment="Center" | |||||
SelectedValue="{Binding StirGear}"/> | |||||
<Button Content="设定" Margin="0,0,30,0" Command="{Binding SetStir}"/> | |||||
</WrapPanel> | |||||
</Grid> | |||||
</GroupBox> | </GroupBox> | ||||
<GroupBox Header="炒锅2" FontSize="15" Foreground="Aqua" VerticalAlignment="Center" Height="140"> | <GroupBox Header="炒锅2" FontSize="15" Foreground="Aqua" VerticalAlignment="Center" Height="140"> | ||||
<WrapPanel VerticalAlignment="Top" Margin="0,5,0,0"> | <WrapPanel VerticalAlignment="Top" Margin="0,5,0,0"> | ||||
@@ -13,7 +13,7 @@ namespace BPASmartClient.MorkF.ViewModel | |||||
internal class DebugViewModel : ObservableObject | internal class DebugViewModel : ObservableObject | ||||
{ | { | ||||
public bool SimOrderEnable { get { return General_Config.SimOrderAllow; } set { General_Config.SimOrderAllow = value; OnPropertyChanged(); } } | public bool SimOrderEnable { get { return General_Config.SimOrderAllow; } set { General_Config.SimOrderAllow = value; OnPropertyChanged(); } } | ||||
#region 设备控制 | |||||
public RelayCommand PlcInite { get; set; } | public RelayCommand PlcInite { get; set; } | ||||
public RelayCommand SimulateOrder { get; set; } | public RelayCommand SimulateOrder { get; set; } | ||||
public RelayCommand MaterialOne { get; set; } | public RelayCommand MaterialOne { get; set; } | ||||
@@ -25,31 +25,64 @@ namespace BPASmartClient.MorkF.ViewModel | |||||
public RelayCommand CloaseExhaust { get; set; } | public RelayCommand CloaseExhaust { get; set; } | ||||
public RelayCommand StartQXOne { get; set; } | public RelayCommand StartQXOne { get; set; } | ||||
public RelayCommand StartQXTwo { get; set; } | public RelayCommand StartQXTwo { get; set; } | ||||
#endregion | |||||
#region 菜品控制 | |||||
public RelayCommand ShreddCabbage { get; set; } | public RelayCommand ShreddCabbage { get; set; } | ||||
public RelayCommand FryPork { get; set; } | public RelayCommand FryPork { get; set; } | ||||
public RelayCommand XingBaoGu { get; set; } | public RelayCommand XingBaoGu { get; set; } | ||||
#endregion | |||||
public RelayCommand TakePot { get; set; } | |||||
public RelayCommand TakePotReset { get; set; } | |||||
public RelayCommand TakeMaterial { get; set; } | |||||
public RelayCommand OutMeal { get; set; } | |||||
#region 配料仓控制 | |||||
public List<string> PassageWays = new List<string>() | |||||
{ | |||||
"通道1", | |||||
"通道2", | |||||
"通道3", | |||||
"通道4", | |||||
"通道5", | |||||
"通道6", | |||||
"通道7", | |||||
"通道8", | |||||
"通道9", | |||||
"通道10", | |||||
"通道11", | |||||
"通道12", | |||||
"通道13", | |||||
"通道14", | |||||
}; | |||||
public int PassagePosition { get { return _passagePosition; } set { _passagePosition = value; OnPropertyChanged(); } } | |||||
private int _passagePosition; | |||||
public int Weight { get { return _weight; } set { _weight = value; OnPropertyChanged(); } } | |||||
private int _weight; | |||||
public RelayCommand OutMaterials { get; set; } | |||||
#endregion | |||||
#region 炒锅1 | |||||
public RelayCommand AddOil { get; set; } | public RelayCommand AddOil { get; set; } | ||||
public RelayCommand TempTurnOff { get; set; } | |||||
public RelayCommand OneBlock { get; set; } | |||||
public RelayCommand TwoBlock { get; set; } | |||||
public RelayCommand ThreeBlock { get; set; } | |||||
public RelayCommand OverTurnOff { get; set; } | |||||
public RelayCommand OverOneBlock { get; set; } | |||||
public RelayCommand OverTwoBlock { get; set; } | |||||
public RelayCommand OverThreeBlock { get; set; } | |||||
public RelayCommand OverGoOn { get; set; } | |||||
public RelayCommand OverGoDown { get; set; } | |||||
public RelayCommand AutoModel { get; set; } | |||||
public RelayCommand ManualModel { get; set; } | |||||
public RelayCommand StartFire { get; set; } | |||||
public RelayCommand StopFire { get; set; } | |||||
public RelayCommand StartStir { get; set; } | |||||
public RelayCommand StopStir { get; set; } | |||||
public RelayCommand OutFood { get; set; } | |||||
public RelayCommand StirArmGoOrigin { get; set; } | |||||
public RelayCommand StirArmGoWork { get; set; } | |||||
public RelayCommand HBOTGoWork { get; set; } | |||||
public RelayCommand OutMeal { get; set; } | |||||
public RelayCommand SetFire { get; set; } | |||||
public RelayCommand SetStir { get; set; } | |||||
public List<int> lstFire { get; set; } = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; | |||||
public List<int> lstStir { get; set; } = new List<int>() { 1, 2, 3 }; | |||||
public int FireGear { get { return _fireGear; } set { _fireGear = value; OnPropertyChanged(); } } | |||||
private int _fireGear; | |||||
public int StirGear { get { return _stirGear; } set { _stirGear = value; OnPropertyChanged(); } } | |||||
private int _stirGear; | |||||
#endregion | |||||
#region 炒锅2 | |||||
public RelayCommand SecAddOil { get; set; } | public RelayCommand SecAddOil { get; set; } | ||||
public RelayCommand SecTempTurnOff { get; set; } | public RelayCommand SecTempTurnOff { get; set; } | ||||
public RelayCommand SecOneBlock { get; set; } | public RelayCommand SecOneBlock { get; set; } | ||||
@@ -63,44 +96,51 @@ namespace BPASmartClient.MorkF.ViewModel | |||||
public RelayCommand SecOverGoDown { get; set; } | public RelayCommand SecOverGoDown { get; set; } | ||||
public RelayCommand SecAutoModel { get; set; } | public RelayCommand SecAutoModel { get; set; } | ||||
public RelayCommand SecManualModel { get; set; } | public RelayCommand SecManualModel { get; set; } | ||||
#endregion | |||||
public DebugViewModel() | public DebugViewModel() | ||||
{ | { | ||||
#region 设备控制 | |||||
PlcInite = new RelayCommand(() => { ActionManage.GetInstance.Send("InitCommand"); }); | PlcInite = new RelayCommand(() => { ActionManage.GetInstance.Send("InitCommand"); }); | ||||
SimulateOrder = new RelayCommand(() => {ActionManage.GetInstance.Send("SimultaorOrder"); }); | |||||
MaterialOne= new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialOne"); }); | |||||
SimulateOrder = new RelayCommand(() => { ActionManage.GetInstance.Send("SimultaorOrder"); }); | |||||
MaterialOne = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialOne"); }); | |||||
MaterialTwo = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialTwo"); }); | MaterialTwo = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialTwo"); }); | ||||
MaterialThree = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialThree"); }); | MaterialThree = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialThree"); }); | ||||
MaterialFour = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialFour"); }); | MaterialFour = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialFour"); }); | ||||
MaterialFive = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialFive"); }); | MaterialFive = new RelayCommand(() => { ActionManage.GetInstance.Send("MaterialFive"); }); | ||||
OpenExhaust = new RelayCommand(() => { ActionManage.GetInstance.Send("OpenExhaust"); }); | OpenExhaust = new RelayCommand(() => { ActionManage.GetInstance.Send("OpenExhaust"); }); | ||||
CloaseExhaust = new RelayCommand(() => { ActionManage.GetInstance.Send("CloseExhaust"); }); | CloaseExhaust = new RelayCommand(() => { ActionManage.GetInstance.Send("CloseExhaust"); }); | ||||
StartQXOne=new RelayCommand(() => { ActionManage.GetInstance.Send("StartQXOne",1); }); | |||||
StartQXTwo = new RelayCommand(() => { ActionManage.GetInstance.Send("StartQXTwo",2); }); | |||||
StartQXOne = new RelayCommand(() => { ActionManage.GetInstance.Send("StartQXOne", 1); }); | |||||
StartQXTwo = new RelayCommand(() => { ActionManage.GetInstance.Send("StartQXTwo", 2); }); | |||||
#endregion | |||||
ShreddCabbage = new RelayCommand(() => { ActionManage.GetInstance.Send("ShreddCabbage"); }); | ShreddCabbage = new RelayCommand(() => { ActionManage.GetInstance.Send("ShreddCabbage"); }); | ||||
FryPork = new RelayCommand(() => { ActionManage.GetInstance.Send("FryPork"); }); | FryPork = new RelayCommand(() => { ActionManage.GetInstance.Send("FryPork"); }); | ||||
XingBaoGu = new RelayCommand(() => { ActionManage.GetInstance.Send("XingBaoGu"); }); | XingBaoGu = new RelayCommand(() => { ActionManage.GetInstance.Send("XingBaoGu"); }); | ||||
TakePot = new RelayCommand(() => { ActionManage.GetInstance.Send("TakePot"); }); | |||||
TakePotReset = new RelayCommand(() => { ActionManage.GetInstance.Send("TakePotReset"); }); | |||||
TakeMaterial= new RelayCommand(() => { ActionManage.GetInstance.Send("TakeMaterial"); }); | |||||
OutMeal = new RelayCommand(() => { ActionManage.GetInstance.Send("OutMeal"); }); | |||||
AddOil = new RelayCommand(() => { ActionManage.GetInstance.Send("AddOil", 1); }); | |||||
TempTurnOff = new RelayCommand(() => { ActionManage.GetInstance.Send("TakeOff", 1); }); | |||||
OneBlock = new RelayCommand(() => { ActionManage.GetInstance.Send("OneBlock",1); }); | |||||
TwoBlock = new RelayCommand(() => { ActionManage.GetInstance.Send("TwoBlock",1); }); | |||||
ThreeBlock = new RelayCommand(() => { ActionManage.GetInstance.Send("ThreeBlock",1); }); | |||||
OverTurnOff = new RelayCommand(() => { ActionManage.GetInstance.Send("OverTurnOff",1); }); | |||||
OverOneBlock = new RelayCommand(() => { ActionManage.GetInstance.Send("OverOneBlock",1); }); | |||||
OverTwoBlock = new RelayCommand(() => { ActionManage.GetInstance.Send("OverTwoBlock",1); }); | |||||
OverThreeBlock = new RelayCommand(() => { ActionManage.GetInstance.Send("OverThreeBlock",1); }); | |||||
OverGoOn = new RelayCommand(() => { ActionManage.GetInstance.Send("OverGoOn",1); }); | |||||
OverGoDown = new RelayCommand(() => { ActionManage.GetInstance.Send("OverGoDown",1); }); | |||||
AutoModel = new RelayCommand(()=>{ActionManage.GetInstance.Send("AutoModel",1); }); | |||||
ManualModel = new RelayCommand(() => { ActionManage.GetInstance.Send("ManualModel",1); }); | |||||
#region 配料仓控制 | |||||
OutMaterials = new RelayCommand(() => { ActionManage.GetInstance.Send("OutMaterials" ,new List<int> { PassagePosition,Weight } ); }); | |||||
#endregion | |||||
#region 炒锅1 | |||||
AddOil = new RelayCommand(() => { ActionManage.GetInstance.Send("AddOil", 1); });//加油 | |||||
StartFire = new RelayCommand(() => { ActionManage.GetInstance.Send("StartFire"); });//加热启动 | |||||
StopFire = new RelayCommand(() => { ActionManage.GetInstance.Send("StopFire"); });//加热停止 | |||||
StartStir = new RelayCommand(() => { ActionManage.GetInstance.Send("StartStir"); });//搅拌启动 | |||||
StopStir = new RelayCommand(() => { ActionManage.GetInstance.Send("StopStir"); });//搅拌停止 | |||||
OutFood = new RelayCommand(() => { ActionManage.GetInstance.Send("OutFood"); });//倒菜启动 | |||||
StirArmGoOrigin = new RelayCommand(() => { ActionManage.GetInstance.Send("StirArmGoOrigin"); });//搅拌臂去原点位 | |||||
StirArmGoWork = new RelayCommand(() => { ActionManage.GetInstance.Send("StirArmGoWork"); });//搅拌臂去炒制位 | |||||
HBOTGoWork = new RelayCommand(() => { ActionManage.GetInstance.Send("HBOTGoWork"); });//放盒子到位 | |||||
OutMeal = new RelayCommand(() => { ActionManage.GetInstance.Send("OutMeal"); });//出餐启动 | |||||
SetFire = new RelayCommand(() => { ActionManage.GetInstance.Send("SetFire", new List<int> { FireGear }); });//加热挡位设定 | |||||
SetStir = new RelayCommand(() => { ActionManage.GetInstance.Send("SetStir", new List<int> { StirGear }); });//搅拌挡位设定 | |||||
#endregion | |||||
#region 炒锅2 | |||||
SecAddOil = new RelayCommand(() => { ActionManage.GetInstance.Send("AddOil", 2); }); | SecAddOil = new RelayCommand(() => { ActionManage.GetInstance.Send("AddOil", 2); }); | ||||
SecTempTurnOff = new RelayCommand(() => { ActionManage.GetInstance.Send("TakeOff", 2); }); | SecTempTurnOff = new RelayCommand(() => { ActionManage.GetInstance.Send("TakeOff", 2); }); | ||||
SecOneBlock = new RelayCommand(() => { ActionManage.GetInstance.Send("OneBlock", 2); }); | SecOneBlock = new RelayCommand(() => { ActionManage.GetInstance.Send("OneBlock", 2); }); | ||||
@@ -114,7 +154,8 @@ namespace BPASmartClient.MorkF.ViewModel | |||||
SecOverGoDown = new RelayCommand(() => { ActionManage.GetInstance.Send("OverGoDown", 2); }); | SecOverGoDown = new RelayCommand(() => { ActionManage.GetInstance.Send("OverGoDown", 2); }); | ||||
SecAutoModel = new RelayCommand(() => { ActionManage.GetInstance.Send("AutoModel", 2); }); | SecAutoModel = new RelayCommand(() => { ActionManage.GetInstance.Send("AutoModel", 2); }); | ||||
SecManualModel = new RelayCommand(() => { ActionManage.GetInstance.Send("ManualModel", 2); }); | SecManualModel = new RelayCommand(() => { ActionManage.GetInstance.Send("ManualModel", 2); }); | ||||
#endregion | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,11 +1,16 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | <PropertyGroup> | ||||
<TargetFramework>net6.0</TargetFramework> | <TargetFramework>net6.0</TargetFramework> | ||||
<ImplicitUsings>enable</ImplicitUsings> | <ImplicitUsings>enable</ImplicitUsings> | ||||
<Nullable>enable</Nullable> | <Nullable>enable</Nullable> | ||||
<OutputType>Library</OutputType> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | |||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.0.0" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\BPASmartClient.Device\BPASmartClient.Device.csproj" /> | <ProjectReference Include="..\BPASmartClient.Device\BPASmartClient.Device.csproj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -1,6 +1,7 @@ | |||||
using BPA.Message.Enum; | using BPA.Message.Enum; | ||||
using BPASmartClient.Device; | using BPASmartClient.Device; | ||||
using BPASmartClient.EventBus; | using BPASmartClient.EventBus; | ||||
using BPASmartClient.Helper; | |||||
using BPASmartClient.Model; | using BPASmartClient.Model; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -13,15 +14,15 @@ namespace BPASmartClient.MorkMOC | |||||
{ | { | ||||
public class Control_MorkMOC : BaseDevice | public class Control_MorkMOC : BaseDevice | ||||
{ | { | ||||
public override global::BPA.Message.Enum.DeviceClientType DeviceType { get { return BPA.Message.Enum.DeviceClientType.TMC_MT; } } | |||||
GVL_MorkMOC morkMoc = new GVL_MorkMOC(); | GVL_MorkMOC morkMoc = new GVL_MorkMOC(); | ||||
PolymerBatching polymerBatching = new PolymerBatching(); | PolymerBatching polymerBatching = new PolymerBatching(); | ||||
//放大倍数 | //放大倍数 | ||||
const int expand = 10; | const int expand = 10; | ||||
public override DeviceClientType DeviceType => throw new NotImplementedException(); | |||||
public override void DoMain() | public override void DoMain() | ||||
{ | { | ||||
ServerInit(); | ServerInit(); | ||||
@@ -178,7 +179,25 @@ namespace BPASmartClient.MorkMOC | |||||
public override void SimOrder() | public override void SimOrder() | ||||
{ | { | ||||
throw new NotImplementedException(); | |||||
ActionManage.GetInstance.Register(new Action<object>((o) => | |||||
{ | |||||
if (o == null) return; | |||||
if(o is LocalRecipe recipe) | |||||
{ | |||||
Dictionary<int, int> OrderPushes = new Dictionary<int, int>(); | |||||
foreach(var item in recipe.localMaterails) | |||||
{ | |||||
OrderPushes.Add(Convert.ToInt32(item.MaterialPosition), Convert.ToInt32(item.MaterialWeight)); | |||||
} | |||||
morkMoc.morkOrderPushes.Enqueue(new OrderLocInfo() | |||||
{ | |||||
GoodName = recipe.RecipeName, | |||||
SuborderId = Guid.NewGuid().ToString(), | |||||
GoodPushes = OrderPushes | |||||
}); | |||||
} | |||||
}),"MakeGoods"); | |||||
} | } | ||||
public override void Stop() | public override void Stop() | ||||
@@ -0,0 +1,55 @@ | |||||
using Microsoft.Toolkit.Mvvm.ComponentModel; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.ObjectModel; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace BPASmartClient.MorkMOC | |||||
{ | |||||
public partial class LocalMaterail:ObservableObject | |||||
{ | |||||
/// <summary> | |||||
/// 物料ID | |||||
/// </summary> | |||||
[ObservableProperty] | |||||
private string? _materialID; | |||||
/// <summary> | |||||
/// 物料本地名称 | |||||
/// </summary> | |||||
[ObservableProperty] | |||||
private string? _materialName; | |||||
/// <summary> | |||||
/// 物料位置 | |||||
/// </summary> | |||||
[ObservableProperty] | |||||
private int? _materialPosition; | |||||
/// <summary> | |||||
/// 物料重量 | |||||
/// </summary> | |||||
[ObservableProperty] | |||||
private string? _materialWeight; | |||||
} | |||||
public partial class LocalRecipe:ObservableObject | |||||
{ | |||||
/// <summary> | |||||
/// 配方ID | |||||
/// </summary> | |||||
[ObservableProperty] | |||||
private string? _recipeID; | |||||
/// <summary> | |||||
/// 配方名称 | |||||
/// </summary> | |||||
[ObservableProperty] | |||||
private string? _recipeName; | |||||
/// <summary> | |||||
/// 原料集合 | |||||
/// </summary> | |||||
public ObservableCollection<LocalMaterail> localMaterails { get; set; } = new ObservableCollection<LocalMaterail>(); | |||||
} | |||||
} |
@@ -10,6 +10,9 @@ namespace BPASmartClient.MorkMOC | |||||
public string SuborderId { get; set; } | public string SuborderId { get; set; } | ||||
public ushort RecipeNumber { get; set; } | public ushort RecipeNumber { get; set; } | ||||
public string GoodName { get; set; } | public string GoodName { get; set; } | ||||
/// <summary> | |||||
/// 物料位置,物料重量 | |||||
/// </summary> | |||||
public Dictionary<int, int> GoodPushes { get; set; } | public Dictionary<int, int> GoodPushes { get; set; } | ||||
} | } | ||||
@@ -271,9 +271,11 @@ namespace BPASmartClient.MorkS | |||||
{ | { | ||||
mORKS.doOrderEvents.Add(order); | mORKS.doOrderEvents.Add(order); | ||||
if (order.MorkOrder.GoodBatchings == null) return; | if (order.MorkOrder.GoodBatchings == null) return; | ||||
if (mORKS.HistorySuborderId.Contains(order.MorkOrder.SuborderId)) return; | |||||
OrderCount++; | OrderCount++; | ||||
OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT); | OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT); | ||||
DeviceProcessLogShow($"接收到{OrderCount}次订单,订单ID:{order.MorkOrder.SuborderId}"); | DeviceProcessLogShow($"接收到{OrderCount}次订单,订单ID:{order.MorkOrder.SuborderId}"); | ||||
mORKS.HistorySuborderId.Add(order.MorkOrder.SuborderId); | |||||
foreach (var item in order.MorkOrder.GoodBatchings) | foreach (var item in order.MorkOrder.GoodBatchings) | ||||
{ | { | ||||
var res = orderMaterialDelivery?.BatchingInfo?.FirstOrDefault(p => p.BatchingId == item.BatchingId); | var res = orderMaterialDelivery?.BatchingInfo?.FirstOrDefault(p => p.BatchingId == item.BatchingId); | ||||
@@ -12,6 +12,7 @@ namespace BPASmartClient.MorkS | |||||
{ | { | ||||
public class GVL_MORKS : IStatus | public class GVL_MORKS : IStatus | ||||
{ | { | ||||
public List<string> HistorySuborderId { get; set; } = new List<string>(); | |||||
/// <summary> | /// <summary> | ||||
/// 机器人取面 | /// 机器人取面 | ||||
/// PLC -> M0.3 | /// PLC -> M0.3 | ||||
@@ -29,6 +29,10 @@ namespace Model | |||||
public int MaterialID { get { return _materialID; } set { _materialID = value; OnPropertyChanged(); } } | public int MaterialID { get { return _materialID; } set { _materialID = value; OnPropertyChanged(); } } | ||||
private int _materialID =1; | private int _materialID =1; | ||||
/// <summary> | /// <summary> | ||||
/// 物料本地名称 | |||||
/// </summary> | |||||
public string MaterialName; | |||||
/// <summary> | |||||
/// 物料位置 | /// 物料位置 | ||||
/// </summary> | /// </summary> | ||||
public string Material { get { return _material; } set { _material = value; OnPropertyChanged(); } } | public string Material { get { return _material; } set { _material = value; OnPropertyChanged(); } } | ||||
@@ -6,20 +6,19 @@ | |||||
<!--<add key="ClientId" value="43"/>--> | <!--<add key="ClientId" value="43"/>--> | ||||
<add key="IsEnableTest" value="false"/> | <add key="IsEnableTest" value="false"/> | ||||
<!--测试环境--><!-- | |||||
<add key="apollouri" value="http://10.2.1.21:28080/"/> | |||||
<add key="AppId" value="test1_HostComputer"/> | |||||
<add key ="Namespaces" value="DEV.test1.Config"/>--> | |||||
<!--测试环境--> | |||||
<!--<add key="apollouri" value="http://10.2.1.21:28080/"/> | |||||
<add key="AppId" value="test1_HostComputer"/> | |||||
<add key ="Namespaces" value="DEV.test1.Config"/>--> | |||||
<!--开发环境--> | <!--开发环境--> | ||||
<!--<add key="apollouri" value="http://47.108.65.220:28080/"/> | |||||
<add key="AppId" value="HostComputer"/> | |||||
<add key ="Namespaces" value="DEV.Config"/>--> | |||||
<add key="apollouri" value="http://10.2.1.21:28080/"/> | |||||
<add key="AppId" value="HostComputer"/> | |||||
<add key ="Namespaces" value="DEV.Config"/> | |||||
<!--正式环境--> | <!--正式环境--> | ||||
<add key="apollouri" value="http://47.108.65.220:28080/"/> | |||||
<!--<add key="apollouri" value="http://47.108.65.220:28080/"/> | |||||
<add key="appid" value="hostcomputer"/> | <add key="appid" value="hostcomputer"/> | ||||
<add key ="namespaces" value="test1.config"/> | |||||
<add key ="namespaces" value="test1.config"/>--> | |||||
<!--阿里云上报启动方式:API 或者 LOCAL--> | <!--阿里云上报启动方式:API 或者 LOCAL--> | ||||
<!--API :通过客户端ID,调用接口查询“设备连接信息”--> | <!--API :通过客户端ID,调用接口查询“设备连接信息”--> | ||||