Skip to content

Commit 6ce96cd

Browse files
committed
* Added sorting to the scan result ListView
* Updated some code doc
1 parent 249b2ae commit 6ce96cd

5 files changed

Lines changed: 166 additions & 11 deletions

File tree

Advanced PortChecker/Advanced PortChecker.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
<Compile Include="Classes\Scanner\ScanOperation.cs" />
7676
<Compile Include="Classes\Scanner\PortScanner.cs" />
7777
<Compile Include="Classes\GUI\StyleManager.cs" />
78+
<Compile Include="Classes\Utils\GridViewSorter.cs" />
7879
<Compile Include="Classes\Utils\ThreadCalculator.cs" />
7980
<Compile Include="Windows\AboutWindow.xaml.cs">
8081
<DependentUpon>AboutWindow.xaml</DependentUpon>

Advanced PortChecker/Classes/Scanner/PortScanner.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal static class PortScanner
1919
/// <param name="startPort">The starting point of ports that needs to be scanned</param>
2020
/// <param name="stopPort">The final port in a range of ports that needs to be scanned</param>
2121
/// <param name="timeout">The amount of time before a connection times out</param>
22-
/// <param name="scanOperation">The operation information regarding this scan</param>
22+
/// <param name="scanOperation">The ScanInformation object containing information regarding this scan</param>
2323
/// <returns>A list of LvCheck objects containing information regarding the ports and address that were scanned</returns>
2424
// ReSharper disable once IdentifierTypo
2525
internal static List<LvCheck> CheckTCPUDP(string address, int startPort, int stopPort, int timeout, ScanOperation scanOperation)
@@ -46,7 +46,7 @@ internal static List<LvCheck> CheckTCPUDP(string address, int startPort, int sto
4646
/// <param name="startPort">The starting point of ports that needs to be scanned</param>
4747
/// <param name="stopPort">The final port in a range of ports that needs to be scanned</param>
4848
/// <param name="timeout">The amount of time before the connection times out</param>
49-
/// <param name="scanOperation">The operation information regarding this scan</param>
49+
/// <param name="scanOperation">The ScanInformation object containing information regarding this scan</param>
5050
/// <param name="reportProgress">A boolean to represent whether this method should report the current progress or not</param>
5151
/// <returns>A list of LvCheck objects containing information regarding the ports and address that were scanned</returns>
5252
internal static List<LvCheck> CheckTCP(string address, int startPort, int stopPort, int timeout, ScanOperation scanOperation, bool reportProgress)
@@ -89,7 +89,7 @@ internal static List<LvCheck> CheckTCP(string address, int startPort, int stopPo
8989
/// <param name="startPort">The starting point of ports that needs to be scanned</param>
9090
/// <param name="stopPort">The final port in a range of ports that needs to be scanned</param>
9191
/// <param name="timeout">The amount of time before the connection times out</param>
92-
/// <param name="scanOperation">The operation information regarding this scan</param>
92+
/// <param name="scanOperation">The ScanInformation object containing information regarding this scan</param>
9393
/// <param name="reportProgress">A boolean to represent whether this method should report the current progress or not</param>
9494
/// <returns>A list of LvCheck objects containing information regarding the ports and address that were scanned</returns>
9595
internal static List<LvCheck> CheckUDP(string address, int startPort, int stopPort, int timeout, ScanOperation scanOperation, bool reportProgress)
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Windows;
4+
using System.Windows.Controls;
5+
using System.Windows.Controls.Primitives;
6+
using System.Windows.Media;
7+
8+
namespace Advanced_PortChecker.Classes.Utils
9+
{
10+
/// <summary>
11+
/// Internal logic for sorting a GridView
12+
/// </summary>
13+
internal class GridViewSort
14+
{
15+
#region Properties
16+
/// <summary>
17+
/// Check whether sorting is enabled or not
18+
/// </summary>
19+
/// <param name="obj">The DependencyObject that needs to be checked for sorting</param>
20+
/// <returns>True if sorting is enabled, otherwise false</returns>
21+
internal static bool GetEnabled(DependencyObject obj)
22+
{
23+
return (bool)obj.GetValue(EnabledProperty);
24+
}
25+
26+
/// <summary>
27+
/// Enable or disable sorting
28+
/// </summary>
29+
/// <param name="obj">The DependencyObject that needs to have the Enabled property for sorting changed</param>
30+
/// <param name="value">True if enabled, otherwise false</param>
31+
internal static void SetEnabled(DependencyObject obj, bool value)
32+
{
33+
obj.SetValue(EnabledProperty, value);
34+
}
35+
36+
/// <summary>
37+
/// The EnabledProperty that can be used by DependencyObjects
38+
/// </summary>
39+
internal static readonly DependencyProperty EnabledProperty = DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(GridViewSort),
40+
new UIPropertyMetadata(
41+
false,
42+
(o, e) =>
43+
{
44+
// ReSharper disable once UsePatternMatching
45+
if (!(o is ListView listView)) return;
46+
bool oldValue = (bool)e.OldValue;
47+
bool newValue = (bool)e.NewValue;
48+
if (oldValue && !newValue)
49+
{
50+
listView.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ColumnHeader_Click));
51+
}
52+
if (!oldValue && newValue)
53+
{
54+
listView.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ColumnHeader_Click));
55+
}
56+
}
57+
)
58+
);
59+
60+
/// <summary>
61+
/// Get the name of a property
62+
/// </summary>
63+
/// <param name="obj">The DependencyObject</param>
64+
/// <returns>The name of a property</returns>
65+
internal static string GetPropertyName(DependencyObject obj)
66+
{
67+
return (string)obj.GetValue(PropertyNameProperty);
68+
}
69+
70+
/// <summary>
71+
/// Set the name of a property
72+
/// </summary>
73+
/// <param name="obj">The DependencyObject</param>
74+
/// <param name="value">The name of the property</param>
75+
internal static void SetPropertyName(DependencyObject obj, string value)
76+
{
77+
obj.SetValue(PropertyNameProperty, value);
78+
}
79+
80+
/// <summary>
81+
/// Using a DependencyProperty as the backing store for PropertyName. This enables animation, styling, binding, etc...
82+
/// </summary>
83+
internal static readonly DependencyProperty PropertyNameProperty =
84+
DependencyProperty.RegisterAttached(
85+
"PropertyName",
86+
typeof(string),
87+
typeof(GridViewSort),
88+
new UIPropertyMetadata(null)
89+
);
90+
#endregion
91+
92+
#region ColumnHeader
93+
/// <summary>
94+
/// Method that is called when a ColumnHeader object is clicked
95+
/// </summary>
96+
/// <param name="sender">The object that called this method</param>
97+
/// <param name="e">The RoutedEventArgs</param>
98+
private static void ColumnHeader_Click(object sender, RoutedEventArgs e)
99+
{
100+
if (!(e.OriginalSource is GridViewColumnHeader headerClicked)) return;
101+
string propertyName = GetPropertyName(headerClicked.Column);
102+
if (string.IsNullOrEmpty(propertyName)) return;
103+
ListView listView = GetAncestor<ListView>(headerClicked);
104+
if (listView == null) return;
105+
if (GetEnabled(listView))
106+
{
107+
ApplySort(listView.Items, propertyName);
108+
}
109+
}
110+
#endregion
111+
112+
#region Helpermethods
113+
/// <summary>
114+
/// Get the parent object of a DependencyObject
115+
/// </summary>
116+
/// <typeparam name="T">DependencyObject</typeparam>
117+
/// <param name="reference">A DependencyObject</param>
118+
/// <returns>The parent of a DependencyObject</returns>
119+
internal static T GetAncestor<T>(DependencyObject reference) where T : DependencyObject
120+
{
121+
DependencyObject parent = VisualTreeHelper.GetParent(reference);
122+
while (!(parent is T))
123+
{
124+
parent = VisualTreeHelper.GetParent(parent ?? throw new InvalidOperationException());
125+
}
126+
return (T)parent;
127+
}
128+
129+
/// <summary>
130+
/// Apply the sorting to the content of a ICollectionView
131+
/// </summary>
132+
/// <param name="view">The ICollectionView</param>
133+
/// <param name="propertyName">The name of the property</param>
134+
internal static void ApplySort(ICollectionView view, string propertyName)
135+
{
136+
ListSortDirection direction = ListSortDirection.Ascending;
137+
if (view.SortDescriptions.Count > 0)
138+
{
139+
SortDescription currentSort = view.SortDescriptions[0];
140+
if (currentSort.PropertyName == propertyName)
141+
{
142+
direction = currentSort.Direction == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending;
143+
}
144+
view.SortDescriptions.Clear();
145+
}
146+
if (!string.IsNullOrEmpty(propertyName))
147+
{
148+
view.SortDescriptions.Add(new SortDescription(propertyName, direction));
149+
}
150+
}
151+
#endregion
152+
}
153+
}

