Wp.Utils.S7.Min 0.0.1-alpha

This is a prerelease version of Wp.Utils.S7.Min.
dotnet add package Wp.Utils.S7.Min --version 0.0.1-alpha                
NuGet\Install-Package Wp.Utils.S7.Min -Version 0.0.1-alpha                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Wp.Utils.S7.Min" Version="0.0.1-alpha" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Wp.Utils.S7.Min --version 0.0.1-alpha                
#r "nuget: Wp.Utils.S7.Min, 0.0.1-alpha"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Wp.Utils.S7.Min as a Cake Addin
#addin nuget:?package=Wp.Utils.S7.Min&version=0.0.1-alpha&prerelease

// Install Wp.Utils.S7.Min as a Cake Tool
#tool nuget:?package=Wp.Utils.S7.Min&version=0.0.1-alpha&prerelease                

S7协议包使用简介

1.测试项目为wpf项目,依赖项为

 <ItemGroup>
   <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
   <PackageReference Include="HandyControl" Version="3.5.1" />
   <PackageReference Include="MaterialDesignThemes" Version="5.1.0" />
   <PackageReference Include="System.IO.Ports" Version="6.0.0" />
   <PackageReference Include="Wp.Utils.Min" Version="0.0.1-alpha" />
 </ItemGroup>

2.测试代码

2.0 Converters

using System.Globalization;
using System.Windows.Data;
using Wp.Utils.Min.Utils;

namespace Wp.Utils.Test.UI.Converters
{
	/// <summary>
	/// 枚举描述转换器
	/// </summary>
	public class EnumDescriptionConverter : IValueConverter
	{
		public static readonly IValueConverter Instance = new EnumDescriptionConverter();

		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			return value is null ? null : EnumUtil.GetEnumDescription((Enum)value);
		}

		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			return Binding.DoNothing;
		}
	}
}

2.1 ViewModels

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.Sockets;
using System.Windows;
using Wp.Utils.Min.Enums;
using Wp.Utils.Min.Utils;
using Wp.Utils.S7.Domain;
using Wp.Utils.S7.Domain.Comm;
using Wp.Utils.S7.Domain.Comm.Data.DataItems;
using Wp.Utils.S7.Domain.Comm.Parameter;
using Wp.Utils.S7.Domain.Data;
using Wp.Utils.S7.Enums;
using CCP = Wp.Utils.S7.Domain.COTP.CotpConnectionPacket;
using CCPO = Wp.Utils.S7.Domain.COTP.CotpConnectionPacketOpt;
using CFP = Wp.Utils.S7.Domain.COTP.CotpFuctionPacket;
using CFPO = Wp.Utils.S7.Domain.COTP.CotpFunctionPacketOpt;
using S7CAH = Wp.Utils.S7.Domain.Comm.Header.S7CommAckHeader;
using S7CJH = Wp.Utils.S7.Domain.Comm.Header.S7CommJobHeader;
using S7ROWDResP = Wp.Utils.S7.Domain.Comm.Parameter.S7ReadOrWriteDataResponseParameter;
using S7ROWDRP = Wp.Utils.S7.Domain.Comm.Parameter.S7ReadOrWriteDataRequestParameter;
using S7RPI = Wp.Utils.S7.Domain.Comm.Parameter.S7ReadOrWriteDataRequestParameterItem;
using S7SCP = Wp.Utils.S7.Domain.Comm.Parameter.S7SetupCommunicationParameter;

using Tsap = Wp.Utils.S7.Domain.COTP.TransportServiceAccessPoint;
using WDRDI = Wp.Utils.S7.Domain.Comm.Data.DataItems.WriteDataRequestDataItem;


namespace Wp.Utils.Test.UI.ViewModels.Pages
{
	public partial class TestS7PageVM : ObservableObject
	{
		#region Events

		#endregion Events

		#region Properties&Fileds

		private Socket _socket;

		[ObservableProperty]
		private string _ip = "127.0.0.1";

		[ObservableProperty]
		private int _port = 102;

		[ObservableProperty]
		private Tsap _source;

		[ObservableProperty]
		private Tsap _destination;

		[ObservableProperty]
		private byte _tpduSize;

