Merge commit '1a74bce2ad0f4ac2c1b21d34220c4a7d44548be2' as 'FSI.Lib'
This commit is contained in:
390
FSI.Lib/.gitignore
vendored
Normal file
390
FSI.Lib/.gitignore
vendored
Normal file
@@ -0,0 +1,390 @@
|
||||
# ---> VisualStudio
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Nuget personal access tokens and Credentials
|
||||
nuget.config
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
25
FSI.Lib/FSI.Lib.sln
Normal file
25
FSI.Lib/FSI.Lib.sln
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31321.278
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FSI.Lib", "FSI.Lib\FSI.Lib.csproj", "{1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0198E104-F95E-49D7-8FA5-9366011FAA9A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
13
FSI.Lib/FSI.Lib/Alg/Casts.cs
Normal file
13
FSI.Lib/FSI.Lib/Alg/Casts.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace FSI.Lib.Alg
|
||||
{
|
||||
public class Casts
|
||||
{
|
||||
|
||||
public static dynamic Cast(dynamic obj, Type castTo)
|
||||
{
|
||||
return Convert.ChangeType(obj, castTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
FSI.Lib/FSI.Lib/App.config
Normal file
24
FSI.Lib/FSI.Lib/App.config
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="Epl.Prj.Path"
|
||||
value="\\fondium.org\DESI$\AUG_Abteilung\Betriebstechnik\EPL\P8\Data\Projekte\FSI\"/>
|
||||
<add key="Epl.Pdf.Path"
|
||||
value="\\10.10.1.40\Betriebstechnik\Eplan\"/>
|
||||
|
||||
<add key="TimeStamp.Format"
|
||||
value="_yyyyMMdd_HHmmss"/>
|
||||
|
||||
<add key ="SieTiaWinCCMsgMgt.Autostart"
|
||||
value="false"/>
|
||||
<add key ="SieTiaWinCCMsgMgt.UpdateIntervall"
|
||||
value="100"/>
|
||||
<add key ="SieTiaWinCCMsgMgt.WindowsName"
|
||||
value=""/>
|
||||
<add key ="SieTiaWinCCMsgMgt.WindowsClassName"
|
||||
value="#32770"/>
|
||||
<add key ="SieTiaWinCCMsgMgt.ButtonName"
|
||||
value="Zur Kenntnis genommen"/>
|
||||
|
||||
</appSettings>
|
||||
</configuration>
|
||||
78
FSI.Lib/FSI.Lib/DeEncryptString/DeEncrypt.cs
Normal file
78
FSI.Lib/FSI.Lib/DeEncryptString/DeEncrypt.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace FSI.Lib.DeEncryptString
|
||||
{
|
||||
public static class DeEncrypt
|
||||
{
|
||||
/// <summary>
|
||||
/// Encrypts the string.
|
||||
/// </summary>
|
||||
/// <param name="clearText">The clear text.</param>
|
||||
/// <param name="Key">The key.</param>
|
||||
/// <param name="IV">The IV.</param>
|
||||
/// <returns></returns>
|
||||
private static byte[] CryptString(byte[] clearText, byte[] Key, byte[] IV)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
Rijndael alg = Rijndael.Create();
|
||||
alg.Key = Key;
|
||||
alg.IV = IV;
|
||||
CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
|
||||
cs.Write(clearText, 0, clearText.Length);
|
||||
cs.Close();
|
||||
byte[] encryptedData = ms.ToArray();
|
||||
return encryptedData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the string.
|
||||
/// </summary>
|
||||
/// <param name="clearText">The clear text.</param>
|
||||
/// <param name="Password">The password.</param>
|
||||
/// <returns></returns>
|
||||
public static string CryptString(string clearText, string Password)
|
||||
{
|
||||
byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
|
||||
PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
|
||||
byte[] encryptedData = CryptString(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));
|
||||
return Convert.ToBase64String(encryptedData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the string.
|
||||
/// </summary>
|
||||
/// <param name="cipherData">The cipher data.</param>
|
||||
/// <param name="Key">The key.</param>
|
||||
/// <param name="IV">The IV.</param>
|
||||
/// <returns></returns>
|
||||
private static byte[] DecryptString(byte[] cipherData, byte[] Key, byte[] IV)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
var alg = Rijndael.Create();
|
||||
alg.Key = Key;
|
||||
alg.IV = IV;
|
||||
CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
|
||||
cs.Write(cipherData, 0, cipherData.Length);
|
||||
cs.Close();
|
||||
byte[] decryptedData = ms.ToArray();
|
||||
return decryptedData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the string.
|
||||
/// </summary>
|
||||
/// <param name="cipherText">The cipher text.</param>
|
||||
/// <param name="Password">The password.</param>
|
||||
/// <returns></returns>
|
||||
public static string DecryptString(string cipherText, string Password)
|
||||
{
|
||||
byte[] cipherBytes = Convert.FromBase64String(cipherText);
|
||||
PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
|
||||
byte[] decryptedData = DecryptString(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16));
|
||||
return System.Text.Encoding.Unicode.GetString(decryptedData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
31
FSI.Lib/FSI.Lib/FSI.Lib.csproj
Normal file
31
FSI.Lib/FSI.Lib/FSI.Lib.csproj
Normal file
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
|
||||
<AssemblyVersion>1.0</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Icons\Cross.png" />
|
||||
<None Remove="Icons\FondiumU.ico" />
|
||||
<None Remove="Icons\Open.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Icons\Cross.png" />
|
||||
<Resource Include="Icons\FondiumU.ico" />
|
||||
<Resource Include="Icons\Open.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Guis\SieStarterCsvExporter\Convert_SINAMICS_trace_CSV.exe">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
54
FSI.Lib/FSI.Lib/Guis/AutoPw/FrmMain.xaml
Normal file
54
FSI.Lib/FSI.Lib/Guis/AutoPw/FrmMain.xaml
Normal file
@@ -0,0 +1,54 @@
|
||||
<Window x:Class="FSI.Lib.Guis.AutoPw.FrmMain"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:FSI.Lib.Guis.AutoPw"
|
||||
mc:Ignorable="d"
|
||||
Title="Passwort eingeben"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Height="Auto"
|
||||
Width="Auto"
|
||||
Icon="../../Icons/FondiumU.ico"
|
||||
WindowStyle="ToolWindow">
|
||||
|
||||
<Grid FocusManager.FocusedElement="{Binding ElementName=TbPw}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="Passwort:"
|
||||
Margin="5 5" />
|
||||
<PasswordBox x:Name="TbPw"
|
||||
Margin=" 5 5 5 5"
|
||||
MinWidth="150"
|
||||
PasswordChanged="TbPw_PasswordChanged"
|
||||
KeyDown="TbPw_KeyDown"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1"
|
||||
Orientation="Horizontal">
|
||||
<Button x:Name="BtnOk"
|
||||
Content="Ok"
|
||||
MinWidth="75"
|
||||
Click="BtnOk_Click"
|
||||
Margin="5 5 " />
|
||||
|
||||
<Button x:Name="BtnCancel"
|
||||
Content="Abbruch"
|
||||
MinWidth="75"
|
||||
Click="BtnCancel_Click"
|
||||
Margin="5 5 " />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<StatusBar Grid.Row="2">
|
||||
<StatusBarItem HorizontalAlignment="Right">
|
||||
<TextBlock Text="{Binding CurrentTime}" />
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
</Grid>
|
||||
</Window>
|
||||
81
FSI.Lib/FSI.Lib/Guis/AutoPw/FrmMain.xaml.cs
Normal file
81
FSI.Lib/FSI.Lib/Guis/AutoPw/FrmMain.xaml.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace FSI.Lib.Guis.AutoPw
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für FrmMain.xaml
|
||||
/// </summary>
|
||||
public partial class FrmMain : Window
|
||||
{
|
||||
public bool CloseAtLostFocus { get; set; }
|
||||
public bool PwOk { get; set; }
|
||||
public FrmMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
BtnOk.IsEnabled = false;
|
||||
Deactivated += FrmMain_Deactivated;
|
||||
DataContext = new MVVM.ViewModel.CurrentTimeViewModel();
|
||||
}
|
||||
|
||||
private void FrmMain_Deactivated(object sender, System.EventArgs e)
|
||||
{
|
||||
if (CloseAtLostFocus)
|
||||
Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void BtnOk_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void BtnCancel_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
PwOk = false;
|
||||
}
|
||||
|
||||
|
||||
private void TbPw_PasswordChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
if (((PasswordBox)sender).Password.Equals(DateTime.Now.ToString("yyyyMMdd")))
|
||||
{
|
||||
BtnOk.IsEnabled = true;
|
||||
PwOk = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BtnOk.IsEnabled = false;
|
||||
PwOk = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void TbPw_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (BtnOk.IsEnabled == true)
|
||||
{
|
||||
Close();
|
||||
PwOk = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
PwOk = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
55
FSI.Lib/FSI.Lib/Guis/DeEncryptMessage/FrmMain.xaml
Normal file
55
FSI.Lib/FSI.Lib/Guis/DeEncryptMessage/FrmMain.xaml
Normal file
@@ -0,0 +1,55 @@
|
||||
<Window x:Class="FSI.Lib.Guis.DeEncryptMessage.FrmMain"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:FSI.Lib.Guis.DeEncryptMessage"
|
||||
mc:Ignorable="d"
|
||||
Title="FSI Message Ent-/Verschlüsseln"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Height="Auto"
|
||||
Width="Auto"
|
||||
Icon="../../Icons/FondiumU.ico">
|
||||
|
||||
<Grid MinWidth="300">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition MinHeight="100" />
|
||||
<RowDefinition MinHeight="100" />
|
||||
<RowDefinition MaxHeight="30"
|
||||
Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBox x:Name="tbInput"
|
||||
TextWrapping="Wrap"
|
||||
AcceptsReturn="True"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
|
||||
<TextBox x:Name="tboutput"
|
||||
Grid.Row="1"
|
||||
AcceptsReturn="True"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Grid.Row="2">
|
||||
<Button x:Name="btnCrypt"
|
||||
Content="verschlüsseln"
|
||||
Margin="5 5 5 5 "
|
||||
Click="btnCrypt_Click" />
|
||||
<Button x:Name="btnDeCrypt"
|
||||
Content="entschlüsseln"
|
||||
Margin="5 5 5 5 "
|
||||
Click="btnDeCrypt_Click" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<StatusBar Grid.Row="3">
|
||||
<StatusBarItem HorizontalAlignment="Right">
|
||||
<TextBlock Text="{Binding CurrentTime}" />
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
61
FSI.Lib/FSI.Lib/Guis/DeEncryptMessage/FrmMain.xaml.cs
Normal file
61
FSI.Lib/FSI.Lib/Guis/DeEncryptMessage/FrmMain.xaml.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace FSI.Lib.Guis.DeEncryptMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für FrmMain.xaml
|
||||
/// </summary>
|
||||
public partial class FrmMain : Window
|
||||
{
|
||||
public string Password { get; set; }
|
||||
public bool CloseAtLostFocus { get; set; }
|
||||
public FrmMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
Deactivated += FrmMain_Deactivated;
|
||||
DataContext = new MVVM.ViewModel.CurrentTimeViewModel();
|
||||
}
|
||||
|
||||
private void FrmMain_Deactivated(object sender, System.EventArgs e)
|
||||
{
|
||||
if (CloseAtLostFocus)
|
||||
Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void btnDeCrypt_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
tboutput.Text = DeEncryptString.DeEncrypt.DecryptString(tbInput.Text, Password);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
MessageBox.Show("Text kann nicht entschlüsselt werden!", "Achtung", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void btnCrypt_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
tboutput.Text = DeEncryptString.DeEncrypt.CryptString(tbInput.Text, Password);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
MessageBox.Show("Text kann nicht verschlüsselt werden!", "Achtung", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
FSI.Lib/FSI.Lib/Guis/Pdf.Mgt/Cmds.cs
Normal file
116
FSI.Lib/FSI.Lib/Guis/Pdf.Mgt/Cmds.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FSI.Lib.Guis.Pdf.Mgt
|
||||
{
|
||||
public class Cmds
|
||||
{
|
||||
public static Task DelDirectoriesAsync(string path)
|
||||
{
|
||||
return Task.Factory.StartNew(() =>
|
||||
{
|
||||
Action<string> DelPath = null;
|
||||
DelPath = p =>
|
||||
{
|
||||
Directory.EnumerateFiles(p).ToList().ForEach(System.IO.File.Delete); // Dateien im Verzeichnis löschen
|
||||
Directory.EnumerateDirectories(p).ToList().ForEach(DelPath);
|
||||
Directory.EnumerateDirectories(p).ToList().ForEach(Directory.Delete); // Verzeichnis löschen
|
||||
};
|
||||
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
string[] directories = Directory.GetDirectories(path); // Alle Unterverzeichniss auslesen
|
||||
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
if (!(directory.Replace(path, "")).StartsWith(".")) // Überprüfen ob Verzeichnis mit "." startet
|
||||
{
|
||||
DelPath(directory); // Unterverzeichnisse inkl. Dateien löschen
|
||||
Directory.Delete(directory); // Verzeichnis löschen
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Task DelFilesAsync(string path)
|
||||
{
|
||||
return Task.Factory.StartNew(() =>
|
||||
{
|
||||
var files = Directory.GetFiles(path);
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(file);
|
||||
|
||||
const int STR_LENGTH = 27; // min. Dateinamen Länge (Zahlen inkl. Bindestriche)
|
||||
|
||||
if (!fileInfo.Name.StartsWith(".")) // Überprüfen ob Datei mit "." startet
|
||||
{
|
||||
if (fileInfo.Extension != ".pdf" || fileInfo.Name.Length <= STR_LENGTH) // Überprüfen ob es sich um eine PDF-Datei handelt
|
||||
{
|
||||
System.IO.File.Delete(fileInfo.FullName); // ... wenn nicht Datei löschen
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] fileStrings = fileInfo.Name.Substring(0, STR_LENGTH - 1).Split('-'); // Zahlenblock splitten für Überprüfung
|
||||
|
||||
if (fileStrings.Length == 3) // 3 Zahlenblöcke vorhanden?
|
||||
{
|
||||
if (fileStrings[0].Length != 10 || !Int64.TryParse(fileStrings[0], out _) || fileStrings[1].Length != 10 || !Int64.TryParse(fileStrings[1], out _) || fileStrings[2].Length != 4 || !Int64.TryParse(fileStrings[2], out _)) // Länge der Zahlenblöcke überprüfen
|
||||
{
|
||||
System.IO.File.Delete(fileInfo.FullName); // ..., wenn Länge nicht passt, Datei löschen
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.IO.File.Delete(fileInfo.FullName); // ..., wenn nicht Datei löschen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Task CreatePdfShortcutsAsync(string path)
|
||||
{
|
||||
return Task.Factory.StartNew(() =>
|
||||
{
|
||||
var files = Directory.GetFiles(path, "*.pdf"); // alle PDF-Dateien einlesen
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(file);
|
||||
|
||||
string[] fileStrings = System.IO.Path.GetFileNameWithoutExtension(fileInfo.Name).Split(' '); // Datei-Namen für Verzeichnis Bezeichnung aufteilen
|
||||
|
||||
string tmpPath = path + fileStrings[1] + " " + fileStrings[2]; // Verzeichnis Bezeichnung zusammenstellen
|
||||
|
||||
if (Convert.ToBoolean(ConfigurationManager.AppSettings["SubDir"])) // mit/ohne Unterverzeichnis
|
||||
{
|
||||
tmpPath = path + fileStrings[1] + @"\" + fileStrings[2]; // mit Unterverzeichnis
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpPath = path + fileStrings[1] + " " + fileStrings[2]; // ohne Unterverzeichnis
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(tmpPath); // Verzeichnis erstellen
|
||||
|
||||
// Shortcut erstellen
|
||||
if (Convert.ToBoolean(ConfigurationManager.AppSettings["WithNo"]))
|
||||
{
|
||||
LnkParser.ShortCut.Create(System.IO.Path.GetFileNameWithoutExtension(tmpPath + "\\" + fileInfo.Name), tmpPath, fileInfo.FullName, System.IO.Path.GetFileNameWithoutExtension(fileInfo.FullName));
|
||||
}
|
||||
else
|
||||
{
|
||||
LnkParser.ShortCut.Create(System.IO.Path.GetFileNameWithoutExtension(fileInfo.Name.Replace(fileStrings[0], "")), tmpPath, fileInfo.FullName, System.IO.Path.GetFileNameWithoutExtension(fileInfo.FullName));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
68
FSI.Lib/FSI.Lib/Guis/Pdf.Mgt/FrmMain.xaml
Normal file
68
FSI.Lib/FSI.Lib/Guis/Pdf.Mgt/FrmMain.xaml
Normal file
@@ -0,0 +1,68 @@
|
||||
<Window x:Class="FSI.Lib.Guis.Pdf.Mgt.FrmMain"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:FSI.Lib.Guis.Pdf.Mgt"
|
||||
mc:Ignorable="d"
|
||||
Title="FSI Eplan PDF Mgt"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Height="Auto"
|
||||
Width="Auto"
|
||||
Icon="../../Icons/FondiumU.ico"
|
||||
WindowStyle="ToolWindow">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition MaxHeight="30"
|
||||
Height="*" />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button x:Name="btnCleanUp"
|
||||
Content="aufräumen"
|
||||
Margin="5 5 5 5 "
|
||||
Click="btnCleanUp_Click" />
|
||||
<Button x:Name="btnCreateShortcuts"
|
||||
Content="Verknüpfungen erstellen"
|
||||
Margin="5 5 5 5 "
|
||||
Click="btnCreateShortcuts_Click" />
|
||||
<Button x:Name="btnStart"
|
||||
Content="alles ausführen"
|
||||
Margin="5 5 5 5 "
|
||||
Click="btnStart_Click" />
|
||||
</StackPanel>
|
||||
<StatusBar Grid.Row="2">
|
||||
<StatusBar.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="4*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
|
||||
</Grid.ColumnDefinitions>
|
||||
</Grid>
|
||||
</ItemsPanelTemplate>
|
||||
</StatusBar.ItemsPanel>
|
||||
<StatusBarItem>
|
||||
<TextBlock x:Name="tbStatus" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem Grid.Column="1">
|
||||
<ProgressBar x:Name="pgProgress"
|
||||
Width="80"
|
||||
Height="18" />
|
||||
</StatusBarItem>
|
||||
|
||||
|
||||
<StatusBarItem HorizontalAlignment="Right">
|
||||
<TextBlock Text="{Binding CurrentTime}" />
|
||||
</StatusBarItem>
|
||||
|
||||
|
||||
</StatusBar>
|
||||
</Grid>
|
||||
</Window>
|
||||
71
FSI.Lib/FSI.Lib/Guis/Pdf.Mgt/FrmMain.xaml.cs
Normal file
71
FSI.Lib/FSI.Lib/Guis/Pdf.Mgt/FrmMain.xaml.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System.Configuration;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
|
||||
namespace FSI.Lib.Guis.Pdf.Mgt
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für FrmMain.xaml
|
||||
/// </summary>
|
||||
public partial class FrmMain : Window
|
||||
{
|
||||
public bool CloseAtLostFocus { get; set; }
|
||||
|
||||
public FrmMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new MVVM.ViewModel.CurrentTimeViewModel();
|
||||
Title += " v" + Assembly.GetExecutingAssembly().GetName().Version; // Version in Titel eintragen
|
||||
Deactivated += FrmMain_Deactivated;
|
||||
}
|
||||
|
||||
private void FrmMain_Deactivated(object sender, System.EventArgs e)
|
||||
{
|
||||
if (CloseAtLostFocus)
|
||||
Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private async void btnCleanUp_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
BtnMgt(false); // Schaltflächen sperren
|
||||
|
||||
await Cmds.DelDirectoriesAsync(ConfigurationManager.AppSettings["PdfPath"]); // nicht benötigte/zulässige Verzeichnisse löschen
|
||||
await Cmds.DelFilesAsync(ConfigurationManager.AppSettings["PdfPath"]); // nicht benötigte/zulässige Datien löschen
|
||||
BtnMgt(true); // Schaltflächen freigeben
|
||||
}
|
||||
|
||||
private async void btnCreateShortcuts_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
BtnMgt(false); // Schaltflächen sperren
|
||||
await Cmds.CreatePdfShortcutsAsync(ConfigurationManager.AppSettings["PdfPath"]); // Verzeichnisstruktur und Verknüpfungen erstellen
|
||||
BtnMgt(true); // Schaltflächen freigeben
|
||||
}
|
||||
|
||||
private async void btnStart_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
BtnMgt(false); // Schaltflächen sperren
|
||||
await Cmds.DelDirectoriesAsync(ConfigurationManager.AppSettings["PdfPath"]); // nicht benötigte/zulässige Verzeichnisse löschen
|
||||
await Cmds.DelFilesAsync(ConfigurationManager.AppSettings["PdfPath"]); // nicht benötigte/zulässige Datien lösche
|
||||
await Cmds.CreatePdfShortcutsAsync(ConfigurationManager.AppSettings["PdfPath"]); // Verzeichnisstruktur und Verknüpfungen erstellen
|
||||
BtnMgt(true); // Schaltflächen freigeben
|
||||
}
|
||||
|
||||
private void BtnMgt(bool enable)
|
||||
{
|
||||
btnCleanUp.IsEnabled =
|
||||
btnCreateShortcuts.IsEnabled =
|
||||
btnStart.IsEnabled = enable;
|
||||
pgProgress.IsIndeterminate = !enable;
|
||||
|
||||
// Status anzeige
|
||||
if (enable)
|
||||
{
|
||||
tbStatus.Text = "beendet";
|
||||
}
|
||||
else
|
||||
{
|
||||
tbStatus.Text = "gestartet";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
185
FSI.Lib/FSI.Lib/Guis/Prj.Mgt/FrmMain.xaml
Normal file
185
FSI.Lib/FSI.Lib/Guis/Prj.Mgt/FrmMain.xaml
Normal file
@@ -0,0 +1,185 @@
|
||||
<Window x:Class="FSI.Lib.Guis.Prj.Mgt.FrmMain"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
|
||||
xmlns:local="clr-namespace:FSI.Lib.Guis.Prj.Mgt"
|
||||
xmlns:control="clr-namespace:FSI.Lib.Wpf.Ctrls.FilterDataGrid"
|
||||
xmlns:viewmodel="clr-namespace:FSI.Lib.Guis.Prj.Mgt.ViewModel"
|
||||
d:DataContext="{d:DesignInstance Type=viewmodel:ViewModelPrj}"
|
||||
mc:Ignorable="d"
|
||||
SizeToContent="Width"
|
||||
Height="800"
|
||||
Width="Auto"
|
||||
Icon="../../Icons/FondiumU.ico">
|
||||
|
||||
<Window.Resources>
|
||||
<ObjectDataProvider x:Key="PrjsFiltered"></ObjectDataProvider>
|
||||
</Window.Resources>
|
||||
|
||||
<Window.InputBindings>
|
||||
<KeyBinding Command="{Binding CmdOpen}"
|
||||
Gesture="CTRL+o" />
|
||||
</Window.InputBindings>
|
||||
|
||||
<Grid FocusManager.FocusedElement="{Binding ElementName=tbSearch}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0"
|
||||
Margin="0,10"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Horizontal">
|
||||
<Label Margin="0,0,20,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="Suche:"
|
||||
FontWeight="Bold" />
|
||||
<TextBox Name="tbSearch"
|
||||
Height="26"
|
||||
MinWidth="200"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding Search, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
TextChanged="tbSearch_TextChanged" />
|
||||
<Button Width="Auto"
|
||||
Margin="5,0,0,0"
|
||||
Padding="4"
|
||||
Command="{Binding RefreshCommand}"
|
||||
ToolTip="Filter löschen"
|
||||
Cursor="Hand">
|
||||
<Image Source="../../Icons/Cross.png"
|
||||
Height="14" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button Width="Auto"
|
||||
Margin="0 0 20 0"
|
||||
Padding="4"
|
||||
ToolTip="öffen"
|
||||
Command="{Binding CmdOpen}"
|
||||
IsEnabled="{Binding CanExecuteOpen}"
|
||||
Cursor="Hand">
|
||||
<Image Source="../../Icons/Open.png"
|
||||
Height="14" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<StackPanel Grid.Row="1"
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,5">
|
||||
<Label Margin="0,0,20,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="Quick-Filter:"
|
||||
FontWeight="Bold" />
|
||||
<Button Width="Auto"
|
||||
Margin="5,0,0,0"
|
||||
Padding="4"
|
||||
ToolTip="Filter löschen"
|
||||
Command="{Binding RefreshCommand}"
|
||||
Cursor="Hand">
|
||||
<Image Source="../../Icons/Cross.png"
|
||||
Height="14" />
|
||||
</Button>
|
||||
<Button Content="PL1"
|
||||
Width="Auto"
|
||||
Margin="10,0,0,0"
|
||||
ToolTip="Filter auf PL1"
|
||||
Command="{Binding CmdQuickSearch}"
|
||||
CommandParameter="PL1"
|
||||
FocusManager.FocusedElement="{Binding ElementName=tbSearch}" />
|
||||
<Button Content="PL2"
|
||||
Width="Auto"
|
||||
Margin="10,0,0,0"
|
||||
ToolTip="Filter auf PL2"
|
||||
Command="{Binding CmdQuickSearch}"
|
||||
CommandParameter="PL2"
|
||||
FocusManager.FocusedElement="{Binding ElementName=tbSearch}" />
|
||||
<Button Content="PL3"
|
||||
Width="Auto"
|
||||
Margin="10,0,0,0"
|
||||
ToolTip="Filter auf PL3"
|
||||
Command="{Binding CmdQuickSearch}"
|
||||
CommandParameter="PL3"
|
||||
FocusManager.FocusedElement="{Binding ElementName=tbSearch}" />
|
||||
<Button Content="SMZ"
|
||||
Width="Auto"
|
||||
Margin="10,0,0,0"
|
||||
ToolTip="Filter auf SMZ"
|
||||
Command="{Binding CmdQuickSearch}"
|
||||
CommandParameter="SMZ"
|
||||
FocusManager.FocusedElement="{Binding ElementName=tbSearch}" />
|
||||
</StackPanel>
|
||||
|
||||
<control:FilterDataGrid x:Name="FilterDataGrid"
|
||||
Grid.Row="2"
|
||||
AutoGenerateColumns="False"
|
||||
DateFormatString="d"
|
||||
FilterLanguage="German"
|
||||
ItemsSource="{Binding PrjsFiltered, UpdateSourceTrigger=PropertyChanged}"
|
||||
SelectionMode="Single"
|
||||
SelectedItem="{Binding SeletctedPrj, UpdateSourceTrigger=PropertyChanged}"
|
||||
ShowElapsedTime="false"
|
||||
ShowRowsCount="True"
|
||||
ShowStatusBar="True">
|
||||
|
||||
<control:FilterDataGrid.InputBindings>
|
||||
<MouseBinding MouseAction="LeftDoubleClick"
|
||||
Command="{Binding CmdOpen}" />
|
||||
|
||||
</control:FilterDataGrid.InputBindings>
|
||||
<control:FilterDataGrid.Columns>
|
||||
|
||||
<control:DataGridTemplateColumn FieldName="PlantNo"
|
||||
Header="Anlagen-Nr."
|
||||
IsColumnFiltered="True"
|
||||
SortMemberPath="PlantNo">
|
||||
<control:DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate DataType="local:Prj">
|
||||
<TextBlock Text="{Binding PlantNo}" />
|
||||
</DataTemplate>
|
||||
</control:DataGridTemplateColumn.CellTemplate>
|
||||
</control:DataGridTemplateColumn>
|
||||
|
||||
<control:DataGridTextColumn Binding="{Binding SubPlantNo}"
|
||||
Header="Teilanlagen-Nr."
|
||||
IsReadOnly="True"
|
||||
IsColumnFiltered="True" />
|
||||
|
||||
<control:DataGridTextColumn Binding="{Binding No, StringFormat={}{0:0000}}"
|
||||
Header="Lfd.-Nr."
|
||||
IsReadOnly="True"
|
||||
IsColumnFiltered="True" />
|
||||
|
||||
<control:DataGridTextColumn Binding="{Binding Plant}"
|
||||
Header="Anlage"
|
||||
IsReadOnly="True"
|
||||
IsColumnFiltered="True" />
|
||||
|
||||
<control:DataGridTextColumn Binding="{Binding SubPlant}"
|
||||
Header="Teilanlage"
|
||||
IsReadOnly="True"
|
||||
IsColumnFiltered="True" />
|
||||
|
||||
<control:DataGridTextColumn Binding="{Binding Description}"
|
||||
Header="Bezeichnung"
|
||||
IsReadOnly="True"
|
||||
IsColumnFiltered="True" />
|
||||
</control:FilterDataGrid.Columns>
|
||||
</control:FilterDataGrid>
|
||||
</Grid>
|
||||
</Window>
|
||||
63
FSI.Lib/FSI.Lib/Guis/Prj.Mgt/FrmMain.xaml.cs
Normal file
63
FSI.Lib/FSI.Lib/Guis/Prj.Mgt/FrmMain.xaml.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using FSI.Lib.Guis.Prj.Mgt.ViewModel;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace FSI.Lib.Guis.Prj.Mgt
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für Main.xaml
|
||||
/// </summary>
|
||||
public partial class FrmMain : Window
|
||||
{
|
||||
public ViewModelPrj Prj { get; set; }
|
||||
public bool ShowPdf { get; set; }
|
||||
public bool CloseAtLostFocus { get; set; }
|
||||
|
||||
public FrmMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Loaded += Main_Loaded;
|
||||
Deactivated += FrmMain_Deactivated;
|
||||
}
|
||||
|
||||
private void FrmMain_Deactivated(object sender, System.EventArgs e)
|
||||
{
|
||||
if (CloseAtLostFocus)
|
||||
Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void Main_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string path;
|
||||
|
||||
if (ShowPdf)
|
||||
{
|
||||
Title = "FSI PDF-Auswahl";
|
||||
path = Settings.Setting<string>("Epl.Pdf.Path");
|
||||
}
|
||||
else
|
||||
{
|
||||
Title = "FSI Epl Projektauswahl";
|
||||
path = Settings.Setting<string>("Epl.Prj.Path");
|
||||
}
|
||||
|
||||
Title += " v" + Assembly.GetExecutingAssembly().GetName().Version; // Version in Titel eintragen
|
||||
|
||||
Prj = new ViewModelPrj(new PrjDataProvider())
|
||||
{
|
||||
DataPath = path,
|
||||
ShowPdf = ShowPdf,
|
||||
};
|
||||
DataContext = Prj;
|
||||
|
||||
Prj.Load();
|
||||
}
|
||||
|
||||
private void tbSearch_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
tbSearch.Select(tbSearch.Text.Length, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
FSI.Lib/FSI.Lib/Guis/Prj.Mgt/Model/Prj.cs
Normal file
25
FSI.Lib/FSI.Lib/Guis/Prj.Mgt/Model/Prj.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FSI.Lib.Guis.Prj.Mgt.Model
|
||||
{
|
||||
public class Prj
|
||||
{
|
||||
public Int64 PlantNo { get; set; }
|
||||
public Int64 SubPlantNo { get; set; }
|
||||
public Int64 No { get; set; }
|
||||
public string Plant { get; set; }
|
||||
public string SubPlant { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string DescriptionDetail { get; set; }
|
||||
public string FullName { get; set; }
|
||||
}
|
||||
|
||||
public interface IPrjDataProvider
|
||||
{
|
||||
IEnumerable<Prj> Load(string path, bool showPdf);
|
||||
}
|
||||
}
|
||||
209
FSI.Lib/FSI.Lib/Guis/Prj.Mgt/ViewModel/ViewModelPrj.cs
Normal file
209
FSI.Lib/FSI.Lib/Guis/Prj.Mgt/ViewModel/ViewModelPrj.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
using FSI.Lib.Guis.Prj.Mgt.Model;
|
||||
using FSI.Lib.MVVM;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace FSI.Lib.Guis.Prj.Mgt.ViewModel
|
||||
{
|
||||
public class ViewModelPrj : MVVM.ViewModelBase
|
||||
{
|
||||
readonly IPrjDataProvider _prjDataProvider;
|
||||
private string _search;
|
||||
private ICollectionView _collView;
|
||||
|
||||
public ICommand RefreshCommand => new DelegateCommand(RefreshData);
|
||||
private ICommand _cmdQuickSearch;
|
||||
private ICommand _cmdOpen;
|
||||
|
||||
public ViewModelPrj(IPrjDataProvider prjDataProvider)
|
||||
{
|
||||
Prjs = new ObservableCollection<Model.Prj>();
|
||||
_prjDataProvider = prjDataProvider;
|
||||
|
||||
_cmdQuickSearch = new RelayCommand<object>(ExecuteQuickSearch, CanExecuteQuickSearch);
|
||||
_cmdOpen = new RelayCommand<object>(ExecuteOpen, CanExecuteOpen);
|
||||
}
|
||||
|
||||
public ObservableCollection<Model.Prj> Prjs { get; }
|
||||
public ObservableCollection<Model.Prj> PrjsFiltered { get; set; }
|
||||
|
||||
public Model.Prj SeletctedPrj { get; set; }
|
||||
|
||||
public string DataPath { get; set; }
|
||||
|
||||
public bool ShowPdf { get; set; }
|
||||
|
||||
public void Load()
|
||||
{
|
||||
var prjs = _prjDataProvider.Load(DataPath, ShowPdf);
|
||||
Prjs.Clear();
|
||||
|
||||
if (prjs != null)
|
||||
{
|
||||
foreach (Model.Prj prj in prjs)
|
||||
{
|
||||
Prjs.Add(prj);
|
||||
}
|
||||
}
|
||||
|
||||
PrjsFiltered = new ObservableCollection<Model.Prj>(Prjs);
|
||||
_collView = CollectionViewSource.GetDefaultView(PrjsFiltered);
|
||||
}
|
||||
|
||||
public string Search
|
||||
{
|
||||
get => _search;
|
||||
set
|
||||
{
|
||||
_search = value;
|
||||
|
||||
_collView.Filter = e =>
|
||||
{
|
||||
var item = (Model.Prj)e;
|
||||
return item != null && ((item.Plant?.StartsWith(_search, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||
|| (item.SubPlant?.StartsWith(_search, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||
#if NET472
|
||||
|| (item.Description?.Contains(_search) ?? false)
|
||||
|| (item.DescriptionDetail?.Contains(_search) ?? false)
|
||||
#elif NET6_0
|
||||
|| (item.Description?.Contains(_search, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||
|| (item.DescriptionDetail?.Contains(_search, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||
#endif
|
||||
);
|
||||
};
|
||||
|
||||
_collView.Refresh();
|
||||
PrjsFiltered = new ObservableCollection<Model.Prj>(_collView.OfType<Model.Prj>().ToList());
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void QuickSearch(string search)
|
||||
{
|
||||
Search = search + " ";
|
||||
}
|
||||
|
||||
private void RefreshData(object obj)
|
||||
{
|
||||
Search = string.Empty;
|
||||
}
|
||||
|
||||
private bool CanExecuteQuickSearch(object obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ExecuteQuickSearch(object obj)
|
||||
{
|
||||
QuickSearch(obj.ToString());
|
||||
}
|
||||
|
||||
public ICommand CmdQuickSearch
|
||||
{
|
||||
get { return _cmdQuickSearch; }
|
||||
set => _cmdQuickSearch = value;
|
||||
}
|
||||
|
||||
private bool CanExecuteOpen(object obj)
|
||||
{
|
||||
if (SeletctedPrj != null)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ExecuteOpen(object obj)
|
||||
{
|
||||
if (ShowPdf)
|
||||
{
|
||||
new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo(SeletctedPrj.FullName)
|
||||
{
|
||||
UseShellExecute = true
|
||||
}
|
||||
}.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
var files = Settings.Setting<string>("Epl.Exe", Settings.Mode.ExeSetttings).Replace(Environment.NewLine, "").Replace("\t", "").Split(";");
|
||||
|
||||
var arguments = " /Variant:\"Electric P8\" ProjectOpen /Project:\"" + SeletctedPrj.FullName + "\"";
|
||||
|
||||
string fileName = string.Empty;
|
||||
string path = string.Empty;
|
||||
|
||||
for (int i = 0; i <= files.Length - 1; i++)
|
||||
{
|
||||
if (File.Exists(files[i].Trim()))
|
||||
{
|
||||
fileName = files[i].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
}
|
||||
}.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand CmdOpen
|
||||
{
|
||||
get { return _cmdOpen; }
|
||||
set => _cmdOpen = value;
|
||||
}
|
||||
}
|
||||
|
||||
public class PrjDataProvider : IPrjDataProvider
|
||||
{
|
||||
public IEnumerable<Model.Prj> Load(string path, bool showPdf)
|
||||
{
|
||||
var prjs = new ObservableCollection<Model.Prj>();
|
||||
string[] files = Directory.GetFiles(path); // alle PDF-Dateien einlesen
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (((file.EndsWith(".elk") || file.EndsWith(".elp") || file.EndsWith(".els") || file.EndsWith(".elx") || file.EndsWith(".elr") || file.EndsWith(".ell") || file.EndsWith(".elf"))
|
||||
&& !showPdf) || (file.EndsWith(".pdf") && showPdf))
|
||||
{
|
||||
Model.Prj prj = new();
|
||||
FileInfo fileInfo = new(file);
|
||||
string[] nameNo = fileInfo.Name[..(27 - 1)].Split('-');
|
||||
|
||||
if (nameNo.Length == 3) // 3 Zahlenblöcke vorhanden?
|
||||
{
|
||||
if (nameNo[0].Length == 10 || Int64.TryParse(nameNo[0], out _) || nameNo[1].Length == 10 || Int64.TryParse(nameNo[1], out _) || nameNo[2].Length == 4 || !Int64.TryParse(nameNo[2], out _)) // Länge der Zahlenblöcke überprüfen
|
||||
{
|
||||
prj.PlantNo = Int64.Parse(nameNo[0]);
|
||||
prj.SubPlantNo = Int64.Parse(nameNo[1]);
|
||||
prj.No = Int64.Parse(nameNo[2]);
|
||||
|
||||
string[] fileStrings = System.IO.Path.GetFileNameWithoutExtension(fileInfo.Name).Split(' ');
|
||||
prj.Plant = fileStrings[1];
|
||||
prj.SubPlant = fileStrings[2];
|
||||
prj.Description = System.IO.Path.GetFileNameWithoutExtension(fileInfo.Name).Replace(nameNo[0] + "-" + nameNo[1] + "-" + nameNo[2] + " " + fileStrings[1] + " " + fileStrings[2], "");
|
||||
prj.Description = prj.Description.Trim();
|
||||
prj.DescriptionDetail = prj.Plant + " " + prj.SubPlant + " " + prj.Description;
|
||||
prj.FullName = fileInfo.FullName;
|
||||
prjs.Add(prj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return prjs;
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
54
FSI.Lib/FSI.Lib/Guis/SieStarterCsvExporter/FrmMain.xaml
Normal file
54
FSI.Lib/FSI.Lib/Guis/SieStarterCsvExporter/FrmMain.xaml
Normal file
@@ -0,0 +1,54 @@
|
||||
<Window x:Class="FSI.Lib.Guis.SieStarterCsvExporter.FrmMain"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Title="FSI Siemens Starter Trace Csv-Exporter"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Height="Auto"
|
||||
Width="Auto"
|
||||
Icon="../../Icons/FondiumU.ico"
|
||||
WindowStyle="ToolWindow">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="Datei:"
|
||||
Margin="5 5 5 5" />
|
||||
<TextBox x:Name="tbSrcFile"
|
||||
Width="600"
|
||||
Margin="5 5 5 5"
|
||||
AllowDrop="True"
|
||||
TextChanged="TbSrcFile_TextChanged"
|
||||
PreviewDragEnter="TbSrcFile_PreviewDragEnter"
|
||||
PreviewDragOver="TbSrcFile_PreviewDragOver"
|
||||
Drop="TbSrcFile_Drop" />
|
||||
|
||||
<Button x:Name="btnSlctSrcFile"
|
||||
Content="..."
|
||||
Width="30"
|
||||
Margin="5 5 5 5"
|
||||
Click="BtnSlctSrcFile_Click" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1">
|
||||
<Button x:Name="btnStart"
|
||||
Content="Start"
|
||||
Margin="5 5 5 5"
|
||||
IsEnabled="False"
|
||||
Click="BtnStart_Click" />
|
||||
</StackPanel>
|
||||
|
||||
<StatusBar Grid.Row="2">
|
||||
<StatusBarItem HorizontalAlignment="Right">
|
||||
<TextBlock Text="{Binding CurrentTime}" />
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
116
FSI.Lib/FSI.Lib/Guis/SieStarterCsvExporter/FrmMain.xaml.cs
Normal file
116
FSI.Lib/FSI.Lib/Guis/SieStarterCsvExporter/FrmMain.xaml.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using Microsoft.Win32;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace FSI.Lib.Guis.SieStarterCsvExporter
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für frmMain.xaml
|
||||
/// </summary>
|
||||
public partial class FrmMain : Window
|
||||
{
|
||||
public FrmMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new MVVM.ViewModel.CurrentTimeViewModel();
|
||||
}
|
||||
private void BtnSlctSrcFile_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
OpenFileDialog dlg = new()
|
||||
{
|
||||
Filter = "Trace (*.trc)|*.trc|alle Dateien (*:*)|*.*"
|
||||
};
|
||||
|
||||
if ((bool)dlg.ShowDialog())
|
||||
{
|
||||
tbSrcFile.Text = dlg.FileName;
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnStart_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string[] tbEntries = tbSrcFile.Text.Split("\n");
|
||||
|
||||
string test = GetType().Namespace;
|
||||
|
||||
var test2 = Assembly.GetExecutingAssembly;
|
||||
|
||||
|
||||
foreach (string tbEntry in tbEntries)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tbEntry))
|
||||
{
|
||||
Process process= new Process();
|
||||
process.StartInfo.FileName = Directory.GetCurrentDirectory() + @"\Guis\SieStarterCsvExporter\" + "Convert_SINAMICS_trace_CSV.exe";
|
||||
process.StartInfo.Arguments = "\"" + tbEntry + "\"";
|
||||
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
tbSrcFile.Text = string.Empty;
|
||||
}
|
||||
|
||||
private void TbSrcFile_PreviewDragEnter(object sender, System.Windows.DragEventArgs e)
|
||||
{
|
||||
if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop))
|
||||
{
|
||||
e.Effects = System.Windows.DragDropEffects.Copy;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Effects = System.Windows.DragDropEffects.None;
|
||||
}
|
||||
}
|
||||
|
||||
private void TbSrcFile_PreviewDragOver(object sender, System.Windows.DragEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void TbSrcFile_Drop(object sender, System.Windows.DragEventArgs e)
|
||||
{
|
||||
// Get data object
|
||||
var dataObject = e.Data as System.Windows.DataObject;
|
||||
|
||||
// Check for file list
|
||||
if (dataObject.ContainsFileDropList())
|
||||
{
|
||||
// Clear values
|
||||
tbSrcFile.Text = string.Empty;
|
||||
|
||||
// Process file names
|
||||
StringCollection fileNames = dataObject.GetFileDropList();
|
||||
StringBuilder bd = new();
|
||||
foreach (string fileName in fileNames)
|
||||
{
|
||||
if (fileName.EndsWith(".trc"))
|
||||
{
|
||||
bd.Append(fileName + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Set text
|
||||
tbSrcFile.Text = bd.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private void TbSrcFile_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tbSrcFile.Text))
|
||||
{
|
||||
btnStart.IsEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
btnStart.IsEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
FSI.Lib/FSI.Lib/Guis/SieTiaWinCCMsgMgt/FrmMain.xaml
Normal file
59
FSI.Lib/FSI.Lib/Guis/SieTiaWinCCMsgMgt/FrmMain.xaml
Normal file
@@ -0,0 +1,59 @@
|
||||
<Window x:Class="FSI.Lib.Guis.SieTiaWinCCMsgMgt.FrmMain"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:FSI.Lib.Guis.SieTiaWinCCMsgMgt"
|
||||
mc:Ignorable="d"
|
||||
Title="FSI WinCC Mgt"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Height="Auto"
|
||||
Width="Auto"
|
||||
MinWidth="200"
|
||||
Icon="../../Icons/FondiumU.ico"
|
||||
WindowStyle="ToolWindow">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition MaxHeight="30"
|
||||
Height="*" />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button x:Name="btnStart"
|
||||
Content="Start"
|
||||
Margin="5 5 5 5 "
|
||||
Click="btnStart_Click" />
|
||||
<Button x:Name="btnStop"
|
||||
Content="Stop"
|
||||
Margin="5 5 5 5 "
|
||||
Click="btnStop_Click" />
|
||||
</StackPanel>
|
||||
|
||||
<StatusBar Grid.Row="2">
|
||||
<StatusBar.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="4*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
|
||||
</Grid.ColumnDefinitions>
|
||||
</Grid>
|
||||
</ItemsPanelTemplate>
|
||||
</StatusBar.ItemsPanel>
|
||||
<StatusBarItem>
|
||||
<TextBlock x:Name="tbStatus" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem Grid.Column="1">
|
||||
<ProgressBar x:Name="pgProgress"
|
||||
Width="80"
|
||||
Height="18" />
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
57
FSI.Lib/FSI.Lib/Guis/SieTiaWinCCMsgMgt/FrmMain.xaml.cs
Normal file
57
FSI.Lib/FSI.Lib/Guis/SieTiaWinCCMsgMgt/FrmMain.xaml.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace FSI.Lib.Guis.SieTiaWinCCMsgMgt
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für FrmMain.xaml
|
||||
/// </summary>
|
||||
public partial class FrmMain : Window
|
||||
{
|
||||
public WinCC WinCC { get; set; }
|
||||
|
||||
public FrmMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void btnStart_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WinCC.Start();
|
||||
CtrlMgt();
|
||||
}
|
||||
|
||||
private void btnStop_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WinCC.Stop();
|
||||
CtrlMgt();
|
||||
}
|
||||
|
||||
private void CtrlMgt()
|
||||
{
|
||||
if (WinCC.Status)
|
||||
{
|
||||
btnStart.IsEnabled = false;
|
||||
btnStop.IsEnabled = true;
|
||||
pgProgress.IsIndeterminate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
btnStart.IsEnabled = true;
|
||||
btnStop.IsEnabled = false;
|
||||
pgProgress.IsIndeterminate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
172
FSI.Lib/FSI.Lib/Guis/SieTiaWinCCMsgMgt/WinCC.cs
Normal file
172
FSI.Lib/FSI.Lib/Guis/SieTiaWinCCMsgMgt/WinCC.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FSI.Lib.Guis.SieTiaWinCCMsgMgt
|
||||
{
|
||||
public class WinCC
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern IntPtr PostMessage(IntPtr hwndParent, int msg, int wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
static extern bool IsWindowVisible(IntPtr hWnd);
|
||||
|
||||
const int BM_CLICK = 0x00F5; //message for Click which is a constant
|
||||
const int WM_LBUTTONDOWN = 0x0201; //message for Mouse down
|
||||
const int WM_LBUTTONUP = 0x0202; // message for Mouse up
|
||||
|
||||
private CancellationTokenSource tokenSource = null;
|
||||
private CancellationToken token;
|
||||
private Task task = null;
|
||||
|
||||
private BackgroundWorker backgroundWorker;
|
||||
|
||||
|
||||
public bool AutoStart { get; set; }
|
||||
public int UpdateIntervall { get; set; }
|
||||
public string WindowsName { get; set; }
|
||||
public string WindowsClassName { get; set; }
|
||||
public string ButtonName { get; set; }
|
||||
|
||||
public WinCC()
|
||||
{
|
||||
backgroundWorker = new BackgroundWorker
|
||||
{
|
||||
WorkerReportsProgress = true,
|
||||
WorkerSupportsCancellation = true
|
||||
};
|
||||
backgroundWorker.DoWork += BackgroundWorker_DoWork;
|
||||
backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged;
|
||||
|
||||
if (AutoStart)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
|
||||
{
|
||||
BackgroundWorker worker = sender as BackgroundWorker;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (worker.CancellationPending == true)
|
||||
{
|
||||
e.Cancel = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Perform a time consuming operation and report progress.
|
||||
System.Threading.Thread.Sleep(UpdateIntervall);
|
||||
|
||||
// Find windos by Name
|
||||
var windowHandle = FindWindow(WindowsClassName, WindowsName);
|
||||
|
||||
if (windowHandle != IntPtr.Zero && IsWindowVisible(windowHandle))
|
||||
{
|
||||
SetForegroundWindow(windowHandle);
|
||||
var btnHandle = FindWindowEx(windowHandle, IntPtr.Zero, null, ButtonName);
|
||||
SendMessage(btnHandle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (backgroundWorker.IsBusy != true)
|
||||
{
|
||||
backgroundWorker.RunWorkerAsync();
|
||||
}
|
||||
Status = true;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (backgroundWorker.WorkerSupportsCancellation == true)
|
||||
{
|
||||
backgroundWorker.CancelAsync();
|
||||
}
|
||||
Status = false;
|
||||
}
|
||||
|
||||
public bool Status { get; set; }
|
||||
|
||||
private void WinCCMsgMgt()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
//MessageBox.Show("13456");
|
||||
Thread.Sleep(5000);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
bool disposedValue = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
tokenSource.Cancel();
|
||||
task.Wait();
|
||||
tokenSource.Dispose();
|
||||
task.Dispose();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
tokenSource = null;
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
16
FSI.Lib/FSI.Lib/Helpers/IdentityHelpers.cs
Normal file
16
FSI.Lib/FSI.Lib/Helpers/IdentityHelpers.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace FSI.Lib.Helpers
|
||||
{
|
||||
public static class IdentityHelpers
|
||||
{
|
||||
public static string ShortName(this WindowsIdentity Identity)
|
||||
{
|
||||
if (null != Identity)
|
||||
{
|
||||
return Identity.Name.Split(new char[] { '\\' })[1];
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
FSI.Lib/FSI.Lib/Icons/Cross.png
Normal file
BIN
FSI.Lib/FSI.Lib/Icons/Cross.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
FSI.Lib/FSI.Lib/Icons/FondiumU.ico
Normal file
BIN
FSI.Lib/FSI.Lib/Icons/FondiumU.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
BIN
FSI.Lib/FSI.Lib/Icons/Open.png
Normal file
BIN
FSI.Lib/FSI.Lib/Icons/Open.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
57
FSI.Lib/FSI.Lib/LnkParser/ShortCut.cs
Normal file
57
FSI.Lib/FSI.Lib/LnkParser/ShortCut.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
|
||||
namespace FSI.Lib.LnkParser
|
||||
{
|
||||
public static class ShortCut
|
||||
{
|
||||
public static void Create(string shortcutName, string shortcutPath, string targetPath, string descripton)
|
||||
{
|
||||
IShellLink link = (IShellLink)new ShellLink();
|
||||
|
||||
// setup shortcut information
|
||||
link.SetPath(targetPath);
|
||||
link.SetDescription(descripton);
|
||||
|
||||
// save it
|
||||
IPersistFile file = (IPersistFile)link;
|
||||
file.Save(Path.Combine(shortcutPath, shortcutName) + ".lnk", false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("00021401-0000-0000-C000-000000000046")]
|
||||
internal class ShellLink
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[Guid("000214F9-0000-0000-C000-000000000046")]
|
||||
internal interface IShellLink
|
||||
{
|
||||
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags);
|
||||
void GetIDList(out IntPtr ppidl);
|
||||
void SetIDList(IntPtr pidl);
|
||||
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
|
||||
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
|
||||
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
|
||||
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
|
||||
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
|
||||
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
|
||||
void GetHotkey(out short pwHotkey);
|
||||
void SetHotkey(short wHotkey);
|
||||
void GetShowCmd(out int piShowCmd);
|
||||
void SetShowCmd(int iShowCmd);
|
||||
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
|
||||
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
|
||||
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
|
||||
void Resolve(IntPtr hwnd, int fFlags);
|
||||
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
|
||||
}
|
||||
}
|
||||
|
||||
43
FSI.Lib/FSI.Lib/MVVM/DelegateCommand.cs
Normal file
43
FSI.Lib/FSI.Lib/MVVM/DelegateCommand.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace FSI.Lib.MVVM
|
||||
{
|
||||
/// <summary>
|
||||
/// DelegateCommand borrowed from
|
||||
/// http://www.wpftutorial.net/DelegateCommand.html
|
||||
/// </summary>
|
||||
public class DelegateCommand : ICommand
|
||||
{
|
||||
private readonly Predicate<object> _canExecute;
|
||||
private readonly Action<object> _execute;
|
||||
|
||||
public DelegateCommand(Action<object> execute,
|
||||
Predicate<object> canExecute = null)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#region ICommand Members
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
public bool CanExecute(object parameter)
|
||||
{
|
||||
return _canExecute == null || _canExecute(parameter);
|
||||
}
|
||||
|
||||
public void Execute(object parameter)
|
||||
{
|
||||
_execute(parameter);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
77
FSI.Lib/FSI.Lib/MVVM/RelayCommand.cs
Normal file
77
FSI.Lib/FSI.Lib/MVVM/RelayCommand.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace FSI.Lib.MVVM
|
||||
{
|
||||
public class RelayCommand<T> : ICommand
|
||||
{
|
||||
#region Fields
|
||||
|
||||
readonly Action<T> _execute = null;
|
||||
readonly Predicate<T> _canExecute = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="execute">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
|
||||
/// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
|
||||
public RelayCommand(Action<T> execute)
|
||||
: this(execute, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new command.
|
||||
/// </summary>
|
||||
/// <param name="execute">The execution logic.</param>
|
||||
/// <param name="canExecute">The execution status logic.</param>
|
||||
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
|
||||
{
|
||||
if (execute == null)
|
||||
throw new ArgumentNullException("execute");
|
||||
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICommand Members
|
||||
|
||||
///<summary>
|
||||
///Defines the method that determines whether the command can execute in its current state.
|
||||
///</summary>
|
||||
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
|
||||
///<returns>
|
||||
///true if this command can be executed; otherwise, false.
|
||||
///</returns>
|
||||
public bool CanExecute(object parameter)
|
||||
{
|
||||
return _canExecute == null ? true : _canExecute((T)parameter);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Occurs when changes occur that affect whether or not the command should execute.
|
||||
///</summary>
|
||||
public event EventHandler CanExecuteChanged
|
||||
{
|
||||
add { CommandManager.RequerySuggested += value; }
|
||||
remove { CommandManager.RequerySuggested -= value; }
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Defines the method to be called when the command is invoked.
|
||||
///</summary>
|
||||
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param>
|
||||
public void Execute(object parameter)
|
||||
{
|
||||
_execute((T)parameter);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
40
FSI.Lib/FSI.Lib/MVVM/ViewModel/CurrentTimeViewModel.cs
Normal file
40
FSI.Lib/FSI.Lib/MVVM/ViewModel/CurrentTimeViewModel.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FSI.Lib.MVVM.ViewModel
|
||||
{
|
||||
public class CurrentTimeViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private string _currentTime;
|
||||
|
||||
public CurrentTimeViewModel()
|
||||
{
|
||||
UpdateTime();
|
||||
}
|
||||
|
||||
private async void UpdateTime()
|
||||
{
|
||||
CurrentTime = DateTime.Now.ToString("G");
|
||||
await Task.Delay(1000);
|
||||
UpdateTime();
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public string CurrentTime
|
||||
{
|
||||
get { return _currentTime; }
|
||||
set { _currentTime = value; OnPropertyChanged(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
61
FSI.Lib/FSI.Lib/MVVM/ViewModelBase.cs
Normal file
61
FSI.Lib/FSI.Lib/MVVM/ViewModelBase.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
/* Example for use:
|
||||
|
||||
public class MyViewModel : ViewModelBase
|
||||
{
|
||||
private int myProperty;
|
||||
public int MyProperty
|
||||
{
|
||||
get { return myProperty; }
|
||||
set { SetProperty(ref myProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
namespace FSI.Lib.MVVM
|
||||
{
|
||||
public class ViewModelBase : INotifyPropertyChanged
|
||||
{
|
||||
/// <summary>
|
||||
/// Multicast event for property change notifications.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a property already matches the desired value. Sets the property and
|
||||
/// notifies listeners only when necessary.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the property.</typeparam>
|
||||
/// <param name="storage">Reference to a property with both getter and setter.</param>
|
||||
/// <param name="value">Desired value for the property.</param>
|
||||
/// <param name="propertyName">Name of the property used to notify listeners.This
|
||||
/// value is optional and can be provided automatically when invoked from compilers that
|
||||
/// support CallerMemberName.</param>
|
||||
/// <returns>True if the value was changed, false if the existing value matched the
|
||||
/// desired value.</returns>
|
||||
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (object.Equals(storage, value)) return false;
|
||||
storage = value;
|
||||
// Log.DebugFormat("{0}.{1} = {2}", this.GetType().Name, propertyName, storage);
|
||||
this.OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Notifies listeners that a property value has changed.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of the property used to notify listeners. This
|
||||
/// value is optional and can be provided automatically when invoked from compilers
|
||||
/// that support <see cref="CallerMemberNameAttribute"/>.</param>
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
73
FSI.Lib/FSI.Lib/Settings.cs
Normal file
73
FSI.Lib/FSI.Lib/Settings.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FSI.Lib
|
||||
{
|
||||
public static class Settings
|
||||
{
|
||||
//static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
|
||||
#if NET472
|
||||
static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().Location);
|
||||
#elif NET6_0
|
||||
static UriBuilder uri = new(Assembly.GetExecutingAssembly().Location);
|
||||
#endif
|
||||
|
||||
static readonly NumberFormatInfo nfi = new NumberFormatInfo()
|
||||
{
|
||||
NumberGroupSeparator = "",
|
||||
CurrencyDecimalSeparator = "."
|
||||
};
|
||||
|
||||
public static T Setting<T>(string name)
|
||||
{
|
||||
return Setting<T>(name, Mode.DllSettings);
|
||||
}
|
||||
|
||||
public static T Setting<T>(string name, Mode exeSettings)
|
||||
{
|
||||
if (exeSettings == Mode.ExeSetttings)
|
||||
{
|
||||
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||
AppSettingsSection appSettingsSection = (AppSettingsSection)configuration.GetSection("appSettings");
|
||||
|
||||
return (T)Convert.ChangeType(appSettingsSection.Settings[name].Value, typeof(T), nfi);
|
||||
}
|
||||
|
||||
if (exeSettings == Mode.DllSettings)
|
||||
{
|
||||
Configuration configuration = ConfigurationManager.OpenExeConfiguration(uri.Path);
|
||||
AppSettingsSection appSettingsSection = (AppSettingsSection)configuration.GetSection("appSettings");
|
||||
return (T)Convert.ChangeType(appSettingsSection.Settings[name].Value, typeof(T), nfi);
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(null, typeof(T), nfi);
|
||||
}
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
ExeSetttings,
|
||||
DllSettings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
App.Config file sample
|
||||
|
||||
<add key="Enabled" value="true" />
|
||||
<add key="ExportPath" value="c:\" />
|
||||
<add key="Seconds" value="25" />
|
||||
<add key="Ratio" value="0.14" />
|
||||
|
||||
Usage:
|
||||
|
||||
somebooleanvar = Settings.Setting<bool>("Enabled");
|
||||
somestringlvar = Settings.Setting<string>("ExportPath");
|
||||
someintvar = Settings.Setting<int>("Seconds");
|
||||
somedoublevar = Settings.Setting<double>("Ratio");
|
||||
|
||||
*/
|
||||
16
FSI.Lib/FSI.Lib/TimeStamp.cs
Normal file
16
FSI.Lib/FSI.Lib/TimeStamp.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FSI.Lib
|
||||
{
|
||||
public static class TimeStamp
|
||||
{
|
||||
public static string Get(string format)
|
||||
{
|
||||
return DateTime.Now.ToString(format);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
FSI.Lib/FSI.Lib/Wpf/Converter/BooleanConverter.cs
Normal file
27
FSI.Lib/FSI.Lib/Wpf/Converter/BooleanConverter.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FSI.Lib.Wpf.Converter
|
||||
{
|
||||
public class BooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return !((bool)value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
22
FSI.Lib/FSI.Lib/Wpf/Converters/InvertedBoolenConverter .cs
Normal file
22
FSI.Lib/FSI.Lib/Wpf/Converters/InvertedBoolenConverter .cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FSI.Lib.Wpf.Converters
|
||||
{
|
||||
|
||||
public class InvertedBoolenConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return !(bool)value;
|
||||
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (bool)value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
16
FSI.Lib/FSI.Lib/Wpf/Ctrls/ChbWindowsTopMost.xaml
Normal file
16
FSI.Lib/FSI.Lib/Wpf/Ctrls/ChbWindowsTopMost.xaml
Normal file
@@ -0,0 +1,16 @@
|
||||
<UserControl x:Class="FSI.Lib.Wpf.Ctrls.ChbWindowsTopMost"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:FSI.Lib.Wpf.Ctrls"
|
||||
mc:Ignorable="d"
|
||||
Width="Auto"
|
||||
Height="Auto">
|
||||
<StackPanel>
|
||||
<CheckBox Name="chbTopMost"
|
||||
Content="Fenster immer im Vordergrund"
|
||||
Checked="CheckBox_Checked"
|
||||
Unchecked="CheckBox_Unchecked" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
89
FSI.Lib/FSI.Lib/Wpf/Ctrls/ChbWindowsTopMost.xaml.cs
Normal file
89
FSI.Lib/FSI.Lib/Wpf/Ctrls/ChbWindowsTopMost.xaml.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace FSI.Lib.Wpf.Ctrls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für ChbWindowsTopMost.xaml
|
||||
/// </summary>
|
||||
public partial class ChbWindowsTopMost : UserControl
|
||||
{
|
||||
private Window _window;
|
||||
|
||||
//A window receives this message when the user chooses a command from the Window menu, or when the user chooses the maximize button, minimize button, restore button, or close button.
|
||||
public const Int32 WM_SYSCOMMAND = 0x112;
|
||||
|
||||
//Draws a horizontal dividing line.This flag is used only in a drop-down menu, submenu, or shortcut menu.The line cannot be grayed, disabled, or highlighted.
|
||||
public const Int32 MF_SEPARATOR = 0x800;
|
||||
|
||||
//Specifies that an ID is a position index into the menu and not a command ID.
|
||||
public const Int32 MF_BYPOSITION = 0x400;
|
||||
|
||||
//Specifies that the menu item is a text string.
|
||||
public const Int32 MF_STRING = 0x0;
|
||||
|
||||
//Menu Ids for our custom menu items
|
||||
public const Int32 _ItemTopMostId = 1000;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool InsertMenu(IntPtr hMenu, Int32 wPosition, Int32 wFlags, Int32 wIDNewItem, string lpNewItem);
|
||||
|
||||
public ChbWindowsTopMost()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += ChbWindowsTopMost_Loaded;
|
||||
}
|
||||
|
||||
private void ChbWindowsTopMost_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_window = Window.GetWindow(this);
|
||||
|
||||
IntPtr windowhandle = new WindowInteropHelper(_window).Handle;
|
||||
HwndSource hwndSource = HwndSource.FromHwnd(windowhandle);
|
||||
|
||||
//Get the handle for the system menu
|
||||
IntPtr systemMenuHandle = GetSystemMenu(windowhandle, false);
|
||||
|
||||
//Insert our custom menu items
|
||||
InsertMenu(systemMenuHandle, 5, MF_BYPOSITION | MF_SEPARATOR, 0, string.Empty); //Add a menu seperator
|
||||
InsertMenu(systemMenuHandle, 6, MF_BYPOSITION, _ItemTopMostId, "immer im Vordergrund"); //Add a setting menu item
|
||||
|
||||
hwndSource.AddHook(new HwndSourceHook(WndProc));
|
||||
}
|
||||
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
// Check if the SystemCommand message has been executed
|
||||
if (msg == WM_SYSCOMMAND)
|
||||
{
|
||||
//check which menu item was clicked
|
||||
switch (wParam.ToInt32())
|
||||
{
|
||||
case _ItemTopMostId:
|
||||
_window.Topmost = !_window.Topmost;
|
||||
chbTopMost.IsChecked = _window.Topmost;
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
private void CheckBox_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_window.Topmost = true;
|
||||
}
|
||||
|
||||
private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_window.Topmost = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/DataGridColumn.cs
Normal file
78
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/DataGridColumn.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace FSI.Lib.Wpf.Ctrls.FilterDataGrid
|
||||
{
|
||||
public sealed class DataGridTemplateColumn : System.Windows.Controls.DataGridTemplateColumn
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// FieldName Dependency Property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty FieldNameProperty =
|
||||
DependencyProperty.Register("FieldName", typeof(string), typeof(DataGridTemplateColumn),
|
||||
new PropertyMetadata(""));
|
||||
|
||||
/// <summary>
|
||||
/// IsColumnFiltered Dependency Property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsColumnFilteredProperty =
|
||||
DependencyProperty.Register("IsColumnFiltered", typeof(bool), typeof(DataGridTemplateColumn),
|
||||
new PropertyMetadata(false));
|
||||
|
||||
#endregion Public Fields
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string FieldName
|
||||
{
|
||||
get => (string)GetValue(FieldNameProperty);
|
||||
set => SetValue(FieldNameProperty, value);
|
||||
}
|
||||
|
||||
public bool IsColumnFiltered
|
||||
{
|
||||
get => (bool)GetValue(IsColumnFilteredProperty);
|
||||
set => SetValue(IsColumnFilteredProperty, value);
|
||||
}
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
|
||||
public sealed class DataGridTextColumn : System.Windows.Controls.DataGridTextColumn
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// FieldName Dependency Property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty FieldNameProperty =
|
||||
DependencyProperty.Register("FieldName", typeof(string), typeof(DataGridTextColumn),
|
||||
new PropertyMetadata(""));
|
||||
|
||||
/// <summary>
|
||||
/// IsColumnFiltered Dependency Property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsColumnFilteredProperty =
|
||||
DependencyProperty.Register("IsColumnFiltered", typeof(bool), typeof(DataGridTextColumn),
|
||||
new PropertyMetadata(false));
|
||||
|
||||
#endregion Public Fields
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string FieldName
|
||||
{
|
||||
get => (string)GetValue(FieldNameProperty);
|
||||
set => SetValue(FieldNameProperty, value);
|
||||
}
|
||||
|
||||
public bool IsColumnFiltered
|
||||
{
|
||||
get => (bool)GetValue(IsColumnFilteredProperty);
|
||||
set => SetValue(IsColumnFilteredProperty, value);
|
||||
}
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
}
|
||||
319
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterCommon.cs
Normal file
319
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterCommon.cs
Normal file
@@ -0,0 +1,319 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FSI.Lib.Wpf.Ctrls.FilterDataGrid
|
||||
{
|
||||
public sealed class FilterCommon : NotifyProperty
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public FilterCommon()
|
||||
{
|
||||
PreviouslyFilteredItems = new HashSet<object>(EqualityComparer<object>.Default);
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string FieldName { get; set; }
|
||||
public Type FieldType { get; set; }
|
||||
public bool IsFiltered { get; set; }
|
||||
public HashSet<object> PreviouslyFilteredItems { get; set; }
|
||||
|
||||
// Treeview
|
||||
public List<FilterItem> Tree { get; set; }
|
||||
|
||||
public Loc Translate { get; set; }
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Recursive call for check/uncheck all items in tree
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="updateChildren"></param>
|
||||
/// <param name="updateParent"></param>
|
||||
private void SetIsChecked(FilterItem item, bool? state, bool updateChildren, bool updateParent)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (state == item.IsChecked) return;
|
||||
item.SetState = state;
|
||||
|
||||
// select all / unselect all
|
||||
if (item.Level == 0)
|
||||
Tree.Where(t => t.Level != 0).ToList().ForEach(c => { SetIsChecked(c, state, true, true); });
|
||||
|
||||
// update children
|
||||
if (updateChildren && item.IsChecked.HasValue)
|
||||
item.Children?.ForEach(c => { SetIsChecked(c, state, true, false); });
|
||||
|
||||
// update parent
|
||||
if (updateParent && item.Parent != null)
|
||||
VerifyCheckedState(item.Parent);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"FilterCommon.SetState : {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the tree when the state of the IsChecked property changes
|
||||
/// </summary>
|
||||
/// <param name="o">item</param>
|
||||
/// <param name="e">state</param>
|
||||
public void UpdateTree(object o, bool? e)
|
||||
{
|
||||
if (o == null) return;
|
||||
var item = (FilterItem)o;
|
||||
SetIsChecked(item, e, true, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check or uncheck parents or children
|
||||
/// </summary>
|
||||
private void VerifyCheckedState(FilterItem item)
|
||||
{
|
||||
bool? state = null;
|
||||
|
||||
for (var i = 0; i < item.Children?.Count; ++i)
|
||||
{
|
||||
var current = item.Children[i].IsChecked;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
state = current;
|
||||
}
|
||||
else if (state != current)
|
||||
{
|
||||
state = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SetIsChecked(item, state, false, true);
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Add the filter to the predicate dictionary
|
||||
/// </summary>
|
||||
public void AddFilter(Dictionary<string, Predicate<object>> criteria)
|
||||
{
|
||||
if (IsFiltered) return;
|
||||
|
||||
// predicate of filter
|
||||
bool Predicate(object o)
|
||||
{
|
||||
var value = o.GetType().GetProperty(FieldName)?.GetValue(o, null);
|
||||
return !PreviouslyFilteredItems.Contains(value);
|
||||
}
|
||||
|
||||
// add to list of predicates
|
||||
criteria.Add(FieldName, Predicate);
|
||||
|
||||
IsFiltered = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Any Date IsChecked, check if any tree item is checked (can apply filter)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool AnyDateIsChecked()
|
||||
{
|
||||
// any IsChecked is true or null
|
||||
// IsDate Checked has three states, isChecked: null and true
|
||||
return Tree != null && Tree.Skip(1).Any(t => t.IsChecked != false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Any state of Date Changed, check if at least one date is checked and another is changed
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool AnyDateChanged()
|
||||
{
|
||||
// any (year, month, day) status changed
|
||||
return Tree != null &&
|
||||
Tree.Skip(1)
|
||||
.Any(year => year.Changed || year.Children
|
||||
.Any(month => month.Changed || month.Children
|
||||
.Any(day => day.Changed))) && AnyDateIsChecked();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build the item tree
|
||||
/// </summary>
|
||||
/// <param name="dates"></param>
|
||||
/// <param name="currentFilter"></param>
|
||||
/// <param name="uncheckPrevious"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<FilterItem> BuildTree(IEnumerable<object> dates, string lastFilter = null)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var uncheckPrevious = FieldName == lastFilter;
|
||||
var type = typeof(DateTime);
|
||||
|
||||
Tree = new List<FilterItem>
|
||||
{
|
||||
new FilterItem(this)
|
||||
{
|
||||
Label = Translate.All, CurrentFilter = this, Content = 0, Level = 0, SetState = true, FieldType = type
|
||||
}
|
||||
};
|
||||
|
||||
if (dates == null) return Tree;
|
||||
// iterate over all items that are not null
|
||||
// INFO:
|
||||
// SetState : does not raise OnDateStatusChanged event
|
||||
// IsChecked : raise OnDateStatusChanged event
|
||||
// (see the FilterItem class for more informations)
|
||||
|
||||
var dateTimes = dates.ToList();
|
||||
|
||||
foreach (var y in from date in dateTimes.Where(d => d != null)
|
||||
.Select(d => (DateTime)d).OrderBy(o => o.Year)
|
||||
group date by date.Year into year
|
||||
select new FilterItem(this)
|
||||
{
|
||||
// YEAR
|
||||
Level = 1,
|
||||
CurrentFilter = this,
|
||||
Content = year.Key,
|
||||
Label = year.First().ToString("yyyy", Translate.Culture),
|
||||
SetState = true, // default state
|
||||
FieldType = type,
|
||||
|
||||
Children = (from date in year
|
||||
group date by date.Month into month
|
||||
select new FilterItem(this)
|
||||
{
|
||||
// MOUNTH
|
||||
Level = 2,
|
||||
CurrentFilter = this,
|
||||
Content = month.Key,
|
||||
Label = month.First().ToString("MMMM", Translate.Culture),
|
||||
SetState = true, // default state
|
||||
FieldType = type,
|
||||
|
||||
Children = (from day in month
|
||||
select new FilterItem(this)
|
||||
{
|
||||
// DAY
|
||||
Level = 3,
|
||||
CurrentFilter = this,
|
||||
Content = day.Day,
|
||||
Label = day.ToString("dd", Translate.Culture),
|
||||
SetState = true, // default state
|
||||
FieldType = type,
|
||||
Children = new List<FilterItem>()
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
})
|
||||
{
|
||||
// set parent and IsChecked property if uncheckPrevious items
|
||||
y.Children.ForEach(m =>
|
||||
{
|
||||
m.Parent = y;
|
||||
|
||||
m.Children.ForEach(d =>
|
||||
{
|
||||
d.Parent = m;
|
||||
|
||||
// set the state of the ischecked property based on the items already filtered (unchecked)
|
||||
if (PreviouslyFilteredItems != null && uncheckPrevious)
|
||||
d.IsChecked = PreviouslyFilteredItems
|
||||
.Any(u => u != null && u.Equals(new DateTime((int)y.Content, (int)m.Content, (int)d.Content))) == false;
|
||||
|
||||
// reset initialization with new state
|
||||
d.InitialState = d.IsChecked;
|
||||
});
|
||||
|
||||
// reset initialization with new state
|
||||
m.InitialState = m.IsChecked;
|
||||
});
|
||||
|
||||
// reset initialization with new state
|
||||
y.InitialState = y.IsChecked;
|
||||
|
||||
Tree.Add(y);
|
||||
}
|
||||
|
||||
// last empty item if exist in collection
|
||||
if (dateTimes.Any(d => d == null))
|
||||
Tree.Add(
|
||||
new FilterItem(this)
|
||||
{
|
||||
Label = Translate.Empty, // translation
|
||||
CurrentFilter = this,
|
||||
Content = null,
|
||||
Level = -1,
|
||||
FieldType = type,
|
||||
SetState = PreviouslyFilteredItems?.Any(u => u == null) == false,
|
||||
Children = new List<FilterItem>()
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"FilterCommon.BuildTree : {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
return Tree;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all the items from the tree (checked or unchecked)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<FilterItem> GetAllItemsTree()
|
||||
{
|
||||
var filterCommon = new List<FilterItem>();
|
||||
|
||||
try
|
||||
{
|
||||
// skip first item (select all)
|
||||
foreach (var y in Tree.Skip(1))
|
||||
if (y.Level > 0) // year :1, mounth : 2, day : 3
|
||||
filterCommon.AddRange(
|
||||
from m in y.Children
|
||||
from d in m.Children
|
||||
select new FilterItem
|
||||
{
|
||||
Content = new DateTime((int)y.Content, (int)m.Content, (int)d.Content),
|
||||
IsChecked = d.IsChecked ?? false,
|
||||
});
|
||||
else // null date (Level -1)
|
||||
filterCommon.Add(new FilterItem
|
||||
{
|
||||
Content = null,
|
||||
IsChecked = y.IsChecked ?? false,
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"FilterCommon.GetAllItemsTree : {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
return filterCommon;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
|
||||
1309
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterDataGrid.cs
Normal file
1309
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterDataGrid.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
namespace FSI.Lib.Wpf.Ctrls.FilterDataGrid
|
||||
{
|
||||
/// <summary>
|
||||
/// ResourceDictionary
|
||||
/// </summary>
|
||||
public partial class FilterDataGridDictionary
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// FilterDataGrid Dictionary
|
||||
/// </summary>
|
||||
public FilterDataGridDictionary()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
}
|
||||
}
|
||||
396
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterHelpers.cs
Normal file
396
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterHelpers.cs
Normal file
@@ -0,0 +1,396 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace FSI.Lib.Wpf.Ctrls.FilterDataGrid
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer = null)
|
||||
{
|
||||
return new HashSet<T>(source, comparer);
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
|
||||
public static class Helpers
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Print elapsed time
|
||||
/// </summary>
|
||||
/// <param name="label"></param>
|
||||
/// <param name="start"></param>
|
||||
public static void Elapsed(string label, DateTime start)
|
||||
{
|
||||
var span = DateTime.Now - start;
|
||||
Debug.WriteLine($"{label,-20}{span:mm\\:ss\\.ff}");
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
|
||||
public static class VisualTreeHelpers
|
||||
{
|
||||
#region Private Methods
|
||||
|
||||
private static T FindVisualChild<T>(this DependencyObject dependencyObject, string name)
|
||||
where T : DependencyObject
|
||||
{
|
||||
// Search immediate children first (breadth-first)
|
||||
var childrenCount = VisualTreeHelper.GetChildrenCount(dependencyObject);
|
||||
|
||||
//http://stackoverflow.com/questions/12304904/why-visualtreehelper-getchildrencount-returns-0-for-popup
|
||||
|
||||
if (childrenCount == 0 && dependencyObject is Popup)
|
||||
{
|
||||
var popup = dependencyObject as Popup;
|
||||
return popup.Child?.FindVisualChild<T>(name);
|
||||
}
|
||||
|
||||
for (var i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(dependencyObject, i);
|
||||
var nameOfChild = child.GetValue(FrameworkElement.NameProperty) as string;
|
||||
|
||||
if (child is T && (name == string.Empty || name == nameOfChild))
|
||||
return (T)child;
|
||||
var childOfChild = child.FindVisualChild<T>(name);
|
||||
if (childOfChild != null)
|
||||
return childOfChild;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IEnumerable<T> GetChildrenOf<T>(this DependencyObject obj, bool recursive) where T : DependencyObject
|
||||
{
|
||||
var count = VisualTreeHelper.GetChildrenCount(obj);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(obj, i);
|
||||
if (child is T) yield return (T)child;
|
||||
|
||||
if (recursive)
|
||||
foreach (var item in child.GetChildrenOf<T>())
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<T> GetChildrenOf<T>(this DependencyObject obj) where T : DependencyObject
|
||||
{
|
||||
return obj.GetChildrenOf<T>(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is an alternative to WPF's
|
||||
/// <see cref="VisualTreeHelper.GetParent" /> method, which also
|
||||
/// supports content elements. Keep in mind that for content element,
|
||||
/// this method falls back to the logical tree of the element!
|
||||
/// </summary>
|
||||
/// <param name="child">The item to be processed.</param>
|
||||
/// <returns>
|
||||
/// The submitted item's parent, if available. Otherwise
|
||||
/// null.
|
||||
/// </returns>
|
||||
private static DependencyObject GetParentObject(this DependencyObject child)
|
||||
{
|
||||
if (child == null) return null;
|
||||
|
||||
//handle content elements separately
|
||||
var contentElement = child as ContentElement;
|
||||
if (contentElement != null)
|
||||
{
|
||||
var parent = ContentOperations.GetParent(contentElement);
|
||||
if (parent != null) return parent;
|
||||
|
||||
var fce = contentElement as FrameworkContentElement;
|
||||
return fce?.Parent;
|
||||
}
|
||||
|
||||
//also try searching for parent in framework elements (such as DockPanel, etc)
|
||||
var frameworkElement = child as FrameworkElement;
|
||||
if (frameworkElement != null)
|
||||
{
|
||||
var parent = frameworkElement.Parent;
|
||||
if (parent != null) return parent;
|
||||
}
|
||||
|
||||
//if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper
|
||||
return VisualTreeHelper.GetParent(child);
|
||||
}
|
||||
#endregion Private Methods
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns the first ancester of specified type
|
||||
/// </summary>
|
||||
public static T FindAncestor<T>(DependencyObject current)
|
||||
where T : DependencyObject
|
||||
{
|
||||
current = VisualTreeHelper.GetParent(current);
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
if (current is T) return (T)current;
|
||||
|
||||
current = VisualTreeHelper.GetParent(current);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific ancester of an object
|
||||
/// </summary>
|
||||
public static T FindAncestor<T>(DependencyObject current, T lookupItem)
|
||||
where T : DependencyObject
|
||||
{
|
||||
while (current != null)
|
||||
{
|
||||
if (current is T && current == lookupItem) return (T)current;
|
||||
|
||||
current = VisualTreeHelper.GetParent(current);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an ancestor object by name and type
|
||||
/// </summary>
|
||||
public static T FindAncestor<T>(DependencyObject current, string parentName)
|
||||
where T : DependencyObject
|
||||
{
|
||||
while (current != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(parentName))
|
||||
{
|
||||
var frameworkElement = current as FrameworkElement;
|
||||
if (current is T && frameworkElement != null && frameworkElement.Name == parentName)
|
||||
return (T)current;
|
||||
}
|
||||
else if (current is T)
|
||||
{
|
||||
return (T)current;
|
||||
}
|
||||
|
||||
current = VisualTreeHelper.GetParent(current);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks for a child control within a parent by name
|
||||
/// </summary>
|
||||
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
|
||||
{
|
||||
// Confirm parent and childName are valid.
|
||||
if (parent == null) return null;
|
||||
|
||||
T foundChild = null;
|
||||
|
||||
var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
|
||||
for (var i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(parent, i);
|
||||
// If the child is not of the request child type child
|
||||
var childType = child as T;
|
||||
if (childType == null)
|
||||
{
|
||||
// recursively drill down the tree
|
||||
foundChild = FindChild<T>(child, childName);
|
||||
|
||||
// If the child is found, break so we do not overwrite the found child.
|
||||
if (foundChild != null) break;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(childName))
|
||||
{
|
||||
var frameworkElement = child as FrameworkElement;
|
||||
// If the child's name is set for search
|
||||
if (frameworkElement != null && frameworkElement.Name == childName)
|
||||
{
|
||||
// if the child's name is of the request name
|
||||
foundChild = (T)child;
|
||||
break;
|
||||
}
|
||||
|
||||
// recursively drill down the tree
|
||||
foundChild = FindChild<T>(child, childName);
|
||||
|
||||
// If the child is found, break so we do not overwrite the found child.
|
||||
if (foundChild != null) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// child element found.
|
||||
foundChild = (T)child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return foundChild;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks for a child control within a parent by type
|
||||
/// </summary>
|
||||
public static T FindChild<T>(DependencyObject parent)
|
||||
where T : DependencyObject
|
||||
{
|
||||
// Confirm parent is valid.
|
||||
if (parent == null) return null;
|
||||
|
||||
T foundChild = null;
|
||||
|
||||
var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
|
||||
for (var i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(parent, i);
|
||||
// If the child is not of the request child type child
|
||||
var childType = child as T;
|
||||
if (childType == null)
|
||||
{
|
||||
// recursively drill down the tree
|
||||
foundChild = FindChild<T>(child);
|
||||
|
||||
// If the child is found, break so we do not overwrite the found child.
|
||||
if (foundChild != null) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// child element found.
|
||||
foundChild = (T)child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return foundChild;
|
||||
}
|
||||
|
||||
public static T FindVisualChild<T>(this DependencyObject dependencyObject) where T : DependencyObject
|
||||
{
|
||||
return dependencyObject.FindVisualChild<T>(string.Empty);
|
||||
}
|
||||
|
||||
public static Visual GetDescendantByType(Visual element, Type type)
|
||||
{
|
||||
if (element == null) return null;
|
||||
if (element.GetType() == type) return element;
|
||||
Visual foundElement = null;
|
||||
if (element is FrameworkElement frameworkElement) frameworkElement.ApplyTemplate();
|
||||
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
|
||||
{
|
||||
var visual = VisualTreeHelper.GetChild(element, i) as Visual;
|
||||
foundElement = GetDescendantByType(visual, type);
|
||||
if (foundElement != null) break;
|
||||
}
|
||||
|
||||
return foundElement;
|
||||
}
|
||||
|
||||
public static DataGridColumnHeader GetHeader(DataGridColumn column, DependencyObject reference)
|
||||
{
|
||||
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(reference); i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(reference, i);
|
||||
|
||||
if (child is DataGridColumnHeader colHeader && colHeader.Column == column) return colHeader;
|
||||
|
||||
colHeader = GetHeader(column, child);
|
||||
if (colHeader != null) return colHeader;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a parent of a given item on the visual tree.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the queried item.</typeparam>
|
||||
/// <param name="child">
|
||||
/// A direct or indirect child of the
|
||||
/// queried item.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The first parent item that matches the submitted
|
||||
/// type parameter. If not matching item can be found, a null
|
||||
/// reference is being returned.
|
||||
/// </returns>
|
||||
public static T TryFindParent<T>(this DependencyObject child) where T : DependencyObject
|
||||
{
|
||||
//get parent item
|
||||
var parentObject = GetParentObject(child);
|
||||
|
||||
//we've reached the end of the tree
|
||||
if (parentObject == null) return null;
|
||||
|
||||
//check if the parent matches the type we're looking for
|
||||
var parent = parentObject as T;
|
||||
if (parent != null)
|
||||
return parent;
|
||||
return TryFindParent<T>(parentObject);
|
||||
}
|
||||
#endregion Public Methods
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all ViewModel classes in the application. Provides support for
|
||||
/// property changes notification.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public abstract class NotifyProperty : INotifyPropertyChanged
|
||||
{
|
||||
#region Public Events
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a property on this object has a new value.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
#endregion Public Events
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Warns the developer if this object does not have a public property with
|
||||
/// the specified name. This method does not exist in a Release build.
|
||||
/// </summary>
|
||||
[Conditional("DEBUG")]
|
||||
[DebuggerStepThrough]
|
||||
private void VerifyPropertyName(string propertyName)
|
||||
{
|
||||
// verify that the property name matches a real,
|
||||
// public, instance property on this object.
|
||||
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
|
||||
Debug.Fail("Invalid property name: " + propertyName);
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Raises this object's PropertyChanged event.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">The name of the property that has a new value.</param>
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
VerifyPropertyName(propertyName);
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
147
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterItem.cs
Normal file
147
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterItem.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FSI.Lib.Wpf.Ctrls.FilterDataGrid
|
||||
{
|
||||
public class FilterItem : NotifyProperty
|
||||
{
|
||||
#region Public Events
|
||||
|
||||
private event EventHandler<bool?> OnDateStatusChanged;
|
||||
|
||||
#endregion Public Events
|
||||
|
||||
#region Constructor
|
||||
|
||||
public FilterItem(FilterCommon action = null)
|
||||
{
|
||||
// event subscription
|
||||
if (action != null)
|
||||
OnDateStatusChanged += action.UpdateTree;
|
||||
}
|
||||
|
||||
#endregion Constructor
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private bool? isChecked;
|
||||
private bool initialized;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
///Children higher levels (years, months)
|
||||
/// </summary>
|
||||
public List<FilterItem> Children { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Raw value of the item (not displayed, see Label property)
|
||||
/// </summary>
|
||||
public object Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Content length
|
||||
/// </summary>
|
||||
public int ContentLength { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Current filter
|
||||
/// </summary>
|
||||
public FilterCommon CurrentFilter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Field type
|
||||
/// </summary>
|
||||
public Type FieldType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initial state
|
||||
/// </summary>
|
||||
public bool? InitialState { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// State of checkbox
|
||||
/// </summary>
|
||||
public bool? IsChecked
|
||||
{
|
||||
get => isChecked;
|
||||
set
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
InitialState = value;
|
||||
initialized = true;
|
||||
isChecked = value; // don't remove
|
||||
|
||||
// the iteration over an Collection triggers the notification
|
||||
// of the "IsChecked" property and slows the performance of the loop,
|
||||
// the return prevents the OnPropertyChanged
|
||||
// notification at initialization
|
||||
return;
|
||||
}
|
||||
|
||||
// raise event to update the date tree, see FilterCommon class
|
||||
// only type date type fields are subscribed to the OnDateStatusChanged event
|
||||
// OnDateStatusChanged is not triggered at tree initialization
|
||||
if (FieldType == typeof(DateTime))
|
||||
{
|
||||
OnDateStatusChanged?.Invoke(this, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
isChecked = value;
|
||||
OnPropertyChanged("IsChecked");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Content displayed
|
||||
/// </summary>
|
||||
public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Hierarchical level for the date
|
||||
/// </summary>
|
||||
public int Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parent of lower levels (days, months)
|
||||
/// </summary>
|
||||
public FilterItem Parent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the state of the IsChecked property for date, does not invoke the update of the tree
|
||||
/// </summary>
|
||||
public bool? SetState
|
||||
{
|
||||
get => isChecked;
|
||||
set
|
||||
{
|
||||
isChecked = value;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
InitialState = value;
|
||||
initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
OnPropertyChanged("IsChecked");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the initial state has changed
|
||||
/// </summary>
|
||||
public bool Changed => isChecked != InitialState;
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
}
|
||||
235
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/Loc.cs
Normal file
235
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/Loc.cs
Normal file
@@ -0,0 +1,235 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace FSI.Lib.Wpf.Ctrls.FilterDataGrid
|
||||
{
|
||||
public enum Local
|
||||
{
|
||||
Chinese,
|
||||
Dutch,
|
||||
English,
|
||||
French,
|
||||
German,
|
||||
Italian,
|
||||
Russian,
|
||||
}
|
||||
|
||||
public class Loc
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private Local language;
|
||||
|
||||
// culture name(used for dates)
|
||||
private static readonly Dictionary<Local, string> CultureNames = new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "zh-Hans" },
|
||||
{ Local.Dutch, "nl-NL" },
|
||||
{ Local.English, "en-US" },
|
||||
{ Local.French, "fr-FR" },
|
||||
{ Local.German, "de-DE" },
|
||||
{ Local.Italian, "it-IT" },
|
||||
{ Local.Russian, "ru-RU" },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Translation dictionary
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, Dictionary<Local, string>> Translation =
|
||||
new Dictionary<string, Dictionary<Local, string>>
|
||||
{
|
||||
{
|
||||
"All", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "(全选)" },
|
||||
{ Local.Dutch, "(Alles selecteren)" },
|
||||
{ Local.English, "(Select all)" },
|
||||
{ Local.French, "(Sélectionner tout)" },
|
||||
{ Local.German, "(Alle auswählen)" },
|
||||
{ Local.Italian, "(Seleziona tutto)" },
|
||||
{ Local.Russian, "(Выбрать все)" },
|
||||
}
|
||||
},
|
||||
{
|
||||
"Empty", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "(空白)" },
|
||||
{ Local.Dutch, "(Leeg)" },
|
||||
{ Local.English, "(Blank)" },
|
||||
{ Local.French, "(Vides)" },
|
||||
{ Local.German, "(Leer)" },
|
||||
{ Local.Italian, "(Vuoto)" },
|
||||
{ Local.Russian, "(Заготовки)" },
|
||||
}
|
||||
},
|
||||
{
|
||||
"Clear", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "清除过滤器 \"{0}\"" },
|
||||
{ Local.Dutch, "Filter \"{0}\" verwijderen" },
|
||||
{ Local.English, "Clear filter \"{0}\"" },
|
||||
{ Local.French, "Effacer le filtre \"{0}\"" },
|
||||
{ Local.German, "Filter löschen \"{0}\"" },
|
||||
{ Local.Italian, "Cancella filtro \"{0}\"" },
|
||||
{ Local.Russian, "Очистить фильтр \"{0}\"" },
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"Contains", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "搜索(包含)" },
|
||||
{ Local.Dutch, "Zoek (bevat)" },
|
||||
{ Local.English, "Search (contains)" },
|
||||
{ Local.French, "Rechercher (contient)" },
|
||||
{ Local.German, "Suche (enthält)" },
|
||||
{ Local.Italian, "Cerca (contiene)" },
|
||||
{ Local.Russian, "Искать (содержит)" },
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"StartsWith", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "搜索 (来自)" },
|
||||
{ Local.Dutch, "Zoek (beginnen met)" },
|
||||
{ Local.English, "Search (startswith)" },
|
||||
{ Local.French, "Rechercher (commence par)" },
|
||||
{ Local.German, "Suche (beginnen mit)" },
|
||||
{ Local.Italian, "Cerca (inizia con)" },
|
||||
{ Local.Russian, "Искать (hачни с)" },
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"Toggle", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "切換包含/開始於" },
|
||||
{ Local.Dutch, "Toggle bevat/begint met" },
|
||||
{ Local.English, "Toggle contains/startswith" },
|
||||
{ Local.French, "Basculer contient/commence par" },
|
||||
{ Local.German, "Toggle enthält/beginnt mit" },
|
||||
{ Local.Italian, "Toggle contiene/inizia con" },
|
||||
{ Local.Russian, "Переключить содержит/начинается с" },
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"Ok", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "确定" },
|
||||
{ Local.Dutch, "Ok" },
|
||||
{ Local.English, "Ok" },
|
||||
{ Local.French, "Ok" },
|
||||
{ Local.German, "Ok" },
|
||||
{ Local.Italian, "Ok" },
|
||||
{ Local.Russian, "Ok" },
|
||||
}
|
||||
},
|
||||
{
|
||||
"Cancel", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "取消" },
|
||||
{ Local.Dutch, "Annuleren" },
|
||||
{ Local.English, "Cancel" },
|
||||
{ Local.French, "Annuler" },
|
||||
{ Local.German, "Abbrechen" },
|
||||
{ Local.Italian, "Annulla" },
|
||||
{ Local.Russian, "Отмена" },
|
||||
}
|
||||
},
|
||||
{
|
||||
"Status", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "{0:n0} 找到了 {1:n0} 条记录" },
|
||||
{ Local.Dutch, "{0:n0} rij(en) gevonden op {1:n0}" },
|
||||
{ Local.English, "{0:n0} record(s) found on {1:n0}" },
|
||||
{ Local.French, "{0:n0} enregistrement(s) trouvé(s) sur {1:n0}" },
|
||||
{ Local.German, "{0:n0} zeilen angezeigt von {1:n0}" },
|
||||
{ Local.Italian, "{0:n0} oggetti trovati su {1:n0}" },
|
||||
{ Local.Russian, "{0:n0} записей найдено на {1:n0}" },
|
||||
}
|
||||
},
|
||||
{
|
||||
"ElapsedTime", new Dictionary<Local, string>
|
||||
{
|
||||
{ Local.Chinese, "经过时间{0:mm}:{0:ss}.{0:ff}" },
|
||||
{ Local.Dutch, "Verstreken tijd {0:mm}:{0:ss}.{0:ff}" },
|
||||
{ Local.English, "Elapsed time {0:mm}:{0:ss}.{0:ff}" },
|
||||
{ Local.French, "Temps écoulé {0:mm}:{0:ss}.{0:ff}" },
|
||||
{ Local.German, "Verstrichene Zeit {0:mm}:{0:ss}.{0:ff}" },
|
||||
{ Local.Italian, "Tempo trascorso {0:mm}:{0:ss}.{0:ff}" },
|
||||
{ Local.Russian, "Пройденное время {0:mm}:{0:ss}.{0:ff}" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Loc()
|
||||
{
|
||||
Language = Local.English;
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public Local Language
|
||||
{
|
||||
get => language;
|
||||
set
|
||||
{
|
||||
language = value;
|
||||
Culture = new CultureInfo(CultureNames[value]);
|
||||
}
|
||||
}
|
||||
|
||||
public CultureInfo Culture { get; private set; }
|
||||
|
||||
public string CultureName => CultureNames[Language];
|
||||
|
||||
public string LanguageName => Enum.GetName(typeof(Local), Language);
|
||||
|
||||
public string All => Translate("All");
|
||||
|
||||
public string Cancel => Translate("Cancel");
|
||||
|
||||
public string Clear => Translate("Clear");
|
||||
|
||||
public string Contains => Translate("Contains");
|
||||
|
||||
public string ElapsedTime => Translate("ElapsedTime");
|
||||
|
||||
public string Empty => Translate("Empty");
|
||||
|
||||
public string Ok => Translate("Ok");
|
||||
|
||||
public string StartsWith => Translate("StartsWith");
|
||||
|
||||
public string Status => Translate("Status");
|
||||
|
||||
public string Toggle => Translate("Toggle");
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Translated into the language
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
private string Translate(string key)
|
||||
{
|
||||
return Translation.ContainsKey(key) && Translation[key].ContainsKey(Language)
|
||||
? Translation[key][Language]
|
||||
: "unknow";
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
1
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/Readme.md
Normal file
1
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/Readme.md
Normal file
@@ -0,0 +1 @@
|
||||
https://github.com/macgile/DataGridFilter
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FSI.Lib.Wpf.Ctrls.FilterDataGrid
|
||||
{
|
||||
public class StringFormatConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
try
|
||||
{
|
||||
// values [0] contains the format
|
||||
if (values[0] == DependencyProperty.UnsetValue || string.IsNullOrEmpty(values[0]?.ToString()))
|
||||
return string.Empty;
|
||||
|
||||
var stringFormat = values[0].ToString();
|
||||
|
||||
return string.Format(stringFormat, values.Skip(1).ToArray());
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
Debug.WriteLine($"StringFormatConverter.Convert error: {ex.Message}");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,880 @@
|
||||
<ResourceDictionary x:Class="FSI.Lib.Wpf.Ctrls.FilterDataGrid.FilterDataGridDictionary"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:control="clr-namespace:FSI.Lib.Wpf.Ctrls.FilterDataGrid"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<!-- STRING FORMAT CONVERTER -->
|
||||
<control:StringFormatConverter x:Key="StringFormatConverter" />
|
||||
|
||||
<!-- INITIAL POPUP SIZE -->
|
||||
<sys:Double x:Key="PopupHeight">420</sys:Double>
|
||||
<sys:Double x:Key="PopupWidth">262</sys:Double>
|
||||
<sys:Boolean x:Key="StayOpen">False</sys:Boolean>
|
||||
|
||||
<!-- https://yqnn.github.io/svg-path-editor/ -->
|
||||
|
||||
<!-- FILTER SET ICON -->
|
||||
<Geometry x:Key="FilterSet">
|
||||
M 0 17 H 12 L 6 25 Z M 6 0 H 29 L 29 3 L 20 10 L 20 21 H 15 L 15 10 L 6 3 Z
|
||||
</Geometry>
|
||||
|
||||
<!-- FILTER BUTTON ICON -->
|
||||
<Geometry x:Key="Filter">
|
||||
M 7 10 L 12 15 L 17 10 H 7 Z
|
||||
</Geometry>
|
||||
|
||||
<!-- DELETE FILTER ICON -->
|
||||
<Geometry x:Key="FilterDelete">
|
||||
M11.1 11.4L8.5 8.9L9.8 7.6L12.3 10.1L14.8 7.6L16.1 8.9L13.6 11.4L16.1 13.9L14.8 15.2L12.3 12.6L9.8 15.2L8.5 13.9ZM0 0H13L13 2L8 6V14L5 11V6L0 2Z
|
||||
</Geometry>
|
||||
|
||||
<!-- BOX CHECKED ICON -->
|
||||
<Geometry x:Key="FilterChecked">
|
||||
M 125 125 L 0 125 V 0 H 125 Z M 1 124 H 124 V 1 H 1 Z M 20 68 L 29 57 L 56 80 L 98 25 L 110 35 L 59 101 Z
|
||||
</Geometry>
|
||||
|
||||
<!-- GRIPSIZE ICON -->
|
||||
<Geometry x:Key="GripSizeIcon">
|
||||
M0 9L2 9M4 9L6 9M8 9L10 9M1 8L1 10M5 8L5 10M9 8L9 10M4 5L6 5M8 5L10 5M5 4L5 6M9 4L9 6M8 1L10 1M9 0L9 2
|
||||
</Geometry>
|
||||
|
||||
<!-- SEARCH MAGNIFIER ICON -->
|
||||
<Geometry x:Key="Magnifier">
|
||||
M9.6 8.5H9L8.7 8.2C9.6 7.4 10 6.2 10 5C10 2.2 7.8 0 5 0S0 2.2 0 5S2.2 10 5 10C6.2 10 7.4 9.6 8.2 8.7L8.5
|
||||
9V9.6L12.3 13.5L13.5 12.3L9.6 8.5ZM5 8.5C3.1 8.5 1.5 6.9 1.5 5S3.1 1.5 5 1.5S8.5 3.1 8.5 5S6.9 8.5 5 8.5Z
|
||||
</Geometry>
|
||||
|
||||
<!-- SEARCH DELETE ICON -->
|
||||
<Geometry x:Key="Delete">
|
||||
M 0 0 M 2 3 L 3 2 L 8 7 L 13 2 L 14 3 L 9 8 L 14 13 L 13 14 L 8 9 L 3 14 L 2 13 L 7 8 Z M 16 0 M 0 16 M 16 16
|
||||
</Geometry>
|
||||
|
||||
<!-- SEARCH CONTAINS ICON -->
|
||||
<Geometry x:Key="StartsWith">
|
||||
M 0.6 1.3 V 0 C 1.1 -0.1 5.5 -1.7 6.2 1.6 V 7.2 H 5 V 6.2 C 4.5 6.7 4 7 3.5 7.2 H 1.4 C 0.4 6.8 0.1 6.1 0 5.2 C 0 4.7 0 3 3 2.8 H 4.9 V 1.7
|
||||
C 4.4 0.2 2.3 0.6 1 1.1 Z M 4.9 5.1 V 3.8 H 2.6 V 3.8 C 1 3.9 0.9 6.2 2.6 6.2 C 3.5 6.2 4 5.9 4.7 5.3 Z M 9.3 0.9 L 9.5 3.5 L 7.4 2 L 6.9 2.9
|
||||
L 9.2 4 L 6.9 5.1 L 7.3 6.1 L 9.5 4.7 L 9.3 7.2 H 10.4 L 10.2 4.6 L 12.3 6 L 12.8 5.1 L 10.5 4.1 L 12.8 2.9 L 12.3 2 L 10.2 3.5 L 10.4 0.9 Z
|
||||
M 16.5 0.9 H 17.6 L 17.4 3.4 L 19.5 2 L 20 2.9 L 17.7 4 L 20 5.2 L 19.5 6 L 17.4 4.7 L 17.6 7.2 H 16.5 L 16.6 4.7 L 14.5 6 L 14 5.2 L 16.3 4
|
||||
L 14 2.9 L 14.6 2 L 16.7 3.4 Z
|
||||
</Geometry>
|
||||
|
||||
<!-- SEARCH STARTSWITH ICON -->
|
||||
<Geometry x:Key="Contains">
|
||||
M 7.2 1.3 V 0 C 7.7 -0.1 12.1 -1.7 12.8 1.6 V 7.2 H 11.6 V 6.2 C 11.1 6.7 10.6 7 10.1 7.2 H 8 C 7 6.8 6.7 6.1 6.6 5.2 C 6.6 4.7 6.6 3 9.6 2.8
|
||||
H 11.5 V 1.7 C 11 0.2 8.9 0.6 7.6 1.1 Z M 11.5 5.1 V 3.8 H 9.2 C 7.5 4.1 8.1 6.2 9.2 6.2 C 10.1 6.2 10.6 5.9 11.3 5.3 Z M 2.4 1 L 2.6 3.5
|
||||
L 0.5 2.1 L 0 3 L 2.2 4.1 L 0 5.3 L 0.4 6.1 L 2.6 4.7 L 2.4 7.2 H 3.5 L 3.3 4.7 L 5.4 6.1 L 5.9 5.2 L 3.6 4.1 L 5.9 3 L 5.4 2.1 L 3.3 3.5
|
||||
L 3.5 1 Z M 16.5 0.9 H 17.6 L 17.4 3.5 L 19.5 2 L 20 3 L 17.7 4 L 20 5.2 L 19.5 6 L 17.4 4.7 L 17.6 7.2 H 16.5 L 16.6 4.7 L 14.5 6 L 14 5.2
|
||||
L 16.3 4.1 L 14 2.9 L 14.6 2 L 16.6 3.4 Z
|
||||
</Geometry>
|
||||
|
||||
<!-- PLACEHOLDER SEARCH BOX -->
|
||||
<Style x:Key="PlaceHolder"
|
||||
TargetType="{x:Type TextBox}">
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="Transparent" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate x:Name="SearchControlTemplate"
|
||||
TargetType="{x:Type TextBox}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- SEARCH TEXTBOX -->
|
||||
<TextBox x:Name="TextSource"
|
||||
Grid.Column="0"
|
||||
Margin="{TemplateBinding Margin}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Panel.ZIndex="2"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="0"
|
||||
Focusable="True"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
MaxLength="{TemplateBinding MaxLength}"
|
||||
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBox x:Name="TextBoxPlaceHolder"
|
||||
Grid.Column="0"
|
||||
Margin="{TemplateBinding Margin}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Panel.ZIndex="1"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="0"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
MaxLength="{TemplateBinding MaxLength}"
|
||||
Text="{TemplateBinding Tag}">
|
||||
<TextBox.Style>
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
<Setter Property="Foreground"
|
||||
Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=Text, ElementName=TextSource}"
|
||||
Value="">
|
||||
<Setter Property="Foreground"
|
||||
Value="LightGray" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBox.Style>
|
||||
</TextBox>
|
||||
|
||||
<!-- BUTTON CLEAR FILTER -->
|
||||
<Button x:Name="ClearSearchBoxBtn"
|
||||
Grid.Column="1"
|
||||
Margin="2"
|
||||
Background="Transparent"
|
||||
Command="{x:Static control:FilterDataGrid.ClearSearchBox}"
|
||||
SnapsToDevicePixels="True"
|
||||
UseLayoutRounding="True">
|
||||
<Button.Style>
|
||||
<Style TargetType="{x:Type Button}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="Transparent"
|
||||
SnapsToDevicePixels="True">
|
||||
<!-- MAGNIFIER / DELETE ICON -->
|
||||
<Path x:Name="PathButton"
|
||||
Width="18"
|
||||
Height="18"
|
||||
Margin="0"
|
||||
Data="{StaticResource Delete}"
|
||||
Fill="DarkSlateGray"
|
||||
SnapsToDevicePixels="True"
|
||||
Stretch="Uniform"
|
||||
UseLayoutRounding="True" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding ElementName=TextSource, Path=Text}"
|
||||
Value="">
|
||||
<Setter Property="IsEnabled"
|
||||
Value="False" />
|
||||
<Setter TargetName="PathButton"
|
||||
Property="Data"
|
||||
Value="{StaticResource Magnifier}" />
|
||||
</DataTrigger>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter Property="Cursor"
|
||||
Value="Hand" />
|
||||
<Setter TargetName="PathButton"
|
||||
Property="Fill"
|
||||
Value="Red" />
|
||||
<Setter TargetName="PathButton"
|
||||
Property="Stroke"
|
||||
Value="Red" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
|
||||
<!-- SEPARATOR -->
|
||||
<Border Grid.Column="2"
|
||||
Width="1"
|
||||
Margin="2,0,2,0"
|
||||
Background="LightGray" />
|
||||
|
||||
<!-- TOGGLE BUTTON -->
|
||||
<ToggleButton Name="SearchToggleButton"
|
||||
Grid.Column="3"
|
||||
Margin="2,0,2,0"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type control:FilterDataGrid}}}"
|
||||
IsChecked="{Binding StartsWith, UpdateSourceTrigger=PropertyChanged}"
|
||||
ToolTip="{Binding Translate.Toggle}">
|
||||
<ToggleButton.Style>
|
||||
<Style TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="Cursor"
|
||||
Value="Hand" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ToggleButton">
|
||||
<Border Padding="3"
|
||||
Background="Transparent"
|
||||
BorderBrush="LightGray"
|
||||
BorderThickness="0">
|
||||
<Path x:Name="PathToggle"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource Contains}"
|
||||
Fill="DarkSlateGray"
|
||||
Stretch="UniformToFill" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsChecked"
|
||||
Value="True">
|
||||
<Setter TargetName="PathToggle"
|
||||
Property="Data"
|
||||
Value="{StaticResource StartsWith}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter TargetName="PathToggle"
|
||||
Property="Fill"
|
||||
Value="Black" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
</Grid>
|
||||
<!-- PLACEHOLDER TEXT -->
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsFocused"
|
||||
Value="True">
|
||||
<Setter TargetName="TextSource"
|
||||
Property="FocusManager.FocusedElement"
|
||||
Value="{Binding RelativeSource={RelativeSource Self}}" />
|
||||
</Trigger>
|
||||
<DataTrigger Binding="{Binding ElementName=SearchToggleButton, Path=IsChecked}"
|
||||
Value="True">
|
||||
<Setter TargetName="TextBoxPlaceHolder"
|
||||
Property="Text"
|
||||
Value="{Binding Translate.StartsWith, Mode=OneWay}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding ElementName=SearchToggleButton, Path=IsChecked}"
|
||||
Value="False">
|
||||
<Setter TargetName="TextBoxPlaceHolder"
|
||||
Property="Text"
|
||||
Value="{Binding Translate.Contains, Mode=OneWay}" />
|
||||
</DataTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- DEFAULT STYLE AND CONTROLTEMPLATE FOR DATAGRID -->
|
||||
<Style BasedOn="{StaticResource {x:Type DataGrid}}"
|
||||
TargetType="{x:Type control:FilterDataGrid}">
|
||||
|
||||
<!-- DISABLING CanUserAddRows : AggregateException when user can add row -->
|
||||
<Setter Property="CanUserAddRows"
|
||||
Value="False" />
|
||||
|
||||
<!-- ROWS COUNT TEMPLATE -->
|
||||
<Setter Property="RowHeaderTemplate">
|
||||
<Setter.Value>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}}, Path=Header}" />
|
||||
</DataTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type DataGrid}">
|
||||
<Border Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
SnapsToDevicePixels="True">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- CONTENT DATAGRID -->
|
||||
<ScrollViewer x:Name="DG_ScrollViewer"
|
||||
Grid.Row="0"
|
||||
CanContentScroll="True"
|
||||
Focusable="false">
|
||||
<ScrollViewer.Template>
|
||||
<ControlTemplate TargetType="{x:Type ScrollViewer}">
|
||||
<Grid ShowGridLines="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Button Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
|
||||
Command="{x:Static DataGrid.SelectAllCommand}"
|
||||
Focusable="false"
|
||||
Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle,
|
||||
TypeInTargetAssembly={x:Type DataGrid}}}"
|
||||
Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.All}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
|
||||
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
|
||||
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
CanContentScroll="{TemplateBinding CanContentScroll}" />
|
||||
<ScrollBar x:Name="PART_VerticalScrollBar"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Maximum="{TemplateBinding ScrollableHeight}"
|
||||
Orientation="Vertical"
|
||||
ViewportSize="{TemplateBinding ViewportHeight}"
|
||||
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
|
||||
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<Grid Grid.Row="2"
|
||||
Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ScrollBar x:Name="PART_HorizontalScrollBar"
|
||||
Grid.Column="1"
|
||||
Maximum="{TemplateBinding ScrollableWidth}"
|
||||
Orientation="Horizontal"
|
||||
ViewportSize="{TemplateBinding ViewportWidth}"
|
||||
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
|
||||
Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</ScrollViewer.Template>
|
||||
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- STATUS BAR & RESULT FILTER -->
|
||||
<Border x:Name="BorderStatusBar"
|
||||
Grid.Row="1"
|
||||
Padding="4,2"
|
||||
Background="Transparent"
|
||||
BorderBrush="LightGray"
|
||||
BorderThickness="0,1">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Visibility"
|
||||
Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=ShowStatusBar, RelativeSource={RelativeSource AncestorType={x:Type control:FilterDataGrid}}}"
|
||||
Value="True">
|
||||
<Setter Property="Visibility"
|
||||
Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
|
||||
<UniformGrid Columns="2"
|
||||
DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type control:FilterDataGrid}}}">
|
||||
|
||||
<!-- RESULT STATUS -->
|
||||
<TextBlock HorizontalAlignment="Left">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<Binding Path="Translate.Status" />
|
||||
<Binding Path="Items.Count"
|
||||
UpdateSourceTrigger="PropertyChanged" />
|
||||
<Binding Path="ItemsSourceCount" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
|
||||
<!-- ELAPSED TIME -->
|
||||
<TextBlock HorizontalAlignment="Right">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<Binding Path="Translate.ElapsedTime"
|
||||
UpdateSourceTrigger="PropertyChanged" />
|
||||
<Binding Path="ElapsedTime" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Visibility"
|
||||
Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ShowElapsedTime}"
|
||||
Value="True">
|
||||
<Setter Property="Visibility"
|
||||
Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</UniformGrid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- DATAGRIDCOLUMNHEADER STYLE -->
|
||||
<Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}"
|
||||
TargetType="DataGridColumnHeader">
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Stretch" />
|
||||
</Style>
|
||||
|
||||
<!-- DATATEMPLATE OF DATAGRIDCOLUMNHEADER -->
|
||||
<DataTemplate x:Key="DataGridHeaderTemplate">
|
||||
|
||||
<!-- HEADER STRECH TO CONTENTPRESENTER OF DATAGRIDCOLUMNHEADER -->
|
||||
<Grid x:Name="ContainerFilterGrid"
|
||||
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}, Mode=FindAncestor, AncestorLevel=1}, Path=ActualWidth}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="Transparent">
|
||||
|
||||
<!-- HEADER/BUTTON -->
|
||||
<Grid x:Name="GridHeaderButton"
|
||||
ShowGridLines="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- RENDER THE HEADER TEXT -->
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding}" />
|
||||
|
||||
<!-- FILTER BUTTON -->
|
||||
<Button Name="filterButton"
|
||||
Grid.Column="1"
|
||||
Width="19"
|
||||
Height="19"
|
||||
Background="Transparent"
|
||||
BorderBrush="DarkGray"
|
||||
BorderThickness="1"
|
||||
Command="{x:Static control:FilterDataGrid.ShowFilter}"
|
||||
Cursor="Hand"
|
||||
Opacity="0.5"
|
||||
OverridesDefaultStyle="True"
|
||||
SnapsToDevicePixels="True"
|
||||
UseLayoutRounding="True">
|
||||
<Button.Style>
|
||||
<Style TargetType="{x:Type Button}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border Padding="2"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="1"
|
||||
SnapsToDevicePixels="True"
|
||||
UseLayoutRounding="True">
|
||||
<Path x:Name="PathFilterIcon"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource Filter}"
|
||||
Fill="DarkSlateGray"
|
||||
Stretch="Uniform" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<!-- POPUP -->
|
||||
<Popup Name="FilterPopup"
|
||||
AllowsTransparency="True"
|
||||
IsOpen="False"
|
||||
PlacementTarget="{Binding ElementName=ContainerFilterGrid}"
|
||||
StaysOpen="{StaticResource StayOpen}">
|
||||
|
||||
<Border x:Name="PopUpBorder"
|
||||
Padding="0"
|
||||
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
|
||||
BorderBrush="LightGray"
|
||||
BorderThickness="1">
|
||||
|
||||
<Grid x:Name="SizableContentGrid"
|
||||
MinWidth="{StaticResource PopupWidth}"
|
||||
MinHeight="{StaticResource PopupHeight}"
|
||||
ShowGridLines="False"
|
||||
ZIndex="1">
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"
|
||||
MinWidth="32" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- BUTTON CLEAR FILTER -->
|
||||
<Button x:Name="ClearFilterBnt"
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="2,10,2,2"
|
||||
Padding="4"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{x:Static control:FilterDataGrid.RemoveFilter}"
|
||||
Content="{Binding Path=Content, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridColumnHeader}}, UpdateSourceTrigger=PropertyChanged}"
|
||||
FontSize="13"
|
||||
OverridesDefaultStyle="True">
|
||||
<Button.Style>
|
||||
<Style TargetType="{x:Type Button}">
|
||||
<Setter Property="Foreground"
|
||||
Value="DarkSlateGray" />
|
||||
<Setter Property="SnapsToDevicePixels"
|
||||
Value="True" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border x:Name="BorderContent"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="0"
|
||||
SnapsToDevicePixels="True"
|
||||
UseLayoutRounding="True">
|
||||
<Grid x:Name="ContentGrid"
|
||||
Background="Transparent">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Path Grid.Column="0"
|
||||
Width="16"
|
||||
Margin="0,0,10,0"
|
||||
Data="{StaticResource FilterDelete}"
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
Stretch="Uniform" />
|
||||
|
||||
<TextBlock x:Name="ContentPresenter"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type control:FilterDataGrid}}}">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<MultiBinding.Bindings>
|
||||
<Binding Path="Translate.Clear"
|
||||
TargetNullValue=""
|
||||
UpdateSourceTrigger="PropertyChanged" />
|
||||
<Binding ElementName="ClearFilterBnt"
|
||||
Path="Content" />
|
||||
</MultiBinding.Bindings>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter TargetName="BorderContent"
|
||||
Property="Background"
|
||||
Value="#F0F0F0" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed"
|
||||
Value="True">
|
||||
<Setter TargetName="BorderContent"
|
||||
Property="Background">
|
||||
<Setter.Value>
|
||||
<SolidColorBrush Opacity="0.8"
|
||||
Color="LightGray" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>
|
||||
<SolidColorBrush Opacity="0.5"
|
||||
Color="DarkSlateGray" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
|
||||
<!-- SEPARATOR -->
|
||||
<Separator Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Margin="0,2"
|
||||
Background="LightGray" />
|
||||
|
||||
<!-- SEARCH BOX -->
|
||||
<Border Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Margin="0,4,4,2"
|
||||
Padding="0,2"
|
||||
VerticalAlignment="Top"
|
||||
Background="Transparent"
|
||||
BorderBrush="LightGray"
|
||||
BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox x:Name="SearchBox"
|
||||
Grid.Column="0"
|
||||
Margin="0"
|
||||
Padding="2,0,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
AcceptsReturn="False"
|
||||
DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type control:FilterDataGrid}}}"
|
||||
Focusable="True"
|
||||
FontSize="13"
|
||||
MaxLength="20"
|
||||
Style="{StaticResource PlaceHolder}"
|
||||
Tag="{Binding Translate.Contains}">
|
||||
<TextBox.InputBindings>
|
||||
<KeyBinding Key="Enter"
|
||||
Command="{x:Static control:FilterDataGrid.ApplyFilter}" />
|
||||
</TextBox.InputBindings>
|
||||
</TextBox>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ICON (current filter is set) -->
|
||||
<Path x:Name="PathIsFiltered"
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Width="19"
|
||||
Height="20"
|
||||
Margin="0,5,0,0"
|
||||
VerticalAlignment="Top"
|
||||
Data="{StaticResource FilterChecked}"
|
||||
Fill="DarkSlateGray"
|
||||
Stretch="Fill"
|
||||
Stroke="DarkSlateGray"
|
||||
StrokeThickness="0.2">
|
||||
<Path.Style>
|
||||
<Style TargetType="Path">
|
||||
<Setter Property="Visibility"
|
||||
Value="Hidden" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ElementName=ClearFilterBnt, Path=IsEnabled}"
|
||||
Value="True">
|
||||
<Setter Property="Visibility"
|
||||
Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Path.Style>
|
||||
</Path>
|
||||
|
||||
<!-- LISTBOX / TREEVIEW -->
|
||||
<Border Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Margin="0,4,4,4"
|
||||
BorderThickness="0">
|
||||
|
||||
<Grid x:Name="GridItemControl">
|
||||
|
||||
<ListBox x:Name="PopupListBox"
|
||||
Grid.Row="0"
|
||||
Padding="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
BorderBrush="LightGray"
|
||||
BorderThickness="1"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Visibility="Collapsed">
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}"
|
||||
TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Left" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBox.ItemTemplate>
|
||||
<!--
|
||||
ContentStringFormat="{}{0}"
|
||||
Content="{Binding Label, ConverterCulture=en-US}"
|
||||
ContentStringFormat="F2, en-US"
|
||||
the value of the label is a string, so it cannot be formatted
|
||||
-->
|
||||
<DataTemplate DataType="{x:Type control:FilterItem}">
|
||||
<CheckBox x:Name="CheckBox"
|
||||
Width="Auto"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Command="{x:Static control:FilterDataGrid.IsChecked}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding Label}"
|
||||
FontWeight="Normal"
|
||||
IsChecked="{Binding IsChecked}"
|
||||
IsThreeState="False" />
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding Level}"
|
||||
Value="1">
|
||||
<Setter TargetName="CheckBox"
|
||||
Property="Margin"
|
||||
Value="4,0,0,0" />
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<TreeView x:Name="PopupTreeview"
|
||||
Grid.Row="0"
|
||||
BorderBrush="LightGray"
|
||||
BorderThickness="1"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Visibility="Collapsed">
|
||||
<TreeView.ItemTemplate>
|
||||
<HierarchicalDataTemplate DataType="control:FilterItem"
|
||||
ItemsSource="{Binding Children}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox x:Name="CheckBoxTree"
|
||||
VerticalAlignment="Center"
|
||||
Focusable="False"
|
||||
IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ContentPresenter Margin="2"
|
||||
Content="{Binding Label}" />
|
||||
</StackPanel>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding Level}"
|
||||
Value="1">
|
||||
<Setter TargetName="CheckBoxTree"
|
||||
Property="Margin"
|
||||
Value="4,0,0,0" />
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</HierarchicalDataTemplate>
|
||||
</TreeView.ItemTemplate>
|
||||
<TreeView.ItemContainerStyle>
|
||||
<Style BasedOn="{StaticResource {x:Type TreeViewItem}}"
|
||||
TargetType="{x:Type TreeViewItem}">
|
||||
<Setter Property="OverridesDefaultStyle"
|
||||
Value="True" />
|
||||
<Setter Property="IsExpanded"
|
||||
Value="False" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="Visibility"
|
||||
Value="Visible" />
|
||||
</Style>
|
||||
</TreeView.ItemContainerStyle>
|
||||
</TreeView>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- OK/CANCEL BUTTON -->
|
||||
<UniformGrid Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Margin="0,6,4,6"
|
||||
HorizontalAlignment="Right"
|
||||
Background="Transparent"
|
||||
Columns="2"
|
||||
DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type control:FilterDataGrid}}}">
|
||||
|
||||
<Button Width="100"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Left"
|
||||
Command="{x:Static control:FilterDataGrid.ApplyFilter}"
|
||||
Content="{Binding Translate.Ok}" />
|
||||
|
||||
<Button Width="100"
|
||||
Margin="6,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{x:Static control:FilterDataGrid.CancelFilter}"
|
||||
Content="{Binding Translate.Cancel}" />
|
||||
</UniformGrid>
|
||||
|
||||
<!-- RESIZE GRIP -->
|
||||
<Thumb x:Name="PopupThumb"
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Width="20"
|
||||
Height="Auto"
|
||||
Margin="0,0,2,2"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
SnapsToDevicePixels="True"
|
||||
UseLayoutRounding="True">
|
||||
<Thumb.Style>
|
||||
<Style TargetType="{x:Type Thumb}">
|
||||
<Style.Setters>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Grid x:Name="resizeVisual"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="Transparent"
|
||||
DockPanel.Dock="Right"
|
||||
SnapsToDevicePixels="True"
|
||||
UseLayoutRounding="True">
|
||||
<Path Width="12"
|
||||
Height="12"
|
||||
Margin="0"
|
||||
Data="{StaticResource GripSizeIcon}"
|
||||
Stretch="None"
|
||||
Stroke="LightSlateGray"
|
||||
StrokeThickness="1" />
|
||||
<Grid.Style>
|
||||
<Style TargetType="{x:Type Grid}">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeNWSE" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Grid.Style>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</Thumb.Style>
|
||||
</Thumb>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Popup>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
||||
18
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/Themes/Generic.xaml
Normal file
18
FSI.Lib/FSI.Lib/Wpf/Ctrls/FilterDataGrid/Themes/Generic.xaml
Normal file
@@ -0,0 +1,18 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:control="clr-namespace:FSI.Lib.Wpf.Ctrls.FilterDataGrid">
|
||||
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="/FilterDataGrid;component/Themes/FilterDataGrid.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<!--
|
||||
EXTERNAL ACCESS FOR CUSTOMIZE DEFAULT STYLE
|
||||
SEE FILTERDATAGRID DEFAULT STYLE
|
||||
-->
|
||||
<Style x:Key="{ComponentResourceKey {x:Type control:FilterDataGrid},
|
||||
FilterDataGridStyle}"
|
||||
BasedOn="{StaticResource {x:Type control:FilterDataGrid}}"
|
||||
TargetType="{x:Type control:FilterDataGrid}" />
|
||||
</ResourceDictionary>
|
||||
138
FSI.Lib/FSI.Lib/Wpf/WindowExtensions.cs
Normal file
138
FSI.Lib/FSI.Lib/Wpf/WindowExtensions.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
namespace FSI.Lib.Wpf.ExtensionMethods
|
||||
{
|
||||
public static class WindowExtensions
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
public static bool ActivateCenteredToMouse(this Window window)
|
||||
{
|
||||
ComputeTopLeft(ref window);
|
||||
return window.Activate();
|
||||
}
|
||||
|
||||
public static void ShowCenteredToMouse(this Window window)
|
||||
{
|
||||
// in case the default start-up location isn't set to Manual
|
||||
WindowStartupLocation oldLocation = window.WindowStartupLocation;
|
||||
// set location to manual -> window will be placed by Top and Left property
|
||||
window.WindowStartupLocation = WindowStartupLocation.Manual;
|
||||
ComputeTopLeft(ref window);
|
||||
window.Show();
|
||||
window.WindowStartupLocation = oldLocation;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private static void ComputeTopLeft(ref Window window)
|
||||
{
|
||||
W32Point pt = new W32Point();
|
||||
if (!GetCursorPos(ref pt))
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
|
||||
}
|
||||
|
||||
// 0x00000002: return nearest monitor if pt is not contained in any monitor.
|
||||
IntPtr monHandle = MonitorFromPoint(pt, 0x00000002);
|
||||
W32MonitorInfo monInfo = new W32MonitorInfo();
|
||||
monInfo.Size = Marshal.SizeOf(typeof(W32MonitorInfo));
|
||||
|
||||
if (!GetMonitorInfo(monHandle, ref monInfo))
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
|
||||
}
|
||||
|
||||
// use WorkArea struct to include the taskbar position.
|
||||
W32Rect monitor = monInfo.WorkArea;
|
||||
double offsetX = Math.Round(window.Width / 2);
|
||||
double offsetY = Math.Round(window.Height / 2);
|
||||
|
||||
double top = pt.Y - offsetY;
|
||||
double left = pt.X - offsetX;
|
||||
|
||||
Rect screen = new Rect(
|
||||
new Point(monitor.Left, monitor.Top),
|
||||
new Point(monitor.Right, monitor.Bottom));
|
||||
Rect wnd = new Rect(
|
||||
new Point(left, top),
|
||||
new Point(left + window.Width, top + window.Height));
|
||||
|
||||
window.Top = wnd.Top;
|
||||
window.Left = wnd.Left;
|
||||
|
||||
if (!screen.Contains(wnd))
|
||||
{
|
||||
if (wnd.Top < screen.Top)
|
||||
{
|
||||
double diff = Math.Abs(screen.Top - wnd.Top);
|
||||
window.Top = wnd.Top + diff;
|
||||
}
|
||||
|
||||
if (wnd.Bottom > screen.Bottom)
|
||||
{
|
||||
double diff = wnd.Bottom - screen.Bottom;
|
||||
window.Top = wnd.Top - diff;
|
||||
}
|
||||
|
||||
if (wnd.Left < screen.Left)
|
||||
{
|
||||
double diff = Math.Abs(screen.Left - wnd.Left);
|
||||
window.Left = wnd.Left + diff;
|
||||
}
|
||||
|
||||
if (wnd.Right > screen.Right)
|
||||
{
|
||||
double diff = wnd.Right - screen.Right;
|
||||
window.Left = wnd.Left - diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region W32 API
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool GetCursorPos(ref W32Point pt);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool GetMonitorInfo(IntPtr hMonitor, ref W32MonitorInfo lpmi);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr MonitorFromPoint(W32Point pt, uint dwFlags);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct W32Point
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct W32MonitorInfo
|
||||
{
|
||||
public int Size;
|
||||
public W32Rect Monitor;
|
||||
public W32Rect WorkArea;
|
||||
public uint Flags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct W32Rect
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
3
FSI.Lib/README.md
Normal file
3
FSI.Lib/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# FSI.Lib
|
||||
|
||||
Fondium Singen Library
|
||||
Reference in New Issue
Block a user