This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("RegionOfInterestChannels")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RegionOfInterestChannels")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bdb25406-3e28-4e62-ae2a-622120f933da")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BDB25406-3E28-4E62-AE2A-622120F933DA}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RegionOfInterestChannels</RootNamespace>
<AssemblyName>RegionOfInterestChannels</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="Microsoft.Xaml.Behaviors">
<HintPath>..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Microsoft.Xaml.Behaviors.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Prism">
<HintPath>..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.dll</HintPath>
</Reference>
<Reference Include="Prism.Unity.Wpf">
<HintPath>..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.Unity.Wpf.dll</HintPath>
</Reference>
<Reference Include="Prism.Wpf">
<HintPath>..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.Wpf.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Security" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="Unity.Abstractions">
<HintPath>..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Unity.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Unity.Container">
<HintPath>..\..\..\..\Common\DTS.Common\lib\PrismLibrary\Unity.Container.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="RegionOfInterestChannelsModule.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources\StringResources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>StringResources.resx</DependentUpon>
</Compile>
<Compile Include="Resources\TranslateExtension.cs" />
<Compile Include="ViewModel\RegionOfInterestChannelsViewModel.cs" />
<Compile Include="View\GridViewColumns.cs" />
<Compile Include="View\RegionOfInterestChannelsDataTemplateSelector.cs" />
<Compile Include="View\RegionOfInterestChannelsView.xaml.cs">
<DependentUpon>RegionOfInterestChannelsView.xaml</DependentUpon>
</Compile>
<Compile Include="View\StateListIndexConverter.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Common\DTS.Common.Core\DTS.Common.Core.csproj">
<Project>{fab1f470-1574-4301-b56e-d3364aa93679}</Project>
<Name>DTS.Common.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Common\DTS.Common.DAS.Concepts\DTS.Common.DAS.Concepts.csproj">
<Project>{ae3987f7-c4c6-40fb-a353-1a2dadef7a9a}</Project>
<Name>DTS.Common.DAS.Concepts</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Common\DTS.Common.ISO\DTS.Common.ISO.csproj">
<Project>{27d0c63b-9095-42da-95fd-f64444c80558}</Project>
<Name>DTS.Common.ISO</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Common\DTS.Common.Serialization\DTS.Common.Serialization.csproj">
<Project>{0679d014-59c2-4327-b288-0e3bd1374710}</Project>
<Name>DTS.Common.Serialization</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Common\DTS.Common.Storage\DTS.Common.Storage.csproj">
<Project>{e3be457c-0ac7-4a9c-bc81-eafeb3217878}</Project>
<Name>DTS.Common.Storage</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Common\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
<Project>{d6da1b74-c711-43c2-91b1-1908a8d04dbf}</Project>
<Name>DTS.Common.Utilities</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Common\DTS.Common\DTS.Common.csproj">
<Project>{f7a0804f-61a4-40ae-83d0-f1137622b592}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\IService\IService.csproj">
<Project>{c9c45b72-05a3-4962-bc13-a78b1f4b1925}</Project>
<Name>IService</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\SensorDB\SensorDB.csproj">
<Project>{444ef10c-046e-47ad-a9a5-17318d488723}</Project>
<Name>SensorDB</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Users\Users.csproj">
<Project>{be8d217d-6da9-4bca-b62a-a82325b33979}</Project>
<Name>Users</Name>
</ProjectReference>
<ProjectReference Include="..\..\Groups\GroupChannelList\GroupChannelList.csproj">
<Project>{aea41635-d997-4179-9fd3-c145a2052947}</Project>
<Name>GroupChannelList</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Model\" />
</ItemGroup>
<ItemGroup>
<Page Include="View\RegionOfInterestChannelsView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\StringResources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>StringResources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,140 @@
using System;
using System.ComponentModel.Composition;
using System.Windows.Media.Imaging;
using DTS.Common;
using DTS.Common.Interface;
using DTS.Common.Interface.RegionOfInterest.RegionOfInterestChannels;
using Prism.Ioc;
using Prism.Modularity;
using RegionOfInterestChannels;
using Unity;
// ReSharper disable CheckNamespace
// ReSharper disable RedundantAttributeUsageProperty
// ReSharper disable UnusedParameter.Local
[assembly: RegionOfInterestChannelsModuleName]
[assembly: RegionOfInterestChannelsModuleImageAttribute]
namespace RegionOfInterestChannels
{
[Export(typeof(IModule))]
[Module(ModuleName = "RegionOfInterestChannelsModule")]
public class RegionOfInterestChannelsModule : IModule
{
/// <summary>
/// Injected unity container
/// </summary>
private readonly Unity.IUnityContainer _unityContainer;
/// <summary>
/// Initializes a new instance of the <see cref="RegionOfInterestChannelsModule"/> class.
/// </summary>
/// <param name="unityContainer">Obtained reference of the unity container by using dependency injection.</param>
public RegionOfInterestChannelsModule(Unity.IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}
public void Initialize()
{
// Register View & View-Model with Unity dependency injection container as a singleton.
_unityContainer.RegisterType<IRegionOfInterestChannelsView, RegionOfInterestChannelsView>();
_unityContainer.RegisterType<IRegionOfInterestChannelsViewModel, RegionOfInterestChannelsViewModel>();
}
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
Initialize();
}
}
/// <summary>
/// Attribute class contains assembly name
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class RegionOfInterestChannelsModuleNameAttribute : TextAttribute
{
public RegionOfInterestChannelsModuleNameAttribute() : this(null) { }
public RegionOfInterestChannelsModuleNameAttribute(string s)
{
AssemblyName = AssemblyNames.RegionOfInterestChannels.ToString();
}
public override string AssemblyName { get; }
public override Type GetAttributeType()
{
return typeof(TextAttribute);
}
public override string GetAssemblyName()
{
return AssemblyName;
}
}
/// <summary>
/// Attribute class contains assembly image and name - used on the Main screen to SummaryModule available components
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class RegionOfInterestChannelsModuleImageAttribute : ImageAttribute
{
private BitmapImage _img;
public RegionOfInterestChannelsModuleImageAttribute() : this(null) { }
public override BitmapImage AssemblyImage
{
get { _img = AssemblyInfo.GetImage(AssemblyNames.RegionOfInterestChannels.ToString()); return _img; }
}
public RegionOfInterestChannelsModuleImageAttribute(string s)
{
_img = AssemblyInfo.GetImage(AssemblyNames.RegionOfInterestChannels.ToString());
}
public override Type GetAttributeType()
{
return typeof(ImageAttribute);
}
public override BitmapImage GetAssemblyImage()
{
return AssemblyImage;
}
private string _name;
public override string AssemblyName
{
get { _name = AssemblyNames.RegionOfInterestChannels.ToString(); return _name; }
}
public override string GetAssemblyName()
{
return AssemblyName;
}
private string _group;
public override string AssemblyGroup
{
get { _group = eAssemblyGroups.Prepare.ToString(); return _group; }
}
public override string GetAssemblyGroup()
{
return AssemblyGroup;
}
private eAssemblyRegion _region;
public override eAssemblyRegion AssemblyRegion
{
get { _region = eAssemblyRegion.RegionOfInterestChannelsRegion; return _region; }
}
public override eAssemblyRegion GetAssemblyRegion()
{
return AssemblyRegion;
}
}
}