		[ObservableProperty]
		private S7SCP _s7SetupCommunicationParameter = new(1, 1, 480);

		[ObservableProperty]
		private string _request;

		[ObservableProperty]
		private string _response;

		[ObservableProperty]
		private string _message = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 没有操作";

		[ObservableProperty]
		private S7RPI _readDataRequestParameterItem = new(ES7SyntaxId.S7ANY, ES7ParameterItemTransportSize.Byte, 1, 1, ES7Area.DataBlocks_DB, new S7Address(0, 0));

		[ObservableProperty]
		private S7RPI _writeDataRequestParameterItem = new(ES7SyntaxId.S7ANY, ES7ParameterItemTransportSize.Byte, 1, 1, ES7Area.DataBlocks_DB, new S7Address(0, 0));

		[ObservableProperty]
		private string _values = string.Empty;

		public ObservableCollection<ES7Area> Area => EnumUtil.GetEnumItems<ES7Area>();

		public ObservableCollection<ES7ParameterItemTransportSize> ParameterItemTransportSize => EnumUtil.GetEnumItems<ES7ParameterItemTransportSize>();

		#region Comnands

		[RelayCommand]
		private void SetupTcpConnection()
		{
			IPEndPoint ie = new(IPAddress.Parse(Ip), Port);
			_socket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
			if (_socket.Connected)
			{
				Message = "Tcp连接已建立";
			}
			else
			{
				_socket.Connect(ie);
				Message = "Tcp连接已建立";
			}
		}

		[RelayCommand]
		private void ShutDownTcpConnection()
		{
			_socket?.Close();
			Message = "Tcp连接已关闭";
		}

		[RelayCommand]
		private void SetupCotpConnection()
		{
			#region COTP

			var opt = new CCPO(false, false);
			var cotp = new CCP(ES7ConnectionPacketPduType.ConnectRequest, 0x00, 0x01, opt, Source, Destination, 0x0A);

			#endregion COTP

			#region TPKT

			ushort length = Convert.ToUInt16(4 + cotp.GetValues().Count);
			var tpkt = new TPKT(length);

			#endregion TPKT

			var request = new S7Protocol<CCP, CCPO>(tpkt, cotp).GetValues();
			Request = request.ToFormatString(EScale.HexToUp);

			Response = Communicate(request).ToFormatString(EScale.HexToUp);
			Message = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} COTP连接已建立";
		}

