Aufbau des Interface IWmsActivitySettingList
Eigenschaft / Methode | Beschreibung |
---|---|
Identifier | Immer gleicher, eindeutiger Identifier dieser Einstellung! |
Title | Titel der Einstellung, wird als Name des Menüs verwendet. |
TitleToolTip | Tooltip für das Menü bzw. die Schaltfläche. |
DialogContent | UserControl zur Bearbeitung der Einstellung im Dialog. |
IsValidDialogData() | Prüft, ob die Eingaben im Dialog valide sind. Nur dann wird der Dialog geschlossen. |
AddErrorToDialog(string error) | Zeigt eine Fehlermeldung im Dialog an. |
InitialiseDialogData(WmsSettingEntry entry) | Erzeugt die Oberfläche zur Bearbeitung eines Eintrages. |
GetDialogData() | Ermittelt die Eingaben aus dem Dialog um sie zu speichern. |
Beispiel
Im Folgenden entwickeln wir eine Aktivität, um Dateien auf einen FTP Server hochzuladen. Der WMS-Benutzer kann beliebig viele FTP-Einstellungen konfigurieren und über die Zuordnungen die
Implementierung IWmsActivitySettingList
Codeblock | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Windows.Controls; using Accantum.Wms.ActivityContracts.Settings; using ActivitySample.Activities.FtpUpload.V01; namespace ActivitySample.Activities.FtpUpload.Setting { public class FtpConfigurationSettings : IWmsActivitySettingList { public static Guid SettingId = new Guid("1f2d1198-b5c7-47f9-a8c4-fda02cc49d61"); // Eindeutiger Identifier dieser Einstellung public Guid Identifier => SettingId; /// <summary> /// Bezeichnung für das Einstellungsmenü /// </summary> public string Title => "FTP"; /// <summary> /// Tooltip für die Schaltfläche im Einstellungsmenü /// </summary> public string TitleTooltip => "FTP-Verbindungen verwalten, die in den FTP-Aktivitäten zur Verfügung stehen."; /// <summary> /// Prefix für Zuordnungsvariablen /// </summary> public string MappingVariablePrefix => "ftp"; /// <summary> /// Zusätzliche Spalten, die in der Übersicht angezeigt werden sollen /// </summary> public IEnumerable<WmsSettingColumnDef> ColumnDefinitions => new List<WmsSettingColumnDef> { new WmsSettingColumnDef("FTP-Host", nameof(WmsFtpConfig.Host)), new WmsSettingColumnDef("Verzeichnis", nameof(WmsFtpConfig.RootDirectory)) }; /// <summary> /// UserControl zur Bearbeitung der Einstellung im Dialog. /// </summary> public UserControl DialogContent { get; private set; } /// <summary> /// Prüft, ob die Eingaben im Dialog valide sind. Nur dann wird der Dialog geschlossen /// </summary> /// <returns>true, wenn der Dialog geschlossen werden darf</returns> public Task<bool> IsValidDialogData() { var oViewModel = (DialogContent as FtpConfig)?.ViewModel; return Task.FromResult(oViewModel != null && oViewModel.IsValid()); } /// <summary> /// Zeigt eine Fehlermeldung im Dialog an. /// </summary> /// <param name="a_sPropertyName">Name der fehlerhaften Eigenschaft</param> /// <param name="a_sErrorMessage">Fehlermeldung</param> public void AddErrorToDialog(string a_sPropertyName, string a_sErrorMessage) { var oViewModel = (DialogContent as FtpConfig)?.ViewModel; oViewModel?.AddErrorToDialog(a_sPropertyName, a_sErrorMessage); } /// <summary> /// Erzeugt die Oberfläche zur Bearbeitung eines Eintrages /// </summary> /// <param name="a_oSettingEntry"></param> public void InitialiseDialogData(WmsSettingEntry a_oSettingEntry) { var oVm = new FtpConfigViewModel(a_oSettingEntry); DialogContent = new FtpConfig(oVm); } /// <summary> /// Ermittelt die Eingaben aus dem Dialog um sie zu speichern /// </summary> /// <returns></returns> public WmsSettingEntry GetDialogData() { var oViewModel = (DialogContent as FtpConfig)?.ViewModel; return oViewModel?.GetSettingEntry(); } } } |
Codeblock | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using System.ComponentModel.DataAnnotations; using System.Net; using System.SecuritySecurity.Authentication; using System.SecurityXml.AuthenticationSerialization; using Accantum.Wms.ActivityContracts.Settings; usingnamespace ActivitySample.Activities.FtpUpload.V01; using{ ActivitySample.Helper; using ActivitySample.Properties; namespace ActivitySample.Activities.FtpUpload.Setting {/// <summary> /// publicEinstellungen classzu FtpConfigViewModeleinem :FTP-Account ValidatableModelBase {/// </summary> [Serializable] private string m_sName; public class WmsFtpConfig { private string m_sDescription; private readonly WmsSettingEntry private string m_sHostoSettingEntry; private string m_sUsernamestrRootDirectory; private SecureString m_sPassword;public WmsFtpConfig() { private int? m_iPort; privatePort EFtpEncryptionMode= m_eEncryptionModenull; private SslProtocols m_eEncryptionProtocol;} privatepublic stringWmsFtpConfig(WmsSettingEntry ma_sRootDirectory;oSettingEntry) private{ bool m_bIsBusy; private string m_sConnectionStateInfo;oSettingEntry = a_oSettingEntry; private readonlyId WmsSettingEntry= ma_oSettingEntry.Id; publicName FtpConfigViewModel(WmsSettingEntry= a_oSettingEntry).Name; { //Eigenschaften aus dem Properites-Array laden m_oSettingEntry = a_oSettingEntry ?? new WmsSettingEntry(); Host SetProperties(); = a_oSettingEntry.Properties[nameof(Host)] as string; } Port #region Properties [Required] = a_oSettingEntry.Properties[nameof(Port)] as int?; public string Name User = a_oSettingEntry.Properties[nameof(User)] as string; { getEncryptedPassword => m_sNamea_oSettingEntry.Properties[nameof(EncryptedPassword)] as string; setEncryptionMode => SetProperty(ref m_sName, value); a_oSettingEntry.Properties[nameof(EncryptionMode)] as EFtpEncryptionMode? ?? EFtpEncryptionMode.AutoDetect; } EncryptionProtocol public string Description = a_oSettingEntry.Properties[nameof(EncryptionProtocol)] as SslProtocols? ?? SslProtocols.None; { RootDirectory = a_oSettingEntry.Properties[nameof(RootDirectory)] as string; get => m_sDescription; } set => SetProperty(ref m_sDescription, value); /// <summary> /// }Eindeutige Id aus der Einstellung [Required, Display(ResourceType = typeof(Resource), Name = "Host")] /// </summary> public stringGuid HostId { get; set; } { /// <summary> get => m_sHost; /// Name aus der Einstellung set => SetProperty(ref m_sHost, value);/// </summary> public string Name }{ get; set; } [Display(ResourceType = typeof(Resource), Name = "Username")] /// <summary> public string Username /// FTP-Host für den Datenaustausch { /// </summary> public string getHost => m_sUsername{ get; set; } /// set<summary> => SetProperty(ref m_sUsername, value); /// Port, welcher für }den FTP-Zugang verwendet wird. Wenn nicht gesetzt, dann werden die publicStandardports SecureStringverwendet Password /// {Standardwert: null /// </summary> get => m_sPassword; public int? Port { get; set; =>} SetProperty(ref m_sPassword, value); /// <summary> } /// Benutzer public int? Portdes FTP-Zugangs. {/// </summary> public string User { get => m_iPort; set; } /// <summary> set => SetProperty(ref m_iPort, value); /// Passwort des FTP-Zugangs } /// </summary> public EFtpEncryptionMode EncryptionMode [XmlElement("Password")] { public string EncryptedPassword { get; set; } get => m_eEncryptionMode; /// <summary> set /// Modus der Verschlüsselung (none, explizit, implizit). { /// </summary> public EFtpEncryptionMode SetProperty(ref m_eEncryptionMode, value); EncryptionMode { get; set; } /// <summary> if (value == EFtpEncryptionMode.AutoDetect) /// Protokoll der Verschlüsselung (SSL -Secure Sockets Layer, TLS). /// </summary> EncryptionProtocol = SslProtocols.None; public SslProtocols EncryptionProtocol { get; set; } } }/// <summary> public SslProtocols EncryptionProtocol {/// Basis-Verzeichnis auf dem FTP-Server (Verzeichnisse mit "/" getrennt, nicht mit "\") /// </summary> get => m_eEncryptionProtocol; public string RootDirectory set => SetProperty(ref m_eEncryptionProtocol, value);{ } get => m_strRootDirectory; [Display(ResourceType = typeof(Resource), Name = "RootDirectoryName")] set public string RootDirectory { { if get(value !=> m_sRootDirectory; null) set => SetProperty(ref m_sRootDirectory, value); { } string strPath = value.Replace('\\', '/'); public bool IsBusy { m_strRootDirectory = (string.IsNullOrEmpty(strPath) || strPath.StartsWith("/")) ? getstrPath => m_bIsBusy;: $"/{strPath}"; set} => SetPropertyWithoutValidate(ref m_bIsBusy, value); } else public string ConnectionStateInfo { get => m_sConnectionStateInfostrRootDirectory = null; set => SetPropertyWithoutValidate(ref m_sConnectionStateInfo, value); } } } #endregion /// <summary> public bool IsValid() /// Um Einstellung {zu speichern in ein WmsSettingEntry wandeln und die zu speichernden Eigenschaften in das return ValidateObject();Properties-Array schreiben } /// </summary> public voidWmsSettingEntry AddErrorToDialog(string a_sPropertyName, string a_sErrorMessageToWmsSettingEntry() { AddError(a_sPropertyName, a_sErrorMessage);return new WmsSettingEntry } { public WmsFtpConfig CreateFtpConfig() Id = m_oSettingEntry.Id, { Name = m_oSettingEntry.Name, = Name; Description = m_oSettingEntry.Description, = Description; var sPasswortStringCreationDate = new NetworkCredential(string.Empty, Password).Password;m_oSettingEntry.CreationDate, var oConfigCreationUser = new WmsFtpConfig(m_oSettingEntry).CreationUser, { HostModifyDate = Hostm_oSettingEntry.ModifyDate, PortModifyUser = Portm_oSettingEntry.ModifyUser, UserProperties = Username,new WmsPropertyCollection EncryptedPassword ={ sPasswortString, //Hier Verschlüsseln! z.B. TripleDES EncryptionMode = EncryptionModenew WmsSettingEntryProperty(nameof(Host), Host), EncryptionProtocol = EncryptionProtocol, new WmsSettingEntryProperty(nameof(Port), Port), RootDirectory = RootDirectory new WmsSettingEntryProperty(nameof(User), User), }; return oConfig; new }WmsSettingEntryProperty(nameof(EncryptedPassword), EncryptedPassword), public WmsSettingEntry GetSettingEntry() { new WmsSettingEntryProperty(nameof(EncryptionMode), EncryptionMode), var oFtpConfig = CreateFtpConfig(); return oFtpConfig.ToWmsSettingEntry(); new WmsSettingEntryProperty(nameof(EncryptionProtocol), EncryptionProtocol), } new WmsSettingEntryProperty(nameof(RootDirectory), RootDirectory) private void SetProperties() { } var oFtp = new WmsFtpConfig(m_oSettingEntry) }; } m_sName = m_oSettingEntry.Name; } } |
Implementierung der Oberfläche zur Eingabe der Einstellung
Codeblock | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using System.ComponentModel.DataAnnotations; using System.Net; using System.Security; using System.Security.Authentication; using Accantum.Wms.ActivityContracts.Settings; using ActivitySample.Activities.FtpUpload.V01; using ActivitySample.Helper; using ActivitySample.Properties; namespace ActivitySample.Activities.FtpUpload.Setting { public class FtpConfigViewModel : ValidatableModelBase { private string m_sName; private string m_sDescription =; private string m_oSettingEntry.DescriptionsHost; private string m_sUsername; var oSecurePassword = new NetworkCredential(string.Empty, oFtp.EncryptedPassword).SecurePassword; //Hier Entschlüsselnprivate SecureString m_sPassword; private int? m_sHost = oFtp.HostiPort; private EFtpEncryptionMode m_sUsername = oFtp.UsereEncryptionMode; private SslProtocols m_sPassword = oSecurePasswordeEncryptionProtocol; private string m_iPort = oFtp.PortsRootDirectory; private bool m_eEncryptionModebIsBusy; = oFtp.EncryptionMode; private string m_sConnectionStateInfo; m_eEncryptionProtocol = oFtp.EncryptionProtocol; private readonly WmsSettingEntry m_oSettingEntry; m_sRootDirectory = oFtp.RootDirectory; public FtpConfigViewModel(WmsSettingEntry a_oSettingEntry) } { } } | ||||||||
Codeblock | ||||||||
| ||||||||
using System; using System.Security.Authentication; using System.Xml.Serialization; using Accantum.Wms.ActivityContracts.Settings; namespace ActivitySample.Activities.FtpUpload.V01 { /// <summary>m_oSettingEntry = a_oSettingEntry ?? new WmsSettingEntry(); /// Einstellungen zu einem FTP-Account SetProperties(); /// </summary> } [Serializable] public class WmsFtpConfig #region Properties { [Required] private readonly WmsSettingEntry m_oSettingEntry; public string Name private string m_strRootDirectory; { public WmsFtpConfig() get {=> m_sName; Portset = null> SetProperty(ref m_sName, value); } public WmsFtpConfig(WmsSettingEntry a_oSettingEntry)string Description { m_oSettingEntryget => am_oSettingEntrysDescription; Idset => SetProperty(ref a_oSettingEntry.Idm_sDescription, value); } Name = a_oSettingEntry.Name; [Required, Display(ResourceType = typeof(Resource), Name //Eigenschaften aus dem Properites-Array laden= "Host")] public string Host Host = a_oSettingEntry.Properties[nameof(Host)] as string;{ Portget => a_oSettingEntry.Properties[nameof(Port)] as int?m_sHost; Userset => a_oSettingEntry.Properties[nameof(User)] as string;SetProperty(ref m_sHost, value); } EncryptedPassword = a_oSettingEntry.Properties[nameofDisplay(EncryptedPassword)]ResourceType as string; = typeof(Resource), Name = "Username")] public EncryptionMode = a_oSettingEntry.Properties[nameof(EncryptionMode)] as EFtpEncryptionMode? ?? EFtpEncryptionMode.AutoDetect;string Username { EncryptionProtocol = a_oSettingEntry.Properties[nameof(EncryptionProtocol)] as SslProtocols? ?? SslProtocols.Noneget => m_sUsername; RootDirectoryset = a_oSettingEntry.Properties[nameof(RootDirectory)] as string> SetProperty(ref m_sUsername, value); } public SecureString Password { /// <summary> /// Eindeutige Idget aus der Einstellung=> m_sPassword; /// </summary> set => SetProperty(ref m_sPassword, value); public Guid Id { get; set; } public /// <summary>int? Port ///{ Name aus der Einstellung /// </summary> get => m_iPort; public string Name { get; set; }=> SetProperty(ref m_iPort, value); /// <summary> } /// FTP-Host fürpublic denEFtpEncryptionMode DatenaustauschEncryptionMode /// </summary>{ public string Host {get get; set=> m_eEncryptionMode; } /// <summary> set /// Port, welcher für den FTP-Zugang verwendet wird. Wenn nicht gesetzt, dann werden{ die Standardports verwendet /// Standardwert: null SetProperty(ref m_eEncryptionMode, value); /// </summary> public int? Port {if get; set; }(value == EFtpEncryptionMode.AutoDetect) /// <summary> /// BenutzerEncryptionProtocol des= FTP-ZugangsSslProtocols.None; /// </summary> } public string} User { get; set; } public SslProtocols EncryptionProtocol /// <summary> { /// Passwort des FTP-Zugangs get => /// </summary>m_eEncryptionProtocol; [XmlElement("Password")] set => SetProperty(ref m_eEncryptionProtocol, value); public string EncryptedPassword { get; set; } /// <summary> [Display(ResourceType = typeof(Resource), Name = "RootDirectoryName")] /// Modus der Verschlüsselungpublic (none, explizit, implizit).string RootDirectory { /// </summary> public EFtpEncryptionMode EncryptionModeget { get; set; }=> m_sRootDirectory; set /// <summary>=> SetProperty(ref m_sRootDirectory, value); ///} Protokoll der Verschlüsselung (SSL -Secure Sockets Layer, TLS). /// </summary> public bool IsBusy public SslProtocols EncryptionProtocol { get; set; } /// <summary> get => m_bIsBusy; /// Basis-Verzeichnis auf dem FTP-Server (Verzeichnisseset mit "/" getrennt, nicht mit "\")=> SetPropertyWithoutValidate(ref m_bIsBusy, value); /// </summary>} public string RootDirectoryConnectionStateInfo { get => m_strRootDirectorysConnectionStateInfo; set => SetPropertyWithoutValidate(ref m_sConnectionStateInfo, value); {} if (value != null) #endregion public {bool IsValid() { string strPath =return value.Replace('\\', '/'ValidateObject(); } public void AddErrorToDialog(string ma_strRootDirectorysPropertyName, = (string.IsNullOrEmpty(strPath) || strPath.StartsWith("/")) ? strPath : $"/{strPath}"; a_sErrorMessage) { } AddError(a_sPropertyName, a_sErrorMessage); } else public WmsFtpConfig CreateFtpConfig() { { m_strRootDirectoryoSettingEntry.Name = nullName; m_oSettingEntry.Description } = Description; } var }sPasswortString = new NetworkCredential(string.Empty, Password).Password; /// <summary> var oConfig ///= Um Einstellung zu speichern in ein WmsSettingEntry wandeln und die zu speichernden Eigenschaften in das Properties-Array schreibennew WmsFtpConfig(m_oSettingEntry) { /// </summary> Host = Host, public WmsSettingEntry ToWmsSettingEntry() { Port = Port, return new WmsSettingEntry User = Username, { EncryptedPassword = sPasswortString, Id = m_oSettingEntry.Id,//Hier Verschlüsseln! z.B. TripleDES NameEncryptionMode = m_oSettingEntry.NameEncryptionMode, DescriptionEncryptionProtocol = m_oSettingEntry.DescriptionEncryptionProtocol, CreationDateRootDirectory = m_oSettingEntry.CreationDate,RootDirectory }; CreationUser = m_oSettingEntry.CreationUser, return oConfig; ModifyDate} = m_oSettingEntry.ModifyDate, public WmsSettingEntry GetSettingEntry() ModifyUser = m_oSettingEntry.ModifyUser, { var oFtpConfig = CreateFtpConfig(); Properties = new WmsPropertyCollection return oFtpConfig.ToWmsSettingEntry(); { } private newvoid WmsSettingEntryPropertySetProperties(nameof(Host), Host), { var oFtp = new WmsSettingEntryProperty(nameof(Port), Port), WmsFtpConfig(m_oSettingEntry); m_sName = m_oSettingEntry.Name; m_sDescription = m_oSettingEntry.Description; new WmsSettingEntryProperty(nameof(User), User), var oSecurePassword = new NetworkCredential(string.Empty, oFtp.EncryptedPassword).SecurePassword; //Hier Entschlüsseln new WmsSettingEntryProperty(nameof(EncryptedPassword), EncryptedPassword), m_sHost = oFtp.Host; new WmsSettingEntryProperty(nameof(EncryptionMode), EncryptionMode),m_sUsername = oFtp.User; m_sPassword = oSecurePassword; new WmsSettingEntryProperty(nameof(EncryptionProtocol), EncryptionProtocol), m_iPort = oFtp.Port; new WmsSettingEntryProperty(nameof(RootDirectory), RootDirectory)m_eEncryptionMode = oFtp.EncryptionMode; m_eEncryptionProtocol = oFtp.EncryptionProtocol; } m_sRootDirectory = }oFtp.RootDirectory; } } } |
Implementierung Oberfläche
Codeblock | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<UserControl x:Class="ActivitySample.Activities.FtpUpload.Setting.FtpConfig" 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:enums="clr-namespace:ActivitySample.Activities.FtpUpload.V01" xmlns:settings="clr-namespace:ActivitySample.Activities.FtpUpload.Setting" xmlns:helper="clr-namespace:ActivitySample.Helper" xmlns:resx="clr-namespace:ActivitySample.Properties" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="500" d:DataContext="{d:DesignInstance {x:Type settings:FtpConfigViewModel}}"> <UserControl.Resources> <ResourceDictionary> <helper:InvertedBooleanConverter x:Key="InvertedBooleanConverter"/> <Style x:Key="TextareaStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}"> <Style.Setters> <Setter Property="AcceptsTab" Value="False" /> <Setter Property="AcceptsReturn" Value="True" /> <Setter Property="TextWrapping" Value="Wrap" /> <Setter Property="SpellCheck.IsEnabled" Value="True" /> <Setter Property="VerticalContentAlignment" Value="Top" /> <Setter Property="VerticalScrollBarVisibility" Value="Auto" /> </Style.Setters> </Style> </ResourceDictionary> </UserControl.Resources> <Grid Margin="2" IsEnabled="{Binding ElementName=BusyIndicator, Path=IsBusy, Converter={StaticResource InvertedBooleanConverter}}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*" MinWidth="300" MaxWidth="500"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Label Grid.Row="0" Grid.Column="0" Content="{x:Static resx:Resource.Name}"/> <!--UpdateSourceTrigger ist nötig, um gleich bei Änderungen Speichern-Button zu aktivieren--> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/> <Label Grid.Row="1" Grid.Column="0" Content="{x:Static resx:Resource.Description}"/> <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Description, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TextareaStyle}" MinLines="2" MaxLines="4"/> <Label Grid.Row="2" Grid.Column="0" Content="{x:Static resx:Resource.Host}"/> <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Host, UpdateSourceTrigger=PropertyChanged}"/> <Label Grid.Row="3" Grid.Column="0" Content="{x:Static resx:Resource.Port}"/> <!--Hier ist auch ein Control denkbar, (das WMS nutzt Controls von Telerik) telerik:RadNumericUpDown--> <TextBox Grid.Row="3" Grid.Column="1" Width="80" HorizontalAlignment="Left" Text="{Binding Port, UpdateSourceTrigger=PropertyChanged}"/> <Label Grid.Row="4" Grid.Column="0" Content="{x:Static resx:Resource.Username}"/> <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}"/> <Label Grid.Row="5" Grid.Column="0" Content="{x:Static resx:Resource.Password}"/> <PasswordBox Grid.Row="5" Grid.Column="1" x:Name="PasswordBox"></PasswordBox> <Label Grid.Column="0" Grid.Row="6" Content="{x:Static resx:Resource.Ftp_EncryptionMode}" ToolTip="{x:Static resx:Resource.Ftp_EncryptionModeDesc}"/> <ComboBox Grid.Column="1" Grid.Row="6" SelectedValue="{Binding EncryptionMode}" ItemsSource="{Binding Source={helper:EnumToItemsSource {x:Type enums:EFtpEncryptionMode}}}" DisplayMemberPath="DisplayName" SelectedValuePath="Value" /> <Label Grid.Row="7" Grid.Column="0" Content="{x:Static resx:Resource.RootDirectoryName}"/> <TextBox Grid.Row="7" Grid.Column="1" Text="{Binding RootDirectory, UpdateSourceTrigger=PropertyChanged}"/> </Grid> </UserControl> |
Codeblock | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using System.Net; using System.Windows.Controls; namespace ActivitySample.Activities.FtpUpload.Setting { /// <summary> /// Interaction logic for FtpSettings.xaml /// </summary> public partial class FtpConfig: UserControl { public FtpConfig(FtpConfigViewModel a_oViewModel) { InitializeComponent(); DataContext = a_oViewModel; PasswordBox.Password = new NetworkCredential(string.Empty, a_oViewModel.Password).Password; } public FtpConfigViewModel ViewModel => DataContext as FtpConfigViewModel; } } |
Verwendung in der Aktivität
Codeblock | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using System; using System.Activities; using System.ComponentModel; using System.Drawing; using System.IO; using System.Linq; using System.Security.Authentication; using Accantum.Wms.ActivityContracts; using Accantum.Wms.ActivityContracts.Attributes; using Accantum.Wms.ActivityContracts.Settings; using ActivitySample.Activities.FtpUpload.Setting; using ActivitySample.Images; using ActivitySample.Properties; namespace ActivitySample.Activities.FtpUpload.V01 { /// <summary> /// Mit dieser Aktivität kann eine Datei auf einen FTP-Server hochgeladen werden. /// BEISPIEL für eine Aktivität mit mehreren Einstellungen (<see cref="IWmsActivitySettingList"/> /// </summary> [ActivityGroup("Acc-Demo")] [LocalizedDisplayName("FtpUpload_DisplayName", typeof(Resource))] [LocalizedDescription("FtpUpload_Description", typeof(Resource), 1)] [Designer(typeof(FtpUploadDesigner))] [ActivitySettingsType(typeof(FtpConfigurationSettings))] [ToolboxBitmap(typeof(EmbeddedImageType), @"logo16x16.png")] public sealed class FtpUploadActivity : CodeActivity { public FtpUploadActivity() { DisplayName = Resource.FtpUpload_DisplayName; CreateTargetDir = true; } /// <summary> /// Id der Konfiguration des FTP-Server-Zugangs (aus einer Zuordnung) /// </summary> [LocalizedDisplayName("Ftp_FtpConfig", typeof(Resource))] [LocalizedDescription("Ftp_FtpConfigDesc", typeof(Resource))] [LocalizedCategory("PropertyView_Category_Setting", typeof(Resource))] [ExcludeInAnnotation] public InArgument<Guid> FtpConfig { get; set; } /// <summary> /// Verzeichnis der Quelldatei /// </summary> [LocalizedDisplayName("SourceDirectory", typeof(Resource))] [LocalizedDescription("SourceDirectoryDesc", typeof(Resource))] [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))] public InArgument<string> SourceDirectory { get; set; } /// <summary> /// Name der Quelldatei /// </summary> [LocalizedDisplayName("SourceFilename", typeof(Resource))] [LocalizedDescription("SourceFilenameDesc", typeof(Resource))] [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))] public InArgument<string> SourceFilename { get; set; } /// <summary> /// FTP-Verzeichnis in welches die Datei hochgeladen wird /// </summary> [LocalizedDisplayName("Ftp_FtpDirectory", typeof(Resource))] [LocalizedDescription("FtpUpload_FtpDirectoryDesc", typeof(Resource))] [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))] public InArgument<string> FtpDirectory { get; set; } /// <summary> /// Kennzeichen, ob die Verzeichnisstrukur der Zieldatei angelegt werden soll, /// wenn diese nicht existiert. /// </summary> [LocalizedDisplayName("CreateTargetDir", typeof(Resource))] [LocalizedDescription("CreateTargetDirDesc", typeof(Resource))] [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))] public bool CreateTargetDir { get; set; } /// <summary> /// Kennzeichen, ob eine bereits existierende Zieldatei überschrieben werden soll. /// </summary> [DefaultValue(false)] [LocalizedDisplayName("OverrideExistingFile", typeof(Resource))] [LocalizedDescription("OverrideExistingFileDesc", typeof(Resource))] [LocalizedCategory("PropertyView_Category_Input", typeof(Resource))] public bool OverrideExistingFile { get; set; } protected override void CacheMetadata(CodeActivityMetadata a_oMetadata) { if (FtpConfig?.Expression == null) a_oMetadata.AddValidationError(Resource.Ftp_FtpConfig); if (SourceFilename?.Expression == null) a_oMetadata.AddValidationError(Resource.SourceFilename); if (SourceDirectory?.Expression == null) a_oMetadata.AddValidationError(Resource.SourceDirectory); base.CacheMetadata(a_oMetadata); } protected override void Execute(CodeActivityContext a_oContext) { WmsFtpConfig oFtpConfig = ResolveFptConfig(a_oContext, FtpConfig?.Get(a_oContext)); string sDirectory = SourceDirectory.Get(a_oContext); string sFileName = SourceFilename.Get(a_oContext); //Hochzuladende Datei prüfen FileInfo oSourceFile = new FileInfo(Path.Combine(sDirectory, sFileName)); CheckFileInfo(a_oContext, oSourceFile); string strFtpDirectory = FtpDirectory.Get(a_oContext); using (WmsFtpClient oFtpClient = new WmsFtpClient(oFtpConfig)) { if (!oFtpClient.UploadFile(oSourceFile, strFtpDirectory, CreateTargetDir, OverrideExistingFile)) throw new Exception($"FTP-Server: Fehler bei Hochladen der Datei.{Environment.NewLine}{oFtpClient.LastError}"); } } /// <summary> /// Prüft, ob die Datei existiert und ob der Mandant darauf zugreifen darf. /// </summary> /// <param name="a_oContext"></param> /// <param name="a_oFileInfo"></param> private void CheckFileInfo(CodeActivityContext a_oContext, FileInfo a_oFileInfo) { if (string.IsNullOrEmpty(a_oFileInfo.FullName)) throw new Exception("Es wurde kein Dateiname angegeben."); // Prüfen, ob die Datei in einem gültigen Mandantenverzeichnis liegt var oWmsApi = a_oContext.GetExtension<IWmsApiExtension>(); if (!oWmsApi.IsInTenantFolder(a_oFileInfo, a_oContext)) throw new AuthenticationException("Auf das angegebene Verzeichnis darf nicht zugegriffen werden."); if (!a_oFileInfo.Exists) throw new Exception($"Die Datei {a_oFileInfo.FullName} existiert nicht."); } /// <summary> /// FTP-Einstellung ermitteln /// </summary> public static WmsFtpConfig ResolveFptConfig(ActivityContext a_oContext, Guid? a_gSettingEntryId) { //Einstellung aus dem ActivityContext ermitteln, dazu ist der Identifier des Settings notwendig WmsSettingsCollection oExtension = a_oContext.GetExtension<WmsSettingsCollection>(); //In den SettingEntries suchen, ob ein Eintrag mit der Id vorhanden ist. WmsSettingEntry oSettingEntry = oExtension[FtpConfigurationSettings.SettingId]?.SettingEntries?.FirstOrDefault(s => s.Id == a_gSettingEntryId); if (oSettingEntry == null) throw new Exception($"Einstellung mit Id {a_gSettingEntryId} ist nicht vorhanden!"); return new WmsFtpConfig(oSettingEntry); } } } |
Codeblock | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<sap:ActivityDesigner x:Class="ActivitySample.Activities.FtpUpload.V01.FtpUploadDesigner" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation" xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation" xmlns:converters="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation" xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:resx="clr-namespace:ActivitySample.Properties" xmlns:v01="clr-namespace:ActivitySample.Activities.FtpUpload.V01" xmlns:theme="clr-namespace:Accantum.Wms.ActivityContracts.Theme;assembly=WmsActivityContracts"> <sap:ActivityDesigner.Resources> <converters:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" /> <DataTemplate x:Key="ExpandedTemplate" DataType="v01:FtpUploadDesigner"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Label Grid.Column="0" Grid.Row="0" Content="{x:Static resx:Resource.Ftp_FtpConfig}" ToolTip="{x:Static resx:Resource.Ftp_FtpConfigDesc}"/> <sapv:ExpressionTextBox Grid.Column="1" Grid.Row="0" OwnerActivity="{Binding ModelItem}" Expression="{Binding Path=ModelItem.FtpConfig, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}" ExpressionType="system:Guid"/> <Label Grid.Column="0" Grid.Row="1" Content="{x:Static resx:Resource.SourceDirectory}" ToolTip="{x:Static resx:Resource.SourceDirectoryDesc}"/> <sapv:ExpressionTextBox Grid.Column="1" Grid.Row="1" OwnerActivity="{Binding ModelItem}" Expression="{Binding Path=ModelItem.SourceDirectory, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}" ExpressionType="system:String"/> <Label Grid.Column="0" Grid.Row="2" Content="{x:Static resx:Resource.SourceFilename}" ToolTip="{x:Static resx:Resource.SourceFilenameDesc}"/> <sapv:ExpressionTextBox Grid.Column="1" Grid.Row="2" OwnerActivity="{Binding ModelItem}" Expression="{Binding Path=ModelItem.SourceFilename, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}" ExpressionType="system:String"/> <Label Grid.Column="0" Grid.Row="3" Content="{x:Static resx:Resource.Ftp_FtpDirectory}" ToolTip="{x:Static resx:Resource.FtpUpload_FtpDirectoryDesc}"/> <sapv:ExpressionTextBox Grid.Column="1" Grid.Row="3" OwnerActivity="{Binding ModelItem}" Expression="{Binding Path=ModelItem.FtpDirectory, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}" ExpressionType="system:String"/> <Label Grid.Column="0" Grid.Row="4" Content="{x:Static resx:Resource.Options}"/> <StackPanel Grid.Column="1" Grid.Row="4" Orientation="Horizontal"> <CheckBox Content="{x:Static resx:Resource.OverrideExistingFile}" IsChecked="{Binding Path=ModelItem.OverrideExistingFile, Mode=TwoWay}" /> <CheckBox Content="{x:Static resx:Resource.CreateTargetDir}" IsChecked="{Binding Path=ModelItem.CreateTargetDir, Mode=TwoWay}" /> </StackPanel> </Grid> </DataTemplate> <Style x:Key="ExpandOrCollapsedStyle" TargetType="{x:Type ContentPresenter}"> <Setter Property="ContentTemplate" Value="{x:Static theme:WmsActivityTheme.CollapsedTemplate}"/> <Style.Triggers> <DataTrigger Binding="{Binding Path=ShowExpanded}" Value="true"> <Setter Property="ContentTemplate" Value="{StaticResource ExpandedTemplate}"/> </DataTrigger> </Style.Triggers> </Style> </sap:ActivityDesigner.Resources> <ContentPresenter Style="{StaticResource ExpandOrCollapsedStyle}" Content="{Binding}"/> </sap:ActivityDesigner> |