Skip to content

Commit d4feade

Browse files
committed
Added Network Adapter Item (#671)
1 parent b7b8d61 commit d4feade

File tree

5 files changed

+372
-5
lines changed

5 files changed

+372
-5
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<UserControl
2+
x:Class="InternetTest.Components.NetworkAdapterItem"
3+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:lang="clr-namespace:InternetTest.Properties"
7+
xmlns:local="clr-namespace:InternetTest.Components"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
Width="400"
10+
Height="200"
11+
FontFamily="..\Fonts\#Hauora"
12+
Foreground="{DynamicResource Foreground1}"
13+
mc:Ignorable="d">
14+
<Border
15+
Margin="10"
16+
Padding="10"
17+
Background="{DynamicResource Background1}"
18+
BorderBrush="{DynamicResource Border}"
19+
BorderThickness="1"
20+
CornerRadius="10">
21+
<Grid>
22+
<Grid.RowDefinitions>
23+
<RowDefinition Height="40" />
24+
<RowDefinition Height="*" />
25+
<RowDefinition Height="Auto" />
26+
</Grid.RowDefinitions>
27+
28+
<Grid>
29+
<Grid.ColumnDefinitions>
30+
<ColumnDefinition Width="Auto" />
31+
<ColumnDefinition />
32+
<ColumnDefinition Width="Auto" />
33+
</Grid.ColumnDefinitions>
34+
<TextBlock
35+
x:Name="AdapterIcon"
36+
Margin="5 0"
37+
VerticalAlignment="Center"
38+
d:Text="&#xF8AC;"
39+
FontFamily="../Fonts/#FluentSystemIcons-Regular"
40+
FontSize="16"
41+
Foreground="{DynamicResource Accent}"
42+
Text="{Binding Icon}" />
43+
<TextBlock
44+
x:Name="NameTxt"
45+
Grid.Column="1"
46+
MaxWidth="280"
47+
VerticalAlignment="Center"
48+
d:Text="Long Adapter Name Will Be Displayed Here"
49+
FontSize="14"
50+
FontWeight="Bold"
51+
Text="{Binding Name}"
52+
TextWrapping="Wrap" />
53+
<Border
54+
Grid.Column="2"
55+
Padding="5 2"
56+
VerticalAlignment="Center"
57+
d:BorderBrush="Green"
58+
BorderBrush="{Binding StatusColor}"
59+
BorderThickness="1"
60+
CornerRadius="10">
61+
<TextBlock
62+
d:Foreground="Green"
63+
d:Text="Connected"
64+
FontWeight="SemiBold"
65+
Foreground="{Binding StatusColor}"
66+
Text="{Binding Status}" />
67+
</Border>
68+
69+
</Grid>
70+
<Grid Grid.Row="1">
71+
<Grid.ColumnDefinitions>
72+
<ColumnDefinition />
73+
<ColumnDefinition />
74+
</Grid.ColumnDefinitions>
75+
<Grid.RowDefinitions>
76+
<RowDefinition Height="Auto" />
77+
<RowDefinition Height="Auto" />
78+
</Grid.RowDefinitions>
79+
<StackPanel Margin="5">
80+
<TextBlock
81+
FontSize="12"
82+
Foreground="{DynamicResource DarkGray}"
83+
Text="{x:Static lang:Resources.InterfaceType}" />
84+
<TextBlock
85+
d:Text="{x:Static lang:Resources.InterfaceType}"
86+
FontSize="14"
87+
FontWeight="SemiBold"
88+
Text="{Binding InterfaceType}" />
89+
90+
</StackPanel>
91+
<StackPanel Grid.Row="1" Margin="5">
92+
<TextBlock
93+
FontSize="12"
94+
Foreground="{DynamicResource DarkGray}"
95+
Text="{x:Static lang:Resources.Speed}" />
96+
<TextBlock
97+
d:Text="{x:Static lang:Resources.Speed}"
98+
FontSize="14"
99+
FontWeight="SemiBold"
100+
Text="{Binding Speed}" />
101+
102+
</StackPanel>
103+
<StackPanel Grid.Column="1" Margin="5">
104+
<TextBlock
105+
FontSize="12"
106+
Foreground="{DynamicResource DarkGray}"
107+
Text="{x:Static lang:Resources.TotalBytesReceived}" />
108+
<TextBlock
109+
d:Text="{x:Static lang:Resources.TotalBytesReceived}"
110+
FontSize="14"
111+
FontWeight="SemiBold"
112+
Text="{Binding TotalBytesReceived}" />
113+
114+
</StackPanel>
115+
<StackPanel
116+
Grid.Row="1"
117+
Grid.Column="1"
118+
Margin="5">
119+
<TextBlock
120+
FontSize="12"
121+
Foreground="{DynamicResource DarkGray}"
122+
Text="{x:Static lang:Resources.TotalBytesSent}" />
123+
<TextBlock
124+
d:Text="{x:Static lang:Resources.TotalBytesSent}"
125+
FontSize="14"
126+
FontWeight="SemiBold"
127+
Text="{Binding TotalBytesSent}" />
128+
129+
</StackPanel>
130+
</Grid>
131+
<StackPanel
132+
Grid.Row="2"
133+
HorizontalAlignment="Right"
134+
Orientation="Horizontal">
135+
<Button
136+
Padding="5 3"
137+
Background="Transparent"
138+
Cursor="Hand"
139+
Foreground="{DynamicResource Foreground1}">
140+
<StackPanel Orientation="Horizontal">
141+
<TextBlock
142+
VerticalAlignment="Center"
143+
FontFamily="..\Fonts\#FluentSystemIcons-Regular"
144+
Text="&#xF4A4;" />
145+
<TextBlock
146+
Margin="5 0 0 0"
147+
FontWeight="SemiBold"
148+
Text="{x:Static lang:Resources.Details}" />
149+
</StackPanel>
150+
</Button>
151+
<Button
152+
Padding="5 3"
153+
Background="Transparent"
154+
Command="{Binding SettingsCommand}"
155+
Cursor="Hand"
156+
Foreground="{DynamicResource Foreground1}">
157+
<StackPanel Orientation="Horizontal">
158+
<TextBlock
159+
VerticalAlignment="Center"
160+
FontFamily="..\Fonts\#FluentSystemIcons-Regular"
161+
Text="&#xFD05;" />
162+
<TextBlock
163+
Margin="5 0 0 0"
164+
FontWeight="SemiBold"
165+
Text="{x:Static lang:Resources.Settings}" />
166+
</StackPanel>
167+
</Button>
168+
</StackPanel>
169+
</Grid>
170+
</Border>
171+
</UserControl>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
MIT License
3+
4+
Copyright (c) Léo Corporation
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
*/
24+
25+
using System.Windows.Controls;
26+
27+
namespace InternetTest.Components
28+
{
29+
/// <summary>
30+
/// Interaction logic for NetworkAdapterItem.xaml
31+
/// </summary>
32+
public partial class NetworkAdapterItem : UserControl
33+
{
34+
public NetworkAdapterItem()
35+
{
36+
InitializeComponent();
37+
}
38+
}
39+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
MIT License
3+
4+
Copyright (c) Léo Corporation
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
*/
24+
using InternetTest.Commands;
25+
using InternetTest.Helpers;
26+
using InternetTest.Models;
27+
using System.Diagnostics;
28+
using System.Net.NetworkInformation;
29+
using System.Windows.Input;
30+
using System.Windows.Media;
31+
32+
namespace InternetTest.ViewModels.Components;
33+
34+
public class NetworkAdapterItemViewModel : ViewModelBase
35+
{
36+
private string? _name;
37+
public string? Name { get => _name; set { _name = value; OnPropertyChanged(nameof(Name)); } }
38+
39+
private string? _interfaceType;
40+
public string? InterfaceType { get => _interfaceType; set { _interfaceType = value; OnPropertyChanged(nameof(InterfaceType)); } }
41+
42+
private string? _status;
43+
public string? Status { get => _status; set { _status = value; OnPropertyChanged(nameof(Status)); } }
44+
45+
private string? _totalBytesReceived;
46+
public string? TotalBytesReceived { get => _totalBytesReceived; set { _totalBytesReceived = value; OnPropertyChanged(nameof(TotalBytesReceived)); } }
47+
48+
private string? _totalBytesSent;
49+
public string? TotalBytesSent { get => _totalBytesSent; set { _totalBytesSent = value; OnPropertyChanged(nameof(TotalBytesSent)); } }
50+
51+
private string? _speed;
52+
public string? Speed { get => _speed; set { _speed = value; OnPropertyChanged(nameof(Speed)); } }
53+
54+
private string? _icon;
55+
public string? Icon { get => _icon; set { _icon = value; OnPropertyChanged(nameof(Icon)); } }
56+
57+
private SolidColorBrush? _statusColor;
58+
public SolidColorBrush? StatusColor
59+
{
60+
get => _statusColor;
61+
set
62+
{
63+
_statusColor = value;
64+
OnPropertyChanged(nameof(StatusColor));
65+
}
66+
}
67+
68+
public ICommand SettingsCommand { get; }
69+
70+
public NetworkAdapterItemViewModel(NetworkAdapter networkAdapter)
71+
{
72+
Name = networkAdapter.Name;
73+
InterfaceType = networkAdapter.NetworkInterfaceType.ToString();
74+
StatusColor = networkAdapter.Status switch
75+
{
76+
OperationalStatus.Up => ThemeHelper.GetSolidColorBrush("Green"),
77+
OperationalStatus.Down => ThemeHelper.GetSolidColorBrush("Red"),
78+
_ => ThemeHelper.GetSolidColorBrush("Accent")
79+
};
80+
Status = networkAdapter.Status switch
81+
{
82+
OperationalStatus.Up => Properties.Resources.ConnectedS,
83+
OperationalStatus.Down => Properties.Resources.Disconnected,
84+
_ => networkAdapter.Status.ToString()
85+
};
86+
87+
Icon = networkAdapter.NetworkInterfaceType switch
88+
{
89+
NetworkInterfaceType.Tunnel => "\uF18E",
90+
NetworkInterfaceType.Ethernet => "\uFB32",
91+
NetworkInterfaceType.Ethernet3Megabit => "\uFB32",
92+
NetworkInterfaceType.FastEthernetFx => "\uFB32",
93+
NetworkInterfaceType.FastEthernetT => "\uFB32",
94+
NetworkInterfaceType.GigabitEthernet => "\uFB32",
95+
_ => "\uF8AC"
96+
};
97+
98+
if (networkAdapter.Name.Contains("Bluetooth")) Icon = "\uF1DF";
99+
100+
Speed = $"{StorageUnitHelper.GetStorageUnit(networkAdapter.Speed).Item2:0.00} {StorageUnitHelper.UnitToString(StorageUnitHelper.GetStorageUnit(networkAdapter.Speed).Item1)}/s";
101+
TotalBytesSent = $"{StorageUnitHelper.GetStorageUnit(networkAdapter.BytesSent).Item2:0.00} {StorageUnitHelper.UnitToString(StorageUnitHelper.GetStorageUnit(networkAdapter.BytesSent).Item1)}";
102+
TotalBytesReceived = $"{StorageUnitHelper.GetStorageUnit(networkAdapter.BytesReceived).Item2:0.00} {StorageUnitHelper.UnitToString(StorageUnitHelper.GetStorageUnit(networkAdapter.BytesReceived).Item1)}";
103+
104+
SettingsCommand = new RelayCommand((object o) =>
105+
{
106+
Process.Start("control.exe", "ncpa.cpl");
107+
});
108+
}
109+
}

InternetTest/InternetTest/ViewModels/WiFiPageViewModel.cs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2222
SOFTWARE.
2323
*/
2424
using InternetTest.Models;
25-
using System;
26-
using System.Collections.Generic;
27-
using System.Linq;
28-
using System.Text;
29-
using System.Threading.Tasks;
25+
using InternetTest.ViewModels.Components;
26+
using System.Net.NetworkInformation;
27+
using System.Windows;
3028

3129
namespace InternetTest.ViewModels;
3230
public class WiFiPageViewModel : ViewModelBase
3331
{
3432
private readonly Settings _settings;
3533

34+
private List<NetworkAdapterItemViewModel> _adapters = [];
35+
public List<NetworkAdapterItemViewModel> Adapters
36+
{
37+
get => _adapters;
38+
set { _adapters = value; OnPropertyChanged(nameof(Adapters)); }
39+
}
40+
41+
private bool _showHidden = false;
42+
public bool ShowHidden { get => _showHidden; set { _showHidden = value; OnPropertyChanged(nameof(ShowHidden)); } }
3643
public WiFiPageViewModel(Settings settings)
3744
{
3845
_settings = settings;
46+
Adapters = [];
47+
ShowHidden = _settings.HideDisabledAdapters ?? false;
48+
49+
GetAdapters();
50+
}
51+
52+
internal void GetAdapters()
53+
{
54+
try
55+
{
56+
Adapters = [];
57+
NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
58+
for (int i = 0; i < networkInterfaces.Length; i++)
59+
{
60+
if (!ShowHidden && networkInterfaces[i].OperationalStatus == OperationalStatus.Down) continue;
61+
62+
// .NET 9+ get the same behavior as .NET 8
63+
if (!(_settings.ShowAdaptersNoIpv4Support ?? false) && !networkInterfaces[i].Supports(NetworkInterfaceComponent.IPv4)) continue;
64+
Adapters.Add(new (new(networkInterfaces[i])));
65+
}
66+
}
67+
catch (Exception ex)
68+
{
69+
MessageBox.Show(ex.Message, Properties.Resources.Error, MessageBoxButton.OK, MessageBoxImage.Error);
70+
}
3971
}
4072
}

0 commit comments

Comments
 (0)