		[RelayCommand]
		private void SetupS7Connection()
		{
			#region S7Comm

			var header = new S7CJH(ES7CommHeaderPduType.JOB, 15874, (ushort)S7SetupCommunicationParameter.GetValues().Count, 0);
			var s7comm = new S7Comm<S7CJH, S7SCP>(header, S7SetupCommunicationParameter);

			#endregion S7Comm

			#region COTP

			var opt = new CFPO(0, true);
			var cotp = new CFP(ES7ConnectionPacketPduType.Data, opt);

			#endregion COTP

			#region TPKT

			ushort length = Convert.ToUInt16(4 + cotp.GetValues().Count + s7comm.GetValues().Count);
			var tpkt = new TPKT(length);

			#endregion TPKT

			var request = new S7Protocol<CFP, S7CJH, S7SCP, CFPO>(tpkt, cotp, s7comm).GetValues();
			Request = request.ToFormatString(EScale.HexToUp);

			Response = Communicate(request).ToFormatString(EScale.HexToUp);
			Message = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} S7连接已建立";
		}

		[RelayCommand]
		private void ReadData()
		{
			#region S7Comm

			var parameter = new S7ROWDRP(ES7CommFunctionCode.ReadVar, new List<S7RPI>() { ReadDataRequestParameterItem });
			var header = new S7CJH(ES7CommHeaderPduType.JOB, 6400, (ushort)parameter.GetValues().Count, 0);
			var s7comm = new S7Comm<S7CJH, S7ROWDRP>(header, parameter);

			#endregion S7Comm

			#region COTP

			var cotp = new CFP(ES7ConnectionPacketPduType.Data, new CFPO(0, true));

			#endregion COTP

			#region TPKT

			var tpkt = new TPKT((ushort)(4 + cotp.GetValues().Count + s7comm.GetValues().Count));

			#endregion TPKT

			var request = new S7Protocol<CFP, S7CJH, S7ROWDRP, CFPO>(tpkt, cotp, s7comm).GetValues();
			Request = request.ToFormatString(EScale.HexToUp);
			var response = new S7Protocol<CFP, S7CAH, S7ROWDResP, S7CommData<ReadDataResponseDataItem>, CFPO, ReadDataResponseDataItem>(Communicate(request));
			Response = response.GetValues().ToFormatString(EScale.HexToUp);
			Message = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 读取数据成功";
		}

		[RelayCommand]
		private void WriteData()
		{
			#region S7Comm

			var dataItems = new List<WDRDI>();
			var values = Values.Split(',', StringSplitOptions.RemoveEmptyEntries);

			for (int i = 0; i < values.Length; i++)
			{
				switch (WriteDataRequestParameterItem.TransportSize)
				{
					case ES7ParameterItemTransportSize.BIT:
						break;

					case ES7ParameterItemTransportSize.Byte:
						dataItems.Add(new WDRDI(ES7TransportSize.BYTE_WORD_DWORD, 8, new byte[] { Convert.ToByte(values[i]) }));
						break;

					case ES7ParameterItemTransportSize.CHAR:
						break;

					case ES7ParameterItemTransportSize.WORD:
						dataItems.Add(new WDRDI(ES7TransportSize.BYTE_WORD_DWORD, 2 * 8, BitConverter.GetBytes(Convert.ToUInt16(values[i]))));
						break;

					case ES7ParameterItemTransportSize.INT:
						dataItems.Add(new WDRDI(ES7TransportSize.INTEGER, 2 * 8, BitConverter.GetBytes(Convert.ToInt16(values[i]))));
						break;

					case ES7ParameterItemTransportSize.DWORD:
						dataItems.Add(new WDRDI(ES7TransportSize.BYTE_WORD_DWORD, 4 * 8, BitConverter.GetBytes(Convert.ToUInt32(values[i]))));
						break;

					case ES7ParameterItemTransportSize.DINT:
						dataItems.Add(new WDRDI(ES7TransportSize.DINTEGER, 4 * 8, BitConverter.GetBytes(Convert.ToInt32(values[i]))));
						break;

					case ES7ParameterItemTransportSize.REAL:
						dataItems.Add(new WDRDI(ES7TransportSize.REAL, 4, BitConverter.GetBytes(Convert.ToSingle(values[i]))));
						break;

					case ES7ParameterItemTransportSize.DATE:
						break;

					case ES7ParameterItemTransportSize.TOD:
						break;

					case ES7ParameterItemTransportSize.TIME:
						break;

					case ES7ParameterItemTransportSize.S5TIME:
						break;

					case ES7ParameterItemTransportSize.DATE_AND_TIME:
						break;

					case ES7ParameterItemTransportSize.COUNTER:
						break;

					case ES7ParameterItemTransportSize.TIMER:
						break;

					case ES7ParameterItemTransportSize.IEC_TIMER:
						break;

					case ES7ParameterItemTransportSize.IEC_COUNTER:
						break;

					case ES7ParameterItemTransportSize.HS_COUNTER:
						break;

					default:
						break;
				}
			}

			var data = new S7CommData<WDRDI>(dataItems);
			var parameter = new S7ROWDRP(ES7CommFunctionCode.WriteVar, new List<S7RPI>() { WriteDataRequestParameterItem });
			var header = new S7CJH(ES7CommHeaderPduType.JOB, 6144, (ushort)parameter.GetValues().Count, (ushort)data.GetValues().Count);
			var s7comm = new S7Comm<S7CJH, S7ROWDRP, S7CommData<WDRDI>, WDRDI>(header, parameter, data);

			#endregion S7Comm

			#region COTP

			var cotp = new CFP(ES7ConnectionPacketPduType.Data, new CFPO(0, true));

			#endregion COTP

			#region KPTK

			var tpkt = new TPKT((ushort)(4 + cotp.GetValues().Count + s7comm.GetValues().Count));

			#endregion KPTK

			var request = new S7Protocol<CFP, S7CJH, S7ROWDRP, S7CommData<WDRDI>, CFPO, WDRDI>(tpkt, cotp, s7comm).GetValues();
			Request = request.ToFormatString(EScale.HexToUp);
			var response = new S7Protocol<CFP, S7CAH, S7ROWDResP, S7CommData<WriteDataResponseDataItem>, CFPO, WriteDataResponseDataItem>(Communicate(request));
			Response = response.GetValues().ToFormatString(EScale.HexToUp);
			Message = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 写数据返回:{string.Join(' ', response.S7Comm.Data.Items.Select(x => EnumUtil.GetEnumDescription(x.ReturnCode)))}";
		}

		[RelayCommand]
		private void CopyRequest()
		{
			Clipboard.SetText(Request);
		}

		[RelayCommand]
		private void CopyResponse()
		{
			Clipboard.SetText(Response);
		}

		#endregion Comnands

		#endregion Properties&Fileds

		#region Methods

		public TestS7PageVM()
		{
			Source = new Tsap(ES7TsapType.Both, 3, 0);
			Destination = new Tsap(ES7TsapType.PG, 3, 0);
		}

		private IEnumerable<byte> Communicate(IEnumerable<byte> data)
		{
			var buffer = new byte[1024];
			_socket.Send(data.ToArray());
			Thread.Sleep(500);
			var count = _socket.Receive(buffer);
			var response = new byte[count];
			Buffer.BlockCopy(buffer, 0, response, 0, response.Length);
			return response;
		}

		#endregion Methods
	}
}