View File

@@ -0,0 +1,117 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace RegionOfInterestChannels.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class StringResources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal StringResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RegionOfInterestChannels.Resources.StringResources", typeof(StringResources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Channel &quot;{0}&quot; has not been assigned to a Region of Interest.
/// </summary>
internal static string Channel_NoROIs {
get {
return ResourceManager.GetString("Channel_NoROIs", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Channel Name.
/// </summary>
internal static string ChannelName {
get {
return ResourceManager.GetString("ChannelName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Some channels had DAS assigned without a channel assigned, these DAS assignments were not used.
/// </summary>
internal static string PhantomDASChannelAssignment {
get {
return ResourceManager.GetString("PhantomDASChannelAssignment", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Region of Interest &quot;{0}&quot; has nothing assigned to it..
/// </summary>
internal static string ROI_NoChannels {
get {
return ResourceManager.GetString("ROI_NoChannels", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Region of Interest.
/// </summary>
internal static string ROI1 {
get {
return ResourceManager.GetString("ROI1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Region of Interest Channel Assignments.
/// </summary>
internal static string Title {
get {
return ResourceManager.GetString("Title", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ChannelName" xml:space="preserve">
<value>Channel Name</value>
</data>
<data name="Channel_NoROIs" xml:space="preserve">
<value>Channel "{0}" has not been assigned to a Region of Interest</value>
</data>
<data name="PhantomDASChannelAssignment" xml:space="preserve">
<value>Some channels had DAS assigned without a channel assigned, these DAS assignments were not used</value>
</data>
<data name="ROI1" xml:space="preserve">
<value>Region of Interest</value>
</data>
<data name="ROI_NoChannels" xml:space="preserve">
<value>Region of Interest "{0}" has nothing assigned to it.</value>
</data>
<data name="Title" xml:space="preserve">
<value>Region of Interest Channel Assignments</value>
</data>
</root>

View File

@@ -0,0 +1,21 @@
using System;
using System.Windows.Markup;
using RegionOfInterestChannels.Resources;
namespace RegionOfInterestChannels
{
[MarkupExtensionReturnType(typeof(string))]
public class TranslateExtension : MarkupExtension
{
private readonly string _key;
public TranslateExtension(string key) { _key = key; }
private const string NotFound = "#stringnotfound#";
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (string.IsNullOrEmpty(_key)) { return NotFound; }
return StringResources.ResourceManager.GetString(_key) ?? NotFound + " " + _key;
}
}
}

View File

@@ -0,0 +1,332 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using DTS.Common.Controls;
using DTS.Common.Interface.RegionOfInterest.RegionOfInterestChannels;
using DTS.Common.Utils;
namespace RegionOfInterestChannels
{
public static class GridViewColumns
{
[AttachedPropertyBrowsableForType(typeof(GridView))]
public static object GetColumnsSource(DependencyObject obj)
{
return obj.GetValue(ColumnsSourceProperty);
}
public static void SetColumnsSource(DependencyObject obj, object value)
{
obj.SetValue(ColumnsSourceProperty, value);
}
// Using a DependencyProperty as the backing store for ColumnsSource. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColumnsSourceProperty =
DependencyProperty.RegisterAttached(
"ColumnsSource",
typeof(object),
typeof(GridViewColumns),
new UIPropertyMetadata(
null,
ColumnsSourceChanged));
[AttachedPropertyBrowsableForType(typeof(GridView))]
public static DataTemplateSelector GetCellDataTemplateSelector(DependencyObject obj)
{
return (DataTemplateSelector)obj.GetValue(CellDataTemplateSelectorProperty);
}
public static void SetCellDataTemplateSelector(DependencyObject obj, DataTemplateSelector value)
{
obj.SetValue(CellDataTemplateSelectorProperty, value);
}
public static readonly DependencyProperty CellDataTemplateSelectorProperty =
DependencyProperty.RegisterAttached(
"CellDataTemplateSelector",
typeof(DataTemplateSelector),
typeof(GridViewColumns),
new UIPropertyMetadata(null));
[AttachedPropertyBrowsableForType(typeof(GridView))]
public static DataTemplate GetCellDataTemplate(DependencyObject obj)
{
return (DataTemplate)obj.GetValue(CellDataTemplateProperty);
}
public static void SetCellDataTemplate(DependencyObject obj, DataTemplate value)
{
obj.SetValue(CellDataTemplateProperty, value);
}
public static readonly DependencyProperty CellDataTemplateProperty =
DependencyProperty.RegisterAttached(
"CellDataTemplate",
typeof(DataTemplate),
typeof(GridViewColumns),
new UIPropertyMetadata(null));
[AttachedPropertyBrowsableForType(typeof(GridView))]
public static string GetHeaderTextMember(DependencyObject obj)
{
return (string)obj.GetValue(HeaderTextMemberProperty);
}
public static void SetHeaderTextMember(DependencyObject obj, string value)
{
obj.SetValue(HeaderTextMemberProperty, value);
}
// Using a DependencyProperty as the backing store for HeaderTextMember. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeaderTextMemberProperty =
DependencyProperty.RegisterAttached("HeaderTextMember", typeof(string), typeof(GridViewColumns), new UIPropertyMetadata(null));
[AttachedPropertyBrowsableForType(typeof(GridView))]
public static string GetDisplayMember(DependencyObject obj)
{
return (string)obj.GetValue(DisplayMemberProperty);
}
public static void SetDisplayMember(DependencyObject obj, string value)
{
obj.SetValue(DisplayMemberProperty, value);
}
// Using a DependencyProperty as the backing store for DisplayMember. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DisplayMemberProperty =
DependencyProperty.RegisterAttached("DisplayMember", typeof(string), typeof(GridViewColumns), new UIPropertyMetadata(null));
private static void ColumnsSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
GridView gridView = obj as GridView;
if (gridView != null)
{
gridView.Columns.Clear();
if (e.OldValue != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(e.OldValue);
if (view != null)
RemoveHandlers(gridView, view);
}
if (e.NewValue != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(e.NewValue);
if (view != null)
{
AddHandlers(gridView, view);
CreateColumns(gridView, view);
}
}
}
}
private static IDictionary<ICollectionView, List<GridView>> _gridViewsByColumnsSource =
new Dictionary<ICollectionView, List<GridView>>();
private static List<GridView> GetGridViewsForColumnSource(ICollectionView columnSource)
{
List<GridView> gridViews;
if (!_gridViewsByColumnsSource.TryGetValue(columnSource, out gridViews))
{
gridViews = new List<GridView>();
_gridViewsByColumnsSource.Add(columnSource, gridViews);
}
return gridViews;
}
private static void AddHandlers(GridView gridView, ICollectionView view)
{
GetGridViewsForColumnSource(view).Add(gridView);
view.CollectionChanged += ColumnsSource_CollectionChanged;
}
private static void CreateColumns(GridView gridView, ICollectionView view)
{
foreach (var item in view)
{
GridViewColumn column = CreateColumn(gridView, item);
gridView.Columns.Add(column);
}
}
private static void RemoveHandlers(GridView gridView, ICollectionView view)
{
view.CollectionChanged -= ColumnsSource_CollectionChanged;
GetGridViewsForColumnSource(view).Remove(gridView);
}
private static void ColumnsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ICollectionView view = sender as ICollectionView;
var gridViews = GetGridViewsForColumnSource(view);
if (gridViews == null || gridViews.Count == 0)
return;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var gridView in gridViews)
{
for (int i = 0; i < e.NewItems.Count; i++)
{
GridViewColumn column = CreateColumn(gridView, e.NewItems[i]);
gridView.Columns.Insert(e.NewStartingIndex + i, column);
}
}
break;
case NotifyCollectionChangedAction.Move:
foreach (var gridView in gridViews)
{
List<GridViewColumn> columns = new List<GridViewColumn>();
for (int i = 0; i < e.OldItems.Count; i++)
{
GridViewColumn column = gridView.Columns[e.OldStartingIndex + i];
columns.Add(column);
}
for (int i = 0; i < e.NewItems.Count; i++)
{
GridViewColumn column = columns[i];
gridView.Columns.Insert(e.NewStartingIndex + i, column);
}
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (var gridView in gridViews)
{
for (int i = 0; i < e.OldItems.Count; i++)
{
gridView.Columns.RemoveAt(e.OldStartingIndex);
}
}
break;
case NotifyCollectionChangedAction.Replace:
foreach (var gridView in gridViews)
{
for (int i = 0; i < e.NewItems.Count; i++)
{
GridViewColumn column = CreateColumn(gridView, e.NewItems[i]);
gridView.Columns[e.NewStartingIndex + i] = column;
}
}
break;
case NotifyCollectionChangedAction.Reset:
foreach (var gridView in gridViews)
{
gridView.Columns.Clear();
CreateColumns(gridView, sender as ICollectionView);
}
break;
default:
break;
}
}
private static void GridViewColumnHeaderSearchable_OnSearch(object sender, RoutedEventArgs e)
{
var searchTerm = (string)e.OriginalSource;
var columnTag = (sender as GridViewColumnHeaderSearchable)?.Tag;
var viewModel = (IRegionOfInterestChannelsViewModel)(sender as GridViewColumnHeaderSearchable)?.DataContext;
viewModel?.Filter(columnTag, searchTerm);
}
private static void GridViewColumnHeader_OnClick(object sender, RoutedEventArgs e)
{
var columnTag = (sender as GridViewColumnHeaderSearchable)?.Tag ?? Utils.FindChild<GridViewColumnHeaderSearchable>((DependencyObject)e.OriginalSource, null)?.Tag;
var viewModel = (IRegionOfInterestChannelsViewModel)(sender as GridViewColumnHeaderSearchable)?.DataContext;
viewModel?.Sort(columnTag, true);
}
private static void GridViewColumnHeaderSelectable_OnSelectAll(object sender, RoutedEventArgs e)
{
var columnTag = (sender as GridViewColumnHeaderSelectable)?.Tag.ToString();
var columnIndex = GetArrayIndex(columnTag);
var viewModel = (IRegionOfInterestChannelsViewModel)(sender as GridViewColumnHeaderSelectable)?.DataContext;
viewModel?.SelectAll(columnIndex, (bool)(e?.OriginalSource ?? false));
}
private static GridViewColumn CreateColumn(GridView gridView, object columnSource)
{
GridViewColumn column = new GridViewColumn();
string headerTextMember = GetHeaderTextMember(gridView);
string displayMember = GetDisplayMember(gridView);
DataTemplate template = GetCellDataTemplate(gridView);
DataTemplateSelector selector = GetCellDataTemplateSelector(gridView);
if (!string.IsNullOrEmpty(headerTextMember))
{
var columnSourceType = (System.Type)GetPropertyValue(columnSource, "MemberType");
switch (true)
{
case bool _ when columnSourceType == typeof(bool):
column.Header = new GridViewColumnHeaderSelectable
{
HeaderTitle = (string)GetPropertyValue(columnSource, headerTextMember),
Tag = (string)GetPropertyValue(columnSource, displayMember),
};
((GridViewColumnHeaderSelectable)column.Header).SelectAll += GridViewColumnHeaderSelectable_OnSelectAll;
break;
case bool _ when columnSourceType == typeof(string):
column.Header = new GridViewColumnHeaderSearchable
{
HeaderTitle = (string)GetPropertyValue(columnSource, headerTextMember),
Tag = (string)GetPropertyValue(columnSource, displayMember),
};
((GridViewColumnHeaderSearchable)column.Header).Search += GridViewColumnHeaderSearchable_OnSearch;
((GridViewColumnHeaderSearchable)column.Header).ClickHandler += GridViewColumnHeader_OnClick;
break;
default:
column.Header = (string)GetPropertyValue(columnSource, headerTextMember);
break;
}
//column.Header = GetPropertyValue(columnSource, headerTextMember);
}
//remember, remember: selector < template < displaymember
if (null != selector)
{
column.CellTemplateSelector = selector;
}
if (null != template)
{
column.CellTemplate = template;
}
if (!string.IsNullOrEmpty(displayMember))
{
//string propertyName = GetPropertyValue(columnSource, displayMember) as string;
//column.DisplayMemberBinding = new Binding(propertyName);
}
return column;
}
private static object GetPropertyValue(object obj, string propertyName)
{
if (obj != null)
{
PropertyInfo prop = obj.GetType().GetProperty(propertyName);
if (prop != null)
return prop.GetValue(obj, null);
}
return null;
}
private static int GetArrayIndex(string fromString)
{
var openBracket = fromString.LastIndexOf("[");
var closeBracket = fromString.LastIndexOf("]");
var numString = fromString.Substring(openBracket + 1, closeBracket - openBracket - 1);
if (int.TryParse(numString, out var index))
{
return index;
}
return -1;
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace RegionOfInterestChannels
{
public class RegionOfInterestChannelsDataTemplateSelector : DataTemplateSelector
{
public DataTemplate TextBlockDataTemplate { get; set; }
public DataTemplate CheckBoxDataTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is ChannelEnabler)
{
GridViewRowPresenter presenter = (container as ContentPresenter).Parent as GridViewRowPresenter;
if (presenter != null)
{
int checkStartColumn = -1;
for (int i = 0; i < presenter.Columns.Count; i++)
{
ContentPresenter templated = VisualTreeHelper.GetChild(presenter, i) as ContentPresenter;
var columnPropertyType = item.GetType().GetProperty(presenter.Columns[i].Header.ToString().Replace(" ", ""))?.GetValue(item, null).GetType();
if (null == columnPropertyType && checkStartColumn < 0)
{
checkStartColumn = i;
}
if (templated != null && templated.Equals(container as ContentPresenter))
{
switch (Type.GetTypeCode(columnPropertyType))
{
case TypeCode.String:
(container as ContentPresenter).Tag = item.GetType().GetProperty(presenter.Columns[i].Header.ToString().Replace(" ", ""))?.GetValue(item, null);
return TextBlockDataTemplate;
case TypeCode.Boolean:
default:
(container as ContentPresenter).Tag = i - checkStartColumn;
return CheckBoxDataTemplate;
}
}
}
}
return CheckBoxDataTemplate;
}
return TextBlockDataTemplate;
}
}
}

View File

@@ -0,0 +1,83 @@
<base:BaseView x:Class="RegionOfInterestChannels.RegionOfInterestChannelsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
xmlns:behaviors="clr-namespace:DTS.Common.Behaviors;assembly=DTS.Common"
xmlns:controls="clr-namespace:DTS.Common.Controls;assembly=DTS.Common"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:strings="clr-namespace:RegionOfInterestChannels"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:RegionOfInterestChannels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<base:BaseView.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/CommonStyles.xaml"/>
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Controls/combobox.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="TextBox" BasedOn="{StaticResource TTS_TextBoxStyle}"/>
<Style TargetType="TextBlock" BasedOn="{StaticResource TTS_TextBlockStyle}">
<Setter Property="FontFamily" Value="Courier New"/>
</Style>
<Style TargetType="CheckBox" BasedOn="{StaticResource PageContentCheckBoxStyle}" />
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource Gray_GridViewColumnHeaderStyle}"/>
<local:StateListIndexConverter x:Key="StateListIndexConverter" />
<local:RegionOfInterestChannelsDataTemplateSelector x:Key="DataTemplateSelector">
<local:RegionOfInterestChannelsDataTemplateSelector.CheckBoxDataTemplate>
<DataTemplate>
<CheckBox HorizontalAlignment="Center" IsChecked="{Binding Path=Checked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutomationProperties.AutomationId="ROIChannelCheckBox">
<CheckBox.DataContext>
<MultiBinding Converter="{StaticResource StateListIndexConverter}">
<Binding Path="ROIIncludes"/>
<Binding Path="Tag" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}" />
</MultiBinding>
</CheckBox.DataContext>
</CheckBox>
</DataTemplate>
</local:RegionOfInterestChannelsDataTemplateSelector.CheckBoxDataTemplate>
<local:RegionOfInterestChannelsDataTemplateSelector.TextBlockDataTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Left" AutomationProperties.AutomationId="ROIChannelTextLbl"
Text="{Binding Path=Tag, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, FallbackValue='???????????????A'}"
Loaded="TextBlock_Loaded" FontFamily="Courier New"/>
</DataTemplate>
</local:RegionOfInterestChannelsDataTemplateSelector.TextBlockDataTemplate>
</local:RegionOfInterestChannelsDataTemplateSelector>
</ResourceDictionary>
</base:BaseView.Resources>
<Grid Background="{StaticResource Brush_ApplicationContentBackground}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Grid.Column="0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Style="{StaticResource SimpleHeader}" Grid.Row="0"
Content="{local:TranslateExtension Title}"
HorizontalAlignment="Stretch"
VerticalAlignment="Top" AutomationProperties.AutomationId="ROIChannelsTitleLabel" />
<ListView Grid.Row="1" ItemsSource="{Binding ChannelList, UpdateSourceTrigger=PropertyChanged}" AutomationProperties.AutomationId="ROIChannelsListView" GridViewColumnHeader.Click="GridViewColumnHeader_OnClick"
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource TTS_ListViewItemStyle}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="FontFamily" Value="Courier New" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<controls:AutoSizedGridView local:GridViewColumns.HeaderTextMember="HeaderText"
local:GridViewColumns.DisplayMember="DisplayMember"
local:GridViewColumns.ColumnsSource="{Binding Columns}"
local:GridViewColumns.CellDataTemplateSelector="{StaticResource DataTemplateSelector}"/>
</ListView.View>
</ListView>
</Grid>
</Grid>
</base:BaseView>

View File

@@ -0,0 +1,48 @@
using DTS.Common.Controls;
using DTS.Common.Interface.RegionOfInterest.RegionOfInterestChannels;
using DTS.Common.Utils;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace RegionOfInterestChannels
{
/// <summary>
/// Interaction logic for RegionOfInterestChannelsView.xaml
/// </summary>
public partial class RegionOfInterestChannelsView : IRegionOfInterestChannelsView
{
public RegionOfInterestChannelsView()
{
InitializeComponent();
}
private void GridViewColumnHeader_OnClick(object sender, RoutedEventArgs e)
{
var vm = (IRegionOfInterestChannelsViewModel)DataContext;
var columnTag = (sender as GridViewColumnHeaderSearchable)?.Tag ?? Utils.FindChild<GridViewColumnHeaderSearchable>((DependencyObject)e.OriginalSource, null)?.Tag ??
(sender as GridViewColumnHeaderSelectable)?.Tag ?? Utils.FindChild<GridViewColumnHeaderSelectable>((DependencyObject)e.OriginalSource, null)?.Tag;
vm?.Sort(columnTag, true);
}
private void TextBlock_Loaded(object sender, RoutedEventArgs e)
{
if (!(sender is TextBlock tb)) return;
if (!((tb.TemplatedParent as ContentPresenter)?.Parent is GridViewRowPresenter presenter)) return;
for (int i = 0; i < presenter.Columns.Count; i++)
{
if (!(VisualTreeHelper.GetChild(presenter, i) is ContentPresenter templated) ||
!templated.Equals((ContentPresenter)tb.TemplatedParent)) continue;
//found our column
if (presenter.Columns[i].ActualWidth < tb.ActualWidth && double.IsNaN(presenter.Columns[i].Width))
{
//now that bindings/templates are applied, control width > column width
//force remeasure
presenter.Columns[i].Width = tb.ActualWidth;
presenter.Columns[i].Width = double.NaN;
}
break;
}
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Data;
namespace RegionOfInterestChannels
{
public class StateListIndexConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (null == values || values.Length != 2)
return null;
if (!(values[1] is int idx) || !(values[0] is IEnumerable<State> states) || states.Count() <= idx)
return null;
return states.ElementAt(idx);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]