Advanced PortChecker/Windows/MainWindow.xaml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
55
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
66
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7-
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8+
xmlns:utils="clr-namespace:Advanced_PortChecker.Classes.Utils"
89
mc:Ignorable="d"
910
UseLayoutRounding="True"
1011
Title="Advanced PortChecker" Height="350" Width="500" WindowStartupLocation="CenterScreen" TitleTextAlignment="Center"
@@ -148,7 +149,7 @@
148149
</Grid>
149150
</GroupBox>
150151
</Grid>
151-
<ListView Margin="5" Grid.Row="2" x:Name="LvPorts">
152+
<ListView Margin="5" Grid.Row="2" x:Name="LvPorts" utils:GridViewSort.Enabled="True">
152153
<ListView.ItemContainerStyle>
153154
<Style TargetType="{x:Type ListViewItem}">
154155
<Setter Property="BorderBrush" Value="LightGray" />
@@ -182,11 +183,11 @@
182183
</ListView.ContextMenu>
183184
<ListView.View>
184185
<GridView>
185-
<GridViewColumn Header="Address" DisplayMemberBinding="{Binding Address}" />
186-
<GridViewColumn Header="Port" DisplayMemberBinding="{Binding Port}" />
187-
<GridViewColumn Header="Host name" DisplayMemberBinding="{Binding HostName}" />
188-
<GridViewColumn Header="Type" DisplayMemberBinding="{Binding Type}" />
189-
<GridViewColumn Header="Description" DisplayMemberBinding="{Binding Description}" />
186+
<GridViewColumn Header="Address" DisplayMemberBinding="{Binding Address}" utils:GridViewSort.PropertyName="Address" />
187+
<GridViewColumn Header="Port" DisplayMemberBinding="{Binding Port}" utils:GridViewSort.PropertyName="Port" />
188+
<GridViewColumn Header="Host name" DisplayMemberBinding="{Binding HostName}" utils:GridViewSort.PropertyName="HostName" />
189+
<GridViewColumn Header="Type" DisplayMemberBinding="{Binding Type}" utils:GridViewSort.PropertyName="Type" />
190+
<GridViewColumn Header="Description" DisplayMemberBinding="{Binding Description}" utils:GridViewSort.PropertyName="Description" />
190191
</GridView>
191192
</ListView.View>
192193
</ListView>

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Advanced PortChecker
2-
Advanced PortChecker is a free and open-source application that can tell you if a certain port is open or not.
2+
Advanced PortChecker is a multithreaded, free and open-source application that can tell you if a certain port is open or not.
33
You can export the results of a scan in TXT, CSV or HTML format.
44

55
# Requirements

0 commit comments

Comments
 (0)