2.2 Views

<Page
    x:Class="Wp.Utils.Test.UI.Views.Pages.TestS7Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:comverters="clr-namespace:Wp.Utils.Test.UI.Converters"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:hc="https://handyorg.github.io/handycontrol"
    xmlns:local="clr-namespace:Wp.Utils.Test.UI.Views.Pages"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:Wp.Utils.Test.UI.ViewModels.Pages"
    Title="TestS7Page"
    d:DesignHeight="966"
    d:DesignWidth="1641"
    Background="White"
    mc:Ignorable="d">
    <Page.DataContext>
        <vm:TestS7PageVM />
    </Page.DataContext>
    
    
    <Page.Resources>
        <Style
            BasedOn="{StaticResource TextBoxExtend}"
            TargetType="hc:TextBox">
            <Setter Property="Margin" Value="10" />
        </Style>
        <Style
            BasedOn="{StaticResource ComboBoxExtend}"
            TargetType="hc:ComboBox">
            <Setter Property="Margin" Value="10" />
        </Style>
        <Style
            BasedOn="{StaticResource ButtonPrimary}"
            TargetType="Button">
            <Setter Property="HorizontalAlignment" Value="Right" />
            <Setter Property="Margin" Value="0,0,10,0" />
        </Style>
    </Page.Resources>
    <ScrollViewer>
        <DockPanel>
            <StackPanel
                DockPanel.Dock="Top"
                Orientation="Vertical">
                <TextBlock
                    HorizontalAlignment="Left"
                    Text="1.建立Tcp连接" />
                <materialDesign:Card>
                    <StackPanel Orientation="Vertical">
                        <UniformGrid Columns="2">
                            <hc:TextBox
                                hc:InfoElement.Title="IP地址"
                                Text="{Binding Ip}" />
                            <hc:TextBox
                                hc:InfoElement.Title="端口号"
                                Text="{Binding Port}" />
                        </UniformGrid>
                        <StackPanel
                            HorizontalAlignment="Right"
                            Orientation="Horizontal">
                            <Button
                                Command="{Binding SetupTcpConnectionCommand}"
                                Content="建立Tcp连接" />
                            <Button
                                Command="{Binding ShutDownTcpConnectionCommand}"
                                Content="断开Tcp连接" />
                        </StackPanel>
                    </StackPanel>
                </materialDesign:Card>
            </StackPanel>
            <StackPanel
                DockPanel.Dock="Top"
                Orientation="Vertical">
                <TextBlock
                    HorizontalAlignment="Left"
                    Text="2.建立COTP连接(实际测试中不需要这一步)" />
                <materialDesign:Card>
                    <StackPanel>
                        <UniformGrid Columns="5">
                            <hc:TextBox
                                hc:InfoElement.Title="主站机架号"
                                Text="{Binding Source.Rack}" />
                            <hc:TextBox
                                hc:InfoElement.Title="主站插槽号"
                                Text="{Binding Source.Slot}" />
                            <hc:TextBox
                                hc:InfoElement.Title="从站机架号"
                                Text="{Binding Destination.Rack}" />
                            <hc:TextBox
                                hc:InfoElement.Title="从站插槽号"
                                Text="{Binding Destination.Slot}" />
                            <hc:TextBox
                                hc:InfoElement.Title="TPDU Size"
                                Text="{Binding TpduSize}" />
                        </UniformGrid>
                        <Button
                            Command="{Binding SetupCotpConnectionCommand}"
                            Content="建立COTP连接" />
                    </StackPanel>
                </materialDesign:Card>
            </StackPanel>
            <StackPanel
                DockPanel.Dock="Top"
                Orientation="Vertical">
                <TextBlock
                    HorizontalAlignment="Left"
                    Text="3.建立S7连接" />
                <materialDesign:Card>
                    <StackPanel Orientation="Vertical">
                        <UniformGrid Columns="3">
                            <hc:TextBox
                                hc:InfoElement.Title="IPMaxAmQCalled"
                                Text="{Binding S7SetupCommunicationParameter.MaxAmQCalled}" />
                            <hc:TextBox
                                hc:InfoElement.Title="MaxAmQCalling"
                                Text="{Binding S7SetupCommunicationParameter.MaxAmQCalling}" />
                            <hc:TextBox
                                hc:InfoElement.Title="PduLength"
                                Text="{Binding S7SetupCommunicationParameter.PduLength}" />
                        </UniformGrid>
                        <Button
                            Command="{Binding SetupS7ConnectionCommand}"
                            Content="建立S7连接" />
                    </StackPanel>
                </materialDesign:Card>
            </StackPanel>
            <StackPanel
                DockPanel.Dock="Top"
                Orientation="Vertical">
                <TextBlock
                    HorizontalAlignment="Left"
                    Text="写数据" />
                <materialDesign:Card>
                    <StackPanel Orientation="Vertical">
                        <UniformGrid Columns="6">
                            <hc:ComboBox
                                hc:InfoElement.Title="Area"
                                ItemsSource="{Binding Area}"
                                SelectedItem="{Binding WriteDataRequestParameterItem.Area}">
                                <hc:ComboBox.ItemTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Converter={x:Static comverters:EnumDescriptionConverter.Instance}}" />
                                    </DataTemplate>
                                </hc:ComboBox.ItemTemplate>
                            </hc:ComboBox>
                            <hc:ComboBox
                                hc:InfoElement.Title="ParameterItemTransportSize"
                                ItemsSource="{Binding ParameterItemTransportSize}"
                                SelectedItem="{Binding WriteDataRequestParameterItem.TransportSize}" />
                            <hc:TextBox
                                hc:InfoElement.Title="DB Number"
                                Text="{Binding WriteDataRequestParameterItem.DbNumber}" />
                            <hc:TextBox
                                hc:InfoElement.Title="Byte Address"
                                Text="{Binding WriteDataRequestParameterItem.Address.ByteAddress}" />
                            <hc:TextBox
                                hc:InfoElement.Title="Bit Address"
                                Text="{Binding WriteDataRequestParameterItem.Address.BitAddress}" />
                            <hc:TextBox
                                hc:InfoElement.Title="要写入的值,以英文逗号为间隔"
                                Text="{Binding Values}" />
                            
                        </UniformGrid>
                        <Button
                            Command="{Binding WriteDataCommand}"
                            Content="写数据" />
                    </StackPanel>
                </materialDesign:Card>
            </StackPanel>
            <StackPanel
                DockPanel.Dock="Top"
                Orientation="Vertical">
                <TextBlock
                    HorizontalAlignment="Left"
                    Text="读数据" />
                <materialDesign:Card>
                    <StackPanel Orientation="Vertical">
                        <UniformGrid Columns="6">
                            <hc:ComboBox
                                hc:InfoElement.Title="Area"
                                ItemsSource="{Binding Area}"
                                SelectedItem="{Binding ReadDataRequestParameterItem.Area}">
                                <hc:ComboBox.ItemTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Converter={x:Static comverters:EnumDescriptionConverter.Instance}}" />
                                    </DataTemplate>
                                </hc:ComboBox.ItemTemplate>
                            </hc:ComboBox>
                            <hc:ComboBox
                                hc:InfoElement.Title="ParameterItemTransportSize"
                                ItemsSource="{Binding ParameterItemTransportSize}"
                                SelectedItem="{Binding ReadDataRequestParameterItem.TransportSize}">
                                
                            </hc:ComboBox>
                            <hc:TextBox
                                hc:InfoElement.Title="DB Number"
                                Text="{Binding ReadDataRequestParameterItem.DbNumber}" />
                            <hc:TextBox
                                hc:InfoElement.Title="Byte Address"
                                Text="{Binding ReadDataRequestParameterItem.Address.ByteAddress}" />
                            <hc:TextBox
                                hc:InfoElement.Title="Bit Address"
                                Text="{Binding ReadDataRequestParameterItem.Address.BitAddress}" />
                            <hc:TextBox
                                hc:InfoElement.Title="Count"
                                Text="{Binding ReadDataRequestParameterItem.Length}" />
                        </UniformGrid>
                        <Button
                            Command="{Binding ReadDataCommand}"
                            Content="读数据" />
                    </StackPanel>
                </materialDesign:Card>
            </StackPanel>
            <TextBlock
                HorizontalAlignment="Left"
                VerticalAlignment="Bottom"
                DockPanel.Dock="Bottom"
                Text="{Binding Message}" />
            <UniformGrid
                VerticalAlignment="Stretch"
                Columns="2">
                <DockPanel
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch">
                    <TextBlock
                        HorizontalAlignment="Left"
                        DockPanel.Dock="Top"
                        Text="请求报文" />
                    <materialDesign:Card>
                        <DockPanel>
                            <Button
                                Command="{Binding CopyRequestCommand}"
                                Content="复制"
                                DockPanel.Dock="Bottom" />
                            <Border
                                Margin="6"
                                Padding="6"
                                BorderBrush="DimGray"
                                BorderThickness="1"
                                CornerRadius="3">
                                <TextBlock
                                    Text="{Binding Request}"
                                    TextWrapping="Wrap" />
                            </Border>
                        </DockPanel>
                    </materialDesign:Card>
                </DockPanel>
                <DockPanel
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch">
                    <TextBlock
                        HorizontalAlignment="Left"
                        DockPanel.Dock="Top"
                        Text="响应报文" />
                    <materialDesign:Card>
                        <DockPanel>
                            <Button
                                Command="{Binding CopyResponseCommand}"
                                Content="复制"
                                DockPanel.Dock="Bottom" />
                            <Border
                                Margin="6"
                                Padding="6"
                                BorderBrush="DimGray"
                                BorderThickness="1"
                                CornerRadius="3">
                                <TextBlock
                                    Text="{Binding Response}"
                                    TextWrapping="Wrap" />
                            </Border>
                        </DockPanel>
                    </materialDesign:Card>
                </DockPanel>
            </UniformGrid>
        </DockPanel>
    </ScrollViewer>
</Page>

2.2 App.xaml

<Application
    x:Class="Wp.Utils.Test.UI.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Wp.Utils.Test.UI"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
    StartupUri="Views/Windows/MainWindow.xaml">
    <Application.Resources>
        
        <ResourceDictionary>
            <Style TargetType="TextBlock">
                <Setter Property="HorizontalAlignment" Value="Center" />
                <Setter Property="VerticalAlignment" Value="Center" />
            </Style>
            <Style TargetType="materialDesign:Card">
                <Setter Property="materialDesign:ElevationAssist.Elevation" Value="Dp2" />
                <Setter Property="Margin" Value="6" />
                <Setter Property="Padding" Value="6" />
            </Style>
            <ResourceDictionary.MergedDictionaries>
                <materialDesign:BundledTheme
                    BaseTheme="Light"
                    PrimaryColor="DeepPurple"
                    SecondaryColor="Lime" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign2.Defaults.xaml" />
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.0.1-alpha 53 9/9/2024