Hello,
I am making an GUI editor for a configuration file which is an XML file that looks like the following
<?xml version="1.0" encoding="utf-8"?><!-- @version: 1.0 --><gateway-config ><!-- GATEWAY COMMUNICATION MIDDLEWARE--><!-- Gates configuration: gate - executable component. It should reside in the same folder with configuration tool--><!-- By default component executable has name like PortimaGW<gate name>.exe--><!-- If it is not the case, then 'exec-filename' can provide different executable filename--><!-- Every gate can have dedicated queue table, queue subfolder.--><!-- GateEdiSMTP is special gate, it always exists. GateEdiSMTP has special registration model.--><!-- GateEdiSMTP always register one SMTP Server windows NT service and/or one or more SMTP Sender windows NT services.--><!-- GateEdiSMPT Server serves all 'in' channels of GateEdiSMPT (and, probably, GateSMTP) gates.--><!-- GateEdiSMTP Sender serves all 'out' GateEdiSMTP channels - one service per one GateEdiSMPT out channels.--><!-- Other gates have standard registration schema - one windows NT service per channel--><gate-config><gate name="GateEdiSMTP" exec-filename="PortimaGWEdiSmtp.exe" queue-table="gate_edi_smtp" queue-subfolder="GateEdiSMTP" /><gate name="GateSMTP" exec-filename="PortimaGWGateSMTP.exe" queue-table="gate_smtp" queue-subfolder="GateSMTP" /><gate name="GateAdoDB" exec-filename="PortimaGWGateAdoDB.exe" queue-table="gate_ado_db" queue-subfolder="GateAdoDB" /><gate name="GateERdr" exec-filename="PortimaGWGateERdr.exe" queue-table="gate_e_rdr" queue-subfolder="GateERdr" /><gate name="GateEdiBroker" exec-filename="PortimaGWGateEdiBroker.exe" queue-table="gate_edi_broker" queue-subfolder="GateEdiBroker" /><gate name="GateRoundTripTest" exec-filename="PortimaGWRoundTripTest.exe" queue-table="gate_rtt" queue-subfolder="GateRoundTripTest" /></gate-config><!-- Channels: different gate I/O communication channels--><channel-config><!-- name, gate and direction can not be empty or absent--><!-- channel name must be unique among all channel names--><!-- (for the message handler selector to work properly)--><!-- direction must be specified and can be either 'in' (gateway input) or 'out' (gateway output)--><!-- display-name can be specified to be used as part of service display name--><!-- if display-name is not specified then name is used instead (blanks are allowed)--><!-- log section defines log level and for how many days log files are kept--><!-- domain section defines list of domains, or name of domain to be used with From and To values of mime mmessages--><!-- if name is defined then this one is used as main one for outgoing messages, otherwise, first in the list is the main one--><!-- mime-composer section defines MIME package type which can be: single (default) or multipart --><!-- resend section can be specified for output channels where resender has sence--><!-- in resend section: --><!-- num-of-retry specifies for how many times message should be resent before giving up--><!-- retry-every-min specifies how long should the resender wait for before next try--><!-- settings section contains channel specific parameters with two special recognized one --><!-- group-message-attachments (true/false) allows regrouping business message and its attachments in one MIME package --><!-- server (name) is used by handler as Svr field in output queue so can be used directly by output channel --><!-- pki section can be specified in which case we use secure message exchange--><channel gate="GateEdiSMTP" name="Server" direction="in" ><!-- if sign-method, encrypt-method, mdn are specified then outgoing messages are signed/encrypted/ask for MDN--><!-- the certs specified can be used for incoming/outgoing messages --><!-- mdn can be 'sha1' (default), 'md5', 'unsigned' or 'no' and is not used for input gates --><!-- mdn-channel can be used to divert generated mdns to dedicated output channel (used for EDI server channels)--><pki sign-method="SHA1" encrypt-method="RC4" mdn-channel="Sender"></pki></channel><channel gate="GateEdiSMTP" name="Sender" direction="out" ><!-- if sign-method and/or encrypt-method are specified then outgoing messages are signed/encrypted --><!-- the certs specified can be used for incoming/outgoing messages --><!-- mdn can be 'sha1' (default), 'md5', 'unsigned' or 'no' and is not used for input gates --><!-- mdn-channel can be used to divert generated mdns to dedicated output channel (used for EDI server channels)--><pki sign-method="SHA1" encrypt-method="RC4" mdn="sha1"></pki></channel><channel gate="GateAdoDB" name="FromCy" direction="in" io-timeout="60" display-name="From Cy"><log level="3" keep-for-days="14" /><settings db-server = "pc01832" db-database = "PORT_DB" db-table = "Messages" db-att-table = "Attachments" /></channel><channel gate="GateAdoDB" name="ToCy" direction="out" io-timeout="60" display-name="To Cy"><log level="3" keep-for-days="14" /><settings db-server = "pc01832" db-database = "PORT_DB" db-table = "Messages" db-att-table = "Attachments" /></channel></channel-config><!-- GATEWAY SERVICES--><!-- <dispatcher-config ref-guid="..." /> attribute defines whether or not to filter out messages with reappearing Reference GUID.--><!-- Can be 'unique' (default) or any other value to cancel the check --><!-- <ipc-as2-decomposer /> section defines behavior of IPC.AS2.XX message decomposer. --><!-- By default IPC.AS2 message are decomposed into seperate IPC.AS2 parts --><!-- For some exchange types this behavior can be canceled. --><!-- <ipc-as2-decomposer bypass="..." /> attribute specifies a list of exchange types seperated by ';' --><!-- for which do not decompose IPC.AS2 messages. --><dispatcher-config ><handlers><handler name="EDI to EDI"><selectors><!-- channel-name, message-class, exchange-type, from, to: "*" - any value; "" - NO value; "..." - real value --><!-- if the value is skipped, the default "*" (any value) is used instead --><selector channel-name="Server" message-class="*" exchange-type="*" from="*" to="*"/></selectors><!-- if you skip message-class or set it "*", the original one is used --><!-- if you specify message-class you can specify error-channel-name --><!-- if conversion fails than copy of message and error message is send to error-channel-name --><!-- if you skip priority 0 is the default --><output channel-name="Sender" message-class="*" error-channel-name="ToCy" priority="0"><parameters><edi-param name="" value="" /></parameters></output><error channel-name=""/></handler><handler name="E-RDR to EDI"><selectors><!-- channel-name, message-class, exchange-type, from, to: "*" - any value; "" - NO value; "..." - real value --><!-- if the value is skipped, the default "*" (any value) is used instead --><selector channel-name="39Export" message-class="*" exchange-type="*" from="*" to="*"/></selectors><!-- if you skip message-class or set it "*", the original one is used --><!-- if you specify message-class you can specify error-channel-name --><!-- if conversion fails than copy of message and error message is send to error-channel-name --><!-- if you skip priority 0 is the default --><output channel-name="Sender" message-class="IPC.AS2.E1" error-channel-name="ToCy" priority="0"><parameters><edi-param name="" value="" /></parameters></output><error channel-name=""/></handler></handlers></dispatcher-config></gateway-config>
I am using WPF and a lot of XmlProvider, XPath bindings and so on and everything goes smoothly with minimum C# coding expept for one thing.
Each channel in configuration can have a 'pki' section (or xml element) which is optional but anyway. This 'pki' element can contain 'mdn-channel' attribute which must contain either valid channel name that is already defined with 'direction'='out' or empty string.
In my WPF window this field is edited via ComboBox control. This ComboBox ItemsSource defined as a CompositeCollection that holds empty string and collection of valid channel names
Here is an exept of code that implements this
<Window x:Class="PortimaGWConfig.WindowGwConfig" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase" xmlns:debug="clr-namespace:System.Diagnostics;assembly=WindowsBase" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:me="clr-namespace:PortimaGWConfig"><Window.Resources> ...<XmlDataProvider x:Key="gatewayConfig" Source="pack://siteOfOrigin:,,,/gateway.config.xml" debug:PresentationTraceSources.TraceLevel="High"/> ...<CollectionViewSource x:Key="gatewayConfigViewOutChannelNames"><CollectionViewSource.Source><Binding Source="{StaticResource gatewayConfig}" XPath="gateway-config/channel-config/channel[@direction='out']/@name"/></CollectionViewSource.Source></CollectionViewSource></Window.Resources> .... <ComboBox Name="editGwChannelMDNChannel"
SelectedValue="{Binding XPath=pki/@mdn-channel, FallbackValue={x:Static Member=sys:String.Empty}}"><ComboBox.ItemsSource><CompositeCollection><x:Static Member="sys:String.Empty" /><CollectionContainer Collection="{Binding Source={StaticResource gatewayConfigViewOutChannelNames}}"/></CompositeCollection></ComboBox.ItemsSource></ComboBox> ...</Window>
The problem is that even through my pki.mdn-channel is equal to "Sender" the ComboBox does not reflect this value.
Another anoying this is sorting of channel names in CollectionViewSource 'gatewayConfigViewOutChannelNames'. I resorted to using ListCollectionView.CustomSort property but my original intention was to use as little coding as possible
Does somebody knows how to handle this situation correctionly?