@@ -93,6 +93,8 @@ | |||||
<None Remove="Image\圆角矩形 30 拷贝.png" /> | <None Remove="Image\圆角矩形 30 拷贝.png" /> | ||||
<None Remove="Image\圆角矩形 4.png" /> | <None Remove="Image\圆角矩形 4.png" /> | ||||
<None Remove="Image\圆角矩形.png" /> | <None Remove="Image\圆角矩形.png" /> | ||||
<None Remove="Image\工艺流程.jpg" /> | |||||
<None Remove="Image\工艺流程.png" /> | |||||
<None Remove="Image\底部背景.png" /> | <None Remove="Image\底部背景.png" /> | ||||
<None Remove="Image\搜索按钮.png" /> | <None Remove="Image\搜索按钮.png" /> | ||||
<None Remove="Image\搜索框.png" /> | <None Remove="Image\搜索框.png" /> | ||||
@@ -173,6 +175,7 @@ | |||||
<None Remove="Image\顶部切图\Top_L.png" /> | <None Remove="Image\顶部切图\Top_L.png" /> | ||||
<None Remove="Image\顶部切图\窗体背景.png" /> | <None Remove="Image\顶部切图\窗体背景.png" /> | ||||
<None Remove="Image\顶部切图\窗体背景2.png" /> | <None Remove="Image\顶部切图\窗体背景2.png" /> | ||||
<None Remove="Image\顶部切图\自动化产线上位机控制系统.png" /> | |||||
<None Remove="Image\顶部切图\返回按钮1.png" /> | <None Remove="Image\顶部切图\返回按钮1.png" /> | ||||
<None Remove="Image\顶部切图\返回按钮2.png" /> | <None Remove="Image\顶部切图\返回按钮2.png" /> | ||||
<None Remove="Image\顶部切图\返回按钮图标.png" /> | <None Remove="Image\顶部切图\返回按钮图标.png" /> | ||||
@@ -203,6 +206,8 @@ | |||||
<Resource Include="Image\告警\无告警.png" /> | <Resource Include="Image\告警\无告警.png" /> | ||||
<Resource Include="Image\告警\无告警1.png" /> | <Resource Include="Image\告警\无告警1.png" /> | ||||
<Resource Include="Image\告警\轻微告警.png" /> | <Resource Include="Image\告警\轻微告警.png" /> | ||||
<Resource Include="Image\工艺流程.jpg" /> | |||||
<Resource Include="Image\工艺流程.png" /> | |||||
<Resource Include="Image\界面2.png"> | <Resource Include="Image\界面2.png"> | ||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||||
</Resource> | </Resource> | ||||
@@ -221,6 +226,7 @@ | |||||
<Resource Include="Image\顶部切图\Top_L.png" /> | <Resource Include="Image\顶部切图\Top_L.png" /> | ||||
<Resource Include="Image\顶部切图\窗体背景.png" /> | <Resource Include="Image\顶部切图\窗体背景.png" /> | ||||
<Resource Include="Image\顶部切图\窗体背景2.png" /> | <Resource Include="Image\顶部切图\窗体背景2.png" /> | ||||
<Resource Include="Image\顶部切图\自动化产线上位机控制系统.png" /> | |||||
<Resource Include="Image\顶部切图\返回按钮1.png" /> | <Resource Include="Image\顶部切图\返回按钮1.png" /> | ||||
<Resource Include="Image\顶部切图\返回按钮2.png" /> | <Resource Include="Image\顶部切图\返回按钮2.png" /> | ||||
<Resource Include="Image\顶部切图\返回按钮图标.png" /> | <Resource Include="Image\顶部切图\返回按钮图标.png" /> | ||||
@@ -0,0 +1,45 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Globalization; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using System.Windows.Data; | |||||
using System.Windows.Media; | |||||
namespace BPASmartClient.CustomResource.Converters | |||||
{ | |||||
public class StatusConverter : IValueConverter | |||||
{ | |||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | |||||
{ | |||||
SolidColorBrush returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 204, 255)); | |||||
if (value != null && value is ushort statusValue) | |||||
{ | |||||
switch (statusValue) | |||||
{ | |||||
case 0: | |||||
returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 204, 255)); | |||||
break; | |||||
case 1: | |||||
returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 255, 127)); | |||||
break; | |||||
case 2: | |||||
returnValue = new SolidColorBrush(Color.FromArgb(255, 255, 215, 00)); | |||||
break; | |||||
case 3: | |||||
returnValue = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
return returnValue; | |||||
} | |||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
} | |||||
} |
@@ -181,6 +181,14 @@ | |||||
</Style.Setters> | </Style.Setters> | ||||
</Style> | </Style> | ||||
<Style x:Key="imagetop_工艺流程" TargetType="Image"> | |||||
<Style.Setters> | |||||
<Setter Property="VerticalAlignment" Value="Stretch" /> | |||||
<Setter Property="HorizontalAlignment" Value="Stretch" /> | |||||
<Setter Property="Source" Value="/BPASmartClient.CustomResource;component/Image/工艺流程.png" /> | |||||
</Style.Setters> | |||||
</Style> | |||||
<Style x:Key="imagetop_维护" TargetType="Image"> | <Style x:Key="imagetop_维护" TargetType="Image"> | ||||
<Style.Setters> | <Style.Setters> | ||||
<Setter Property="Width" Value="20" /> | <Setter Property="Width" Value="20" /> | ||||
@@ -225,7 +233,7 @@ | |||||
<Setter Property="Width" Value="250" /> | <Setter Property="Width" Value="250" /> | ||||
<Setter Property="VerticalAlignment" Value="Top" /> | <Setter Property="VerticalAlignment" Value="Top" /> | ||||
<Setter Property="HorizontalAlignment" Value="Left" /> | <Setter Property="HorizontalAlignment" Value="Left" /> | ||||
<Setter Property="Source" Value="/BPASmartClient.CustomResource;component/Image/顶部切图/黑菠萝智慧餐饮管理系统.png" /> | |||||
<Setter Property="Source" Value="/BPASmartClient.CustomResource;component/Image/顶部切图/自动化产线上位机控制系统.png" /> | |||||
</Style.Setters> | </Style.Setters> | ||||
</Style> | </Style> | ||||
@@ -49,11 +49,11 @@ namespace BPASmartClient.Modbus | |||||
Port = port; | Port = port; | ||||
modbusFactory = new ModbusFactory(); | modbusFactory = new ModbusFactory(); | ||||
Connect(); | Connect(); | ||||
master.Transport.ReadTimeout = 2000;//读取超时时间 | |||||
master.Transport.WriteTimeout = 2000;//写入超时时间 | |||||
master.Transport.Retries = 10;//重试次数 | |||||
if (Connected) | if (Connected) | ||||
{ | { | ||||
master.Transport.ReadTimeout = 2000;//读取超时时间 | |||||
master.Transport.WriteTimeout = 2000;//写入超时时间 | |||||
master.Transport.Retries = 10;//重试次数 | |||||
ConnectOk?.Invoke(); | ConnectOk?.Invoke(); | ||||
MessageLog.GetInstance.Show($"设备【{ip}:{port}】连接成功"); | MessageLog.GetInstance.Show($"设备【{ip}:{port}】连接成功"); | ||||
} | } | ||||
@@ -0,0 +1,23 @@ | |||||
<UserControl x:Class="BPASmartClient.Control.GYLCControl" | |||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||||
xmlns:local="clr-namespace:BPASmartClient.Control" | |||||
mc:Ignorable="d" | |||||
d:DesignHeight="450" d:DesignWidth="800"> | |||||
<UserControl.Resources> | |||||
<ResourceDictionary> | |||||
<ResourceDictionary.MergedDictionaries> | |||||
<ResourceDictionary Source="/BPASmartClient.CustomResource;component/Themes/GenricStyle.xaml" /> | |||||
<ResourceDictionary Source="/BPASmartClient.CustomResource;component/Themes/MyStyle.xaml" /> | |||||
</ResourceDictionary.MergedDictionaries> | |||||
</ResourceDictionary> | |||||
</UserControl.Resources> | |||||
<ScrollViewer> | |||||
<Image Style="{DynamicResource imagetop_工艺流程}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"> | |||||
</Image> | |||||
</ScrollViewer> | |||||
</UserControl> |
@@ -0,0 +1,28 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using System.Windows; | |||||
using System.Windows.Controls; | |||||
using System.Windows.Data; | |||||
using System.Windows.Documents; | |||||
using System.Windows.Input; | |||||
using System.Windows.Media; | |||||
using System.Windows.Media.Imaging; | |||||
using System.Windows.Navigation; | |||||
using System.Windows.Shapes; | |||||
namespace BPASmartClient.Control | |||||
{ | |||||
/// <summary> | |||||
/// GYLCControl.xaml 的交互逻辑 | |||||
/// </summary> | |||||
public partial class GYLCControl : UserControl | |||||
{ | |||||
public GYLCControl() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@@ -152,6 +152,12 @@ | |||||
Header="IOT监视" | Header="IOT监视" | ||||
Tag="IOTView" /> | Tag="IOTView" /> | ||||
<Separator /> | <Separator /> | ||||
<MenuItem | |||||
Click="MenuItem_Click" | |||||
FontSize="12" | |||||
Header="工艺流程" | |||||
Tag="GYLCControl" /> | |||||
<Separator /> | |||||
</MenuItem> | </MenuItem> | ||||
<MenuItem Header="综合查询"> | <MenuItem Header="综合查询"> | ||||
<MenuItem | <MenuItem | ||||
@@ -23,6 +23,7 @@ | |||||
<con:ColorConverter x:Key="ColorConverter" /> | <con:ColorConverter x:Key="ColorConverter" /> | ||||
<con:TextConverter x:Key="TextConverter" /> | <con:TextConverter x:Key="TextConverter" /> | ||||
<con:VisibleTypeConverter x:Key="VisibleTypeConverter" /> | <con:VisibleTypeConverter x:Key="VisibleTypeConverter" /> | ||||
<con:StatusConverter x:Key="StatusConverter" /> | |||||
</ResourceDictionary> | </ResourceDictionary> | ||||
<ResourceDictionary> | <ResourceDictionary> | ||||
@@ -14,16 +14,15 @@ namespace DosingSystem.Model | |||||
{ | { | ||||
public class DeviceInquire | public class DeviceInquire | ||||
{ | { | ||||
private volatile static DeviceInquire _Instance; | private volatile static DeviceInquire _Instance; | ||||
public static DeviceInquire GetInstance => _Instance ?? (_Instance = new DeviceInquire()); | public static DeviceInquire GetInstance => _Instance ?? (_Instance = new DeviceInquire()); | ||||
private DeviceInquire() { } | private DeviceInquire() { } | ||||
string IPSegment = "192.168.1."; | string IPSegment = "192.168.1."; | ||||
string NameAddress = "VW5000"; | |||||
string NameAddress = "VW0"; | |||||
int count = 0; | int count = 0; | ||||
private static readonly object _lock = new object(); | private static readonly object _lock = new object(); | ||||
ConcurrentDictionary<string, ModbusTcp> modbusTcps = new ConcurrentDictionary<string, ModbusTcp>(); | |||||
ConcurrentDictionary<string, DeviceStatus> DeviceLists = new ConcurrentDictionary<string, DeviceStatus>(); | |||||
List<string> InvalidIP = new List<string>(); | List<string> InvalidIP = new List<string>(); | ||||
public void Init() | public void Init() | ||||
@@ -36,10 +35,14 @@ namespace DosingSystem.Model | |||||
}), "配料机设备上线监听", true); | }), "配料机设备上线监听", true); | ||||
} | } | ||||
public ModbusTcp GetModbusTcp(string ip) | |||||
public DeviceStatus GetDevice(string deviceName) | |||||
{ | { | ||||
if (modbusTcps.ContainsKey(ip)) return modbusTcps[ip]; | |||||
else return default; | |||||
if (deviceName != null) | |||||
{ | |||||
var res = DeviceLists.Values.FirstOrDefault(p => p.DeviceName == deviceName); | |||||
if (res != null) return res; | |||||
} | |||||
return default; | |||||
} | } | ||||
private void IpAddressLines() | private void IpAddressLines() | ||||
@@ -48,8 +51,7 @@ namespace DosingSystem.Model | |||||
{ | { | ||||
if (!InvalidIP.Contains($"{IPSegment}{i}")) | if (!InvalidIP.Contains($"{IPSegment}{i}")) | ||||
{ | { | ||||
Ping myPing; | |||||
myPing = new Ping(); | |||||
Ping myPing = new Ping(); | |||||
myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted); | myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted); | ||||
string pingIP = $"{IPSegment}{i}"; | string pingIP = $"{IPSegment}{i}"; | ||||
myPing.SendAsync(pingIP, 1000, null); | myPing.SendAsync(pingIP, 1000, null); | ||||
@@ -69,17 +71,23 @@ namespace DosingSystem.Model | |||||
if (e.Reply.Status == IPStatus.Success) | if (e.Reply.Status == IPStatus.Success) | ||||
{ | { | ||||
string ip = e.Reply.Address.ToString(); | string ip = e.Reply.Address.ToString(); | ||||
if (!modbusTcps.ContainsKey(ip)) | |||||
if (!DeviceLists.ContainsKey(ip)) | |||||
{ | { | ||||
modbusTcps.TryAdd(ip, new ModbusTcp()); | |||||
modbusTcps[ip].IsReconnect = false; | |||||
Task.Run(new Action(() => { modbusTcps[ip].ModbusTcpConnect(ip); })); | |||||
modbusTcps[ip].ConnectOk = new Action(() => | |||||
DeviceStatus DS = new DeviceStatus(); | |||||
//DeviceLists.TryAdd(ip, new DeviceStatus()); | |||||
//DeviceLists[ip].modbusTcp.IsReconnect = false; | |||||
//Task.Run(new Action(() => { DeviceLists[ip].modbusTcp.ModbusTcpConnect(ip, 508); })); | |||||
DS.modbusTcp.IsReconnect = false; | |||||
Task.Run(new Action(() => { DS.modbusTcp.ModbusTcpConnect(ip, 508); })); | |||||
DS.modbusTcp.ConnectOk = new Action(() => | |||||
{ | { | ||||
string DeviceName = modbusTcps[ip].GetString(NameAddress, 10); | |||||
//string DeviceName = DeviceLists[ip].modbusTcp.GetString(NameAddress, 20); | |||||
string DeviceName = DS.modbusTcp.GetString(NameAddress, 20); | |||||
if (DeviceName.Length > 0) | if (DeviceName.Length > 0) | ||||
{ | { | ||||
DeviceLists.TryAdd(ip, DS); | |||||
DeviceLists[ip].Init(DeviceName); | |||||
DeviceLists[ip].modbusTcp.IsReconnect = true; | |||||
App.Current.Dispatcher.Invoke(new Action(() => | App.Current.Dispatcher.Invoke(new Action(() => | ||||
{ | { | ||||
DeviceListViewModel.devices.Add(new Devices() | DeviceListViewModel.devices.Add(new Devices() | ||||
@@ -87,6 +95,9 @@ namespace DosingSystem.Model | |||||
DeviceName = DeviceName, | DeviceName = DeviceName, | ||||
IpAddress = ip | IpAddress = ip | ||||
}); | }); | ||||
if (!NewRecipeViewModel.RawMaterialNames.Contains(DeviceName)) | |||||
NewRecipeViewModel.RawMaterialNames.Add(DeviceName); | |||||
})); | })); | ||||
} | } | ||||
else | else | ||||
@@ -95,23 +106,71 @@ namespace DosingSystem.Model | |||||
} | } | ||||
}); | }); | ||||
modbusTcps[ip].ConnectFail = new Action(() => | |||||
DS.modbusTcp.ConnectFail = new Action(() => | |||||
{ | { | ||||
if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); | if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); | ||||
}); | }); | ||||
modbusTcps[ip].Disconnect = new Action(() => | |||||
DS.modbusTcp.Disconnect = new Action(() => | |||||
{ | { | ||||
if (InvalidIP.Contains(ip)) InvalidIP.Remove(ip); | if (InvalidIP.Contains(ip)) InvalidIP.Remove(ip); | ||||
var res = DeviceListViewModel.devices.FirstOrDefault(P => P.IpAddress == ip); | var res = DeviceListViewModel.devices.FirstOrDefault(P => P.IpAddress == ip); | ||||
if (res != null && DeviceListViewModel.devices.Contains(res)) | if (res != null && DeviceListViewModel.devices.Contains(res)) | ||||
App.Current.Dispatcher.Invoke(new Action(() => { DeviceListViewModel.devices.Remove(res); })); | |||||
App.Current.Dispatcher.Invoke(new Action(() => | |||||
{ | |||||
DeviceListViewModel.devices.Remove(res); | |||||
if (!NewRecipeViewModel.RawMaterialNames.Contains(res.DeviceName)) | |||||
NewRecipeViewModel.RawMaterialNames.Remove(res.DeviceName); | |||||
})); | |||||
//DeviceLists[ip].Dispose(); | |||||
DS.Dispose(); | |||||
}); | }); | ||||
} | } | ||||
} | } | ||||
CompleteCount(); | CompleteCount(); | ||||
} | } | ||||
} | |||||
public class DeviceStatus | |||||
{ | |||||
public string DeviceName = String.Empty; | |||||
public ModbusTcp modbusTcp = new ModbusTcp(); | |||||
public void Init(string DeviceName) | |||||
{ | |||||
this.DeviceName = DeviceName; | |||||
if (modbusTcp.Connected) | |||||
{ | |||||
ThreadManage.GetInstance().StartLong(new Action(() => | |||||
{ | |||||
var res = this.modbusTcp.Read("VW100"); | |||||
if (res is ushort ushortValue) | |||||
{ | |||||
RunStatus = ushortValue; | |||||
} | |||||
Thread.Sleep(100); | |||||
}), $"{DeviceName} 开始监听", true); | |||||
} | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
ThreadManage.GetInstance().StopTask($"{DeviceName} 开始监听"); | |||||
} | |||||
public bool IsConnected => modbusTcp.Connected; | |||||
/// <summary> | |||||
/// 配料系统运行状态 | |||||
/// </summary> | |||||
public ushort RunStatus { get; private set; } | |||||
public void Start(float Value) | |||||
{ | |||||
if (modbusTcp.Connected) | |||||
{ | |||||
modbusTcp.SetReal("VW40", Value);//写入配方量 | |||||
modbusTcp.Write("M0.0", true);//设备启动写入 | |||||
} | |||||
} | |||||
} | } | ||||
} | } |
@@ -4,6 +4,7 @@ using System.Linq; | |||||
using System.Text; | using System.Text; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||
using DosingSystem.ViewModel; | |||||
namespace DosingSystem.Model | namespace DosingSystem.Model | ||||
{ | { | ||||
@@ -0,0 +1,48 @@ | |||||
using Microsoft.Toolkit.Mvvm.ComponentModel; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace DosingSystem.Model | |||||
{ | |||||
/// <summary> | |||||
/// 原料模块 | |||||
/// </summary> | |||||
public class RawMaterialModel : ObservableObject | |||||
{ | |||||
/// <summary> | |||||
/// 原料名称 | |||||
/// </summary> | |||||
public string RawMaterialName { get { return _mRawMaterialName; } set { _mRawMaterialName = value; OnPropertyChanged(); } } | |||||
private string _mRawMaterialName; | |||||
/// <summary> | |||||
/// 原料设备IP | |||||
/// </summary> | |||||
public string DeviceIp { get; set; } | |||||
/// <summary> | |||||
/// 原料重量 | |||||
/// </summary> | |||||
public float RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value; OnPropertyChanged(); } } | |||||
private float _mRawMaterialWeight; | |||||
/// <summary> | |||||
/// 原料ID | |||||
/// </summary> | |||||
public string RawMaterialId { get { return _mRawMaterialId; } set { _mRawMaterialId = value; OnPropertyChanged(); } } | |||||
private string _mRawMaterialId; | |||||
/// <summary> | |||||
/// 原料设备执行状态 | |||||
/// 1:等待下料 | |||||
/// 2:下料中 | |||||
/// 3:下料完成 | |||||
/// </summary> | |||||
public int RecipeStatus { get { return _mRecipeStatus; } set { _mRecipeStatus = value; OnPropertyChanged(); } } | |||||
private int _mRecipeStatus; | |||||
} | |||||
} |
@@ -9,8 +9,13 @@ using Microsoft.Toolkit.Mvvm.ComponentModel; | |||||
namespace DosingSystem.Model | namespace DosingSystem.Model | ||||
{ | { | ||||
/// <summary> | |||||
/// 配方模块 | |||||
/// </summary> | |||||
public class RecipeModel : ObservableObject | public class RecipeModel : ObservableObject | ||||
{ | { | ||||
public bool IsEnable { get { return _mIsEnable; } set { _mIsEnable = value; OnPropertyChanged(); } } | |||||
private bool _mIsEnable = true; | |||||
/// <summary> | /// <summary> | ||||
/// 序号 | /// 序号 | ||||
@@ -30,7 +35,11 @@ namespace DosingSystem.Model | |||||
public string RecipCode { get { return _mRecipCode; } set { _mRecipCode = value; OnPropertyChanged(); } } | public string RecipCode { get { return _mRecipCode; } set { _mRecipCode = value; OnPropertyChanged(); } } | ||||
private string _mRecipCode; | private string _mRecipCode; | ||||
public ObservableCollection<RawMaterial> RawMaterials { get; set; } = new ObservableCollection<RawMaterial>(); | |||||
/// <summary> | |||||
/// 原料集合 | |||||
/// </summary> | |||||
public ObservableCollection<RawMaterialModel> RawMaterials { get; set; } = new ObservableCollection<RawMaterialModel>(); | |||||
} | } | ||||
@@ -139,7 +139,7 @@ | |||||
<ColumnDefinition Width="0.5*" /> | <ColumnDefinition Width="0.5*" /> | ||||
</Grid.ColumnDefinitions> | </Grid.ColumnDefinitions> | ||||
<ComboBox | |||||
<!--<ComboBox | |||||
Name="cb" | Name="cb" | ||||
Grid.Column="0" | Grid.Column="0" | ||||
Margin="3,1" | Margin="3,1" | ||||
@@ -153,8 +153,19 @@ | |||||
ItemsSource="{Binding DataContext.RawMaterialNames, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | ItemsSource="{Binding DataContext.RawMaterialNames, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | ||||
SelectedIndex="0" | SelectedIndex="0" | ||||
Style="{StaticResource ComboBoxStyle}" | Style="{StaticResource ComboBoxStyle}" | ||||
Text="{Binding RawMaterialName}" /> | |||||
Text="{Binding RawMaterialName}" />--> | |||||
<TextBox | |||||
Name="cb" | |||||
Grid.Column="0" | |||||
Margin="3,1" | |||||
VerticalAlignment="Center" | |||||
BorderBrush="#FF074B92" | |||||
BorderThickness="1" | |||||
FontFamily="楷体" | |||||
FontSize="20" | |||||
Foreground="#FF2AB2E7" | |||||
Text="{Binding RawMaterialName}" /> | |||||
<StackPanel | <StackPanel | ||||
Grid.Column="1" | Grid.Column="1" | ||||
VerticalAlignment="Center" | VerticalAlignment="Center" | ||||
@@ -2,26 +2,187 @@ | |||||
x:Class="DosingSystem.View.RecipeControlView" | x:Class="DosingSystem.View.RecipeControlView" | ||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
xmlns:control="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" | |||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||||
xmlns:control="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" | |||||
xmlns:pry="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" | |||||
xmlns:vm="clr-namespace:DosingSystem.ViewModel" | |||||
xmlns:local="clr-namespace:DosingSystem.View" | xmlns:local="clr-namespace:DosingSystem.View" | ||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||
xmlns:pry="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" | |||||
xmlns:vm="clr-namespace:DosingSystem.ViewModel" | |||||
d:DesignHeight="450" | d:DesignHeight="450" | ||||
d:DesignWidth="800" | d:DesignWidth="800" | ||||
mc:Ignorable="d"> | mc:Ignorable="d"> | ||||
<UserControl.DataContext> | <UserControl.DataContext> | ||||
<vm:RecipeControlViewModel/> | |||||
<vm:RecipeControlViewModel /> | |||||
</UserControl.DataContext> | </UserControl.DataContext> | ||||
<UserControl.Resources> | |||||
<Style x:Key="UserItemContainerStyle" TargetType="ListBoxItem"> | |||||
<Style.Resources> | |||||
<!-- SelectedItem with focus --> | |||||
<SolidColorBrush | |||||
x:Key="{x:Static SystemColors.HighlightBrushKey}" | |||||
Opacity=".4" | |||||
Color="White" /> | |||||
<!-- SelectedItem without focus --> | |||||
<SolidColorBrush | |||||
x:Key="{x:Static SystemColors.ControlBrushKey}" | |||||
Opacity=".4" | |||||
Color="White" /> | |||||
</Style.Resources> | |||||
<!-- 设置触发器 --> | |||||
<Style.Triggers> | |||||
<Trigger Property="IsMouseOver" Value="true"> | |||||
<Setter Property="Background" Value="White" /> | |||||
<Setter Property="Foreground" Value="White" /> | |||||
</Trigger> | |||||
<Trigger Property="IsFocused" Value="true"> | |||||
<Setter Property="Background" Value="White" /> | |||||
<Setter Property="Foreground" Value="White" /> | |||||
</Trigger> | |||||
</Style.Triggers> | |||||
</Style> | |||||
</UserControl.Resources> | |||||
<Grid> | <Grid> | ||||
<TextBlock | |||||
HorizontalAlignment="Center" | |||||
VerticalAlignment="Center" | |||||
FontSize="40" | |||||
Foreground="Wheat" | |||||
Text="配方控制" /> | |||||
<ScrollViewer> | |||||
<ItemsControl ItemsSource="{Binding Recipes}"> | |||||
<ItemsControl.ItemTemplate> | |||||
<DataTemplate> | |||||
<Grid Height="150" VerticalAlignment="Top"> | |||||
<Border | |||||
Name="ShadowElement" | |||||
Height="150" | |||||
VerticalAlignment="Top" | |||||
BorderBrush="#00BEFA" | |||||
BorderThickness="2" | |||||
ClipToBounds="True" | |||||
CornerRadius="8"> | |||||
<Border.Effect> | |||||
<DropShadowEffect | |||||
BlurRadius="18" | |||||
ShadowDepth="0" | |||||
Color="#00BEFA" /> | |||||
</Border.Effect> | |||||
</Border> | |||||
<Grid> | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition Width="auto" /> | |||||
<ColumnDefinition /> | |||||
<ColumnDefinition Width="auto" /> | |||||
</Grid.ColumnDefinitions> | |||||
<Grid Margin="20,0,0,0"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition /> | |||||
<RowDefinition /> | |||||
</Grid.RowDefinitions> | |||||
<TextBlock | |||||
FontSize="40" | |||||
Foreground="White" | |||||
Text="{Binding RecipeName}" /> | |||||
<Button | |||||
Grid.Row="1" | |||||
Width="80" | |||||
Height="30" | |||||
HorizontalAlignment="Left" | |||||
Command="{Binding DataContext.StartCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | |||||
CommandParameter="{Binding RecipeName}" | |||||
Content="配方下发" | |||||
IsEnabled="{Binding IsEnable}" /> | |||||
</Grid> | |||||
<ListView | |||||
Grid.Column="1" | |||||
Margin="10" | |||||
Background="Transparent" | |||||
BorderBrush="#00BEFA" | |||||
BorderThickness="2,0,2,0" | |||||
ItemsSource="{Binding RawMaterials}" | |||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"> | |||||
<ListView.ItemsPanel> | |||||
<ItemsPanelTemplate> | |||||
<UniformGrid | |||||
HorizontalAlignment="Left" | |||||
VerticalAlignment="Top" | |||||
Columns="4" /> | |||||
</ItemsPanelTemplate> | |||||
</ListView.ItemsPanel> | |||||
<ListView.ItemTemplate> | |||||
<DataTemplate> | |||||
<StackPanel | |||||
Grid.Column="1" | |||||
Height="20" | |||||
Margin="20,0,0,0" | |||||
VerticalAlignment="Top" | |||||
Orientation="Horizontal"> | |||||
<Ellipse | |||||
Width="{Binding ElementName=n, Path=ActualHeight}" | |||||
Margin="0,0,5,0" | |||||
Fill="{Binding RecipeStatus, Converter={StaticResource StatusConverter}}" /> | |||||
<TextBlock | |||||
Name="n" | |||||
FontSize="16" | |||||
Foreground="White" | |||||
Text="{Binding RawMaterialName}" /> | |||||
</StackPanel> | |||||
</DataTemplate> | |||||
</ListView.ItemTemplate> | |||||
</ListView> | |||||
<StackPanel | |||||
Grid.Column="2" | |||||
Margin="5,0" | |||||
VerticalAlignment="Center"> | |||||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal"> | |||||
<Ellipse | |||||
Width="{Binding ElementName=tb, Path=ActualHeight}" | |||||
Margin="0,0,5,0" | |||||
Fill="Green" /> | |||||
<TextBlock | |||||
Name="tb" | |||||
Foreground="#ddd" | |||||
Text="等待下料" /> | |||||
</StackPanel> | |||||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal"> | |||||
<Ellipse | |||||
Width="{Binding ElementName=tb, Path=ActualHeight}" | |||||
Margin="0,0,5,0" | |||||
Fill="Yellow" /> | |||||
<TextBlock | |||||
Name="tb1" | |||||
Foreground="#ddd" | |||||
Text="下料中" /> | |||||
</StackPanel> | |||||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal"> | |||||
<Ellipse | |||||
Width="{Binding ElementName=tb, Path=ActualHeight}" | |||||
Margin="0,0,5,0" | |||||
Fill="Aqua" /> | |||||
<TextBlock | |||||
Name="tb2" | |||||
Foreground="#ddd" | |||||
Text="下料完成" /> | |||||
</StackPanel> | |||||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal"> | |||||
<Ellipse | |||||
Width="{Binding ElementName=tb, Path=ActualHeight}" | |||||
Margin="0,0,5,0" | |||||
Fill="Red" /> | |||||
<TextBlock | |||||
Name="tb3" | |||||
Foreground="#ddd" | |||||
Text="原料设备异常" /> | |||||
</StackPanel> | |||||
</StackPanel> | |||||
</Grid> | |||||
</Grid> | |||||
</DataTemplate> | |||||
</ItemsControl.ItemTemplate> | |||||
</ItemsControl> | |||||
</ScrollViewer> | |||||
</Grid> | </Grid> | ||||
</UserControl> | </UserControl> |
@@ -185,7 +185,6 @@ | |||||
Foreground="#ff00ccff" | Foreground="#ff00ccff" | ||||
Style="{StaticResource TextBlockStyle}" | Style="{StaticResource TextBlockStyle}" | ||||
Text="{Binding RecipeName}" /> | Text="{Binding RecipeName}" /> | ||||
<!--<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="1,0,1,0" />--> | |||||
</Grid> | </Grid> | ||||
@@ -195,24 +194,22 @@ | |||||
Style="{StaticResource TextBlockStyle}" | Style="{StaticResource TextBlockStyle}" | ||||
Text="{Binding RecipCode}" /> | Text="{Binding RecipCode}" /> | ||||
<Grid Grid.Column="3"> | |||||
<!--<Grid Grid.Column="3"> | |||||
<Button | <Button | ||||
Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | ||||
CommandParameter="{Binding RecipCode}" | CommandParameter="{Binding RecipCode}" | ||||
Content="编辑" | Content="编辑" | ||||
Style="{StaticResource buttonStyle}" /> | Style="{StaticResource buttonStyle}" /> | ||||
<!--<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="1,0,1,0" />--> | |||||
</Grid> | |||||
</Grid>--> | |||||
<Grid Grid.Column="5"> | <Grid Grid.Column="5"> | ||||
<Button | <Button | ||||
Command="{Binding DataContext.LookCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | |||||
Command="{Binding DataContext.DetailsCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | |||||
CommandParameter="{Binding RecipCode}" | CommandParameter="{Binding RecipCode}" | ||||
Content="查看" | |||||
Content="详情" | |||||
Style="{StaticResource buttonStyle}" /> | Style="{StaticResource buttonStyle}" /> | ||||
<!--<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="0,0,1,0" />--> | |||||
</Grid> | </Grid> | ||||
<Grid Grid.Column="6"> | <Grid Grid.Column="6"> | ||||
@@ -221,14 +218,8 @@ | |||||
CommandParameter="{Binding RecipCode}" | CommandParameter="{Binding RecipCode}" | ||||
Content="删除" | Content="删除" | ||||
Style="{StaticResource buttonStyle}" /> | Style="{StaticResource buttonStyle}" /> | ||||
<!--<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="0,0,1,0" />--> | |||||
</Grid> | </Grid> | ||||
<!--<Border | |||||
Grid.ColumnSpan="8" | |||||
BorderBrush="{StaticResource BorderSolid}" | |||||
BorderThickness="1,1,1,1" />--> | |||||
</Grid> | </Grid> | ||||
<ControlTemplate.Triggers> | <ControlTemplate.Triggers> | ||||
@@ -16,10 +16,7 @@ namespace DosingSystem.ViewModel | |||||
{ | { | ||||
public DeviceListViewModel() | public DeviceListViewModel() | ||||
{ | { | ||||
for (int i = 0; i < 10; i++) | |||||
{ | |||||
devices.Add(new Devices() { IpAddress = $"192.168.1.{i + 10}", DeviceName = $"Device_{i}" }); | |||||
} | |||||
} | } | ||||
public static ObservableCollection<Devices> devices { get; set; } = new ObservableCollection<Devices>(); | public static ObservableCollection<Devices> devices { get; set; } = new ObservableCollection<Devices>(); | ||||
@@ -55,7 +55,7 @@ namespace DosingSystem.ViewModel | |||||
MenuInit(); | MenuInit(); | ||||
permission = Permission.管理员; | permission = Permission.管理员; | ||||
if (Menus.Count > 0) DoNavChanged(Menus.ElementAt(0).CommandParameter); | if (Menus.Count > 0) DoNavChanged(Menus.ElementAt(0).CommandParameter); | ||||
DeviceInquire.GetInstance.Init(); | |||||
} | } | ||||
@@ -15,11 +15,18 @@ namespace DosingSystem.ViewModel | |||||
{ | { | ||||
public NewRecipeViewModel() | public NewRecipeViewModel() | ||||
{ | { | ||||
RawMaterialNames.Clear(); | |||||
for (int i = 0; i < 10; i++) | |||||
ActionManage.GetInstance.Register(new Action<object>((o) => | |||||
{ | { | ||||
RawMaterialNames.Add($"原料{i}"); | |||||
} | |||||
if (o != null && o is RecipeModel rm) | |||||
{ | |||||
RecipeName = rm.RecipeName; | |||||
foreach (var item in rm.RawMaterials) | |||||
{ | |||||
RawMaterials.Add(item); | |||||
} | |||||
RecipCode = rm.RecipCode; | |||||
} | |||||
}), "Details"); | |||||
AddCommand = new RelayCommand(() => | AddCommand = new RelayCommand(() => | ||||
{ | { | ||||
@@ -27,7 +34,7 @@ namespace DosingSystem.ViewModel | |||||
string guid = Guid.NewGuid().ToString(); | string guid = Guid.NewGuid().ToString(); | ||||
if (RawMaterials.FirstOrDefault(p => p.RawMaterialId == guid) == null) | if (RawMaterials.FirstOrDefault(p => p.RawMaterialId == guid) == null) | ||||
{ | { | ||||
RawMaterials.Add(new RawMaterial() | |||||
RawMaterials.Add(new RawMaterialModel() | |||||
{ | { | ||||
RawMaterialId = guid | RawMaterialId = guid | ||||
}); | }); | ||||
@@ -46,66 +53,72 @@ namespace DosingSystem.ViewModel | |||||
SaveCommand = new RelayCommand(() => | SaveCommand = new RelayCommand(() => | ||||
{ | { | ||||
var res = Array.FindIndex(Json<LocaPar>.Data.Recipes.ToArray(), p => p.RecipeName == RecipeName); | |||||
if (res >= 0 && res < Json<LocaPar>.Data.Recipes.Count) | |||||
if (RecipCode.Length <= 0) | |||||
{ | { | ||||
Json<LocaPar>.Data.Recipes.ElementAt(res).RecipeName = RecipeName; | |||||
Json<LocaPar>.Data.Recipes.ElementAt(res).RawMaterials = RawMaterials; | |||||
var res = Array.FindIndex(Json<LocaPar>.Data.Recipes.ToArray(), p => p.RecipeName == RecipeName); | |||||
if (res >= 0 && res < Json<LocaPar>.Data.Recipes.Count) | |||||
{ | |||||
ErrorInfo = "该配方已存在,请重新输入"; | |||||
} | |||||
else | |||||
{ | |||||
AddRecipes(); | |||||
} | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
string date = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); | |||||
var dates = date.Split("-").ToList(); | |||||
StringBuilder sb = new StringBuilder(); | |||||
dates?.ForEach((item) => { sb.Append(item); }); | |||||
Json<LocaPar>.Data.Recipes.Add(new RecipeModel() | |||||
var res = Array.FindIndex(Json<LocaPar>.Data.Recipes.ToArray(), p => p.RecipCode == RecipCode); | |||||
if (res >= 0 && res < Json<LocaPar>.Data.Recipes.Count) | |||||
{ | { | ||||
SerialNum = Json<LocaPar>.Data.Recipes.Count + 1, | |||||
RawMaterials = RawMaterials, | |||||
RecipCode = sb.ToString(), | |||||
RecipeName = RecipeName | |||||
}); | |||||
Json<LocaPar>.Data.Recipes.ElementAt(res).RecipeName = RecipeName; | |||||
foreach (var item in RawMaterials) | |||||
{ | |||||
Json<LocaPar>.Data.Recipes.ElementAt(res).RawMaterials.Add(item); | |||||
} | |||||
} | |||||
} | } | ||||
ActionManage.GetInstance.Send("CloseNewRecipeView"); | ActionManage.GetInstance.Send("CloseNewRecipeView"); | ||||
}); | }); | ||||
} | } | ||||
private void AddRecipes() | |||||
{ | |||||
string date = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); | |||||
var dates = date.Split("-").ToList(); | |||||
StringBuilder sb = new StringBuilder(); | |||||
dates?.ForEach((item) => { sb.Append(item); }); | |||||
Json<LocaPar>.Data.Recipes.Add(new RecipeModel() | |||||
{ | |||||
SerialNum = Json<LocaPar>.Data.Recipes.Count + 1, | |||||
RawMaterials = RawMaterials, | |||||
RecipCode = sb.ToString(), | |||||
RecipeName = RecipeName | |||||
}); | |||||
} | |||||
static NewRecipeViewModel() | |||||
{ | |||||
RawMaterialNames.Clear(); | |||||
} | |||||
private string RecipCode = string.Empty; | |||||
public string RecipeName { get { return _mRecipeName; } set { _mRecipeName = value; OnPropertyChanged(); } } | public string RecipeName { get { return _mRecipeName; } set { _mRecipeName = value; OnPropertyChanged(); } } | ||||
private string _mRecipeName; | private string _mRecipeName; | ||||
public string ErrorInfo { get { return _mErrorInfo; } set { _mErrorInfo = value; OnPropertyChanged(); } } | public string ErrorInfo { get { return _mErrorInfo; } set { _mErrorInfo = value; OnPropertyChanged(); } } | ||||
private string _mErrorInfo; | private string _mErrorInfo; | ||||
public RelayCommand AddCommand { get; set; } | public RelayCommand AddCommand { get; set; } | ||||
public RelayCommand<object> RemoveCommand { get; set; } | public RelayCommand<object> RemoveCommand { get; set; } | ||||
public RelayCommand SaveCommand { get; set; } | public RelayCommand SaveCommand { get; set; } | ||||
public ObservableCollection<RawMaterial> RawMaterials { get; set; } = new ObservableCollection<RawMaterial>(); | |||||
public ObservableCollection<string> RawMaterialNames { get; set; } = new ObservableCollection<string>(); | |||||
} | |||||
public class RawMaterial : ObservableObject | |||||
{ | |||||
/// <summary> | |||||
/// 原料名称 | |||||
/// </summary> | |||||
public string RawMaterialName { get { return _mRawMaterialName; } set { _mRawMaterialName = value; OnPropertyChanged(); } } | |||||
private string _mRawMaterialName; | |||||
/// <summary> | |||||
/// 原料重量 | |||||
/// </summary> | |||||
public float RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value; OnPropertyChanged(); } } | |||||
private float _mRawMaterialWeight; | |||||
/// <summary> | |||||
/// 原料ID | |||||
/// </summary> | |||||
public string RawMaterialId { get { return _mRawMaterialId; } set { _mRawMaterialId = value; OnPropertyChanged(); } } | |||||
private string _mRawMaterialId; | |||||
public ObservableCollection<RawMaterialModel> RawMaterials { get; set; } = new ObservableCollection<RawMaterialModel>(); | |||||
public static ObservableCollection<string> RawMaterialNames { get; set; } = new ObservableCollection<string>(); | |||||
} | } | ||||
} | } |
@@ -9,10 +9,35 @@ using System.Collections.ObjectModel; | |||||
using System.Windows; | using System.Windows; | ||||
using BPASmartClient.Helper; | using BPASmartClient.Helper; | ||||
using Microsoft.Toolkit.Mvvm.Input; | using Microsoft.Toolkit.Mvvm.Input; | ||||
using DosingSystem.Model; | |||||
namespace DosingSystem.ViewModel | namespace DosingSystem.ViewModel | ||||
{ | { | ||||
public class RecipeControlViewModel : ObservableObject | public class RecipeControlViewModel : ObservableObject | ||||
{ | { | ||||
public RecipeControlViewModel() | |||||
{ | |||||
Recipes = Json<LocaPar>.Data.Recipes; | |||||
StartCommand = new RelayCommand<object>((o) => | |||||
{ | |||||
if (o != null && o is string deviceName) | |||||
{ | |||||
Task.Run(new Action(() => | |||||
{ | |||||
int index = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == deviceName); | |||||
if (index >= 0 && index < Recipes.Count) | |||||
{ | |||||
Recipes.ElementAt(index).IsEnable = false; | |||||
foreach (var item in Recipes.ElementAt(index).RawMaterials) | |||||
{ | |||||
DeviceInquire.GetInstance.GetDevice(item.RawMaterialName)?.Start(item.RawMaterialWeight);//启动写入 | |||||
} | |||||
} | |||||
})); | |||||
} | |||||
}); | |||||
} | |||||
public RelayCommand<object> StartCommand { get; set; } | |||||
public ObservableCollection<RecipeModel> Recipes { get; set; } | |||||
} | } | ||||
} | } |
@@ -26,14 +26,38 @@ namespace DosingSystem.ViewModel | |||||
nrv.ShowDialog(); | nrv.ShowDialog(); | ||||
}); | }); | ||||
SaveRecipe = new Action(() => { Json<LocaPar>.Save(); }); | SaveRecipe = new Action(() => { Json<LocaPar>.Save(); }); | ||||
RemoveCommand = new RelayCommand<object>((o) => | |||||
{ | |||||
if (o is string str) | |||||
{ | |||||
var res = Json<LocaPar>.Data.Recipes.FirstOrDefault(p => p.RecipCode == str); | |||||
if (res != null) Json<LocaPar>.Data.Recipes.Remove(res); | |||||
} | |||||
}); | |||||
DetailsCommand = new RelayCommand<object>((o) => | |||||
{ | |||||
if (o != null && o is string str) | |||||
{ | |||||
ActionManage.GetInstance.CancelRegister("Details"); | |||||
NewRecipeView nrv = new NewRecipeView(); | |||||
ActionManage.GetInstance.Send("Details", Json<LocaPar>.Data.Recipes.FirstOrDefault(p => p.RecipCode == str)); | |||||
nrv.ShowDialog(); | |||||
} | |||||
}); | |||||
} | } | ||||
public Action NewRecipe { get; set; } | public Action NewRecipe { get; set; } | ||||
public Action SaveRecipe { get; set; } | public Action SaveRecipe { get; set; } | ||||
public RelayCommand<object> EditCommand { get; set; } | public RelayCommand<object> EditCommand { get; set; } | ||||
public RelayCommand<object> LookCommand { get; set; } | |||||
public RelayCommand<object> DetailsCommand { get; set; } | |||||
public RelayCommand<object> RemoveCommand { get; set; } | public RelayCommand<object> RemoveCommand { get; set; } | ||||
public ObservableCollection<RecipeModel> Recipes { get; set; } | public ObservableCollection<RecipeModel> Recipes { get; set; } | ||||
} | } | ||||
} | } |