Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
66c672f
Fix null deref in FileNameValidator and BooleansOrConverter. Use Gene…
labre-rdc Mar 2, 2026
fcddf1b
BindingProxy: Docs and use nameof.
labre-rdc Mar 2, 2026
4525d29
Add and set ValidationErrorTemplate for CheckBoxes.
labre-rdc Mar 2, 2026
d6fdd8f
Fix obvious typo in ChildWindowStyles restricting the window height t…
labre-rdc Mar 2, 2026
39a6c6a
Reuse FileExistsValidator in EmptyOrFileExistsValidator.
labre-rdc Mar 2, 2026
c9e73e5
ListHelper: code documentation and refactoring of Modify as generic. …
labre-rdc Mar 2, 2026
f58adf9
PowershellHelper: Support commands exceeding the command line limit o…
labre-rdc Mar 2, 2026
9023d2d
NetworkInterfaceView: Fix all warnings.
labre-rdc Mar 2, 2026
42530bd
ProfileChildWindow: Remove size limit for wider content.
labre-rdc Mar 2, 2026
5e2411c
Add NetworkProfile enum and a property for later use in NetworkInterf…
labre-rdc Mar 2, 2026
34e7047
Add NETworkManager.Interfaces project to avoid certain circular refer…
labre-rdc Mar 2, 2026
80a33d0
Add generic converter for DataGrid column collapsing, checking proper…
labre-rdc Mar 2, 2026
53ea911
Add converter to use size factors in XAML.
labre-rdc Mar 2, 2026
9064595
Add ValidationHelper to convert ViewModel HasError states to style ch…
labre-rdc Mar 2, 2026
99fe27b
Add converters for localized enum conversion (int, string).
labre-rdc Mar 2, 2026
adb2920
Add empty variants of FilePath and Int32 validators.
labre-rdc Mar 2, 2026
3d29a0b
Fix 2 warnings in ProfilesView. Scnr.
labre-rdc Mar 2, 2026
65969a5
Add localization strings for Firewall application. Separate commit to…
labre-rdc Mar 2, 2026
be56e92
Add Firewall application.
labre-rdc Mar 2, 2026
f92d09b
Firewall App PR: Replace changelog pr placeholder with actual pr number.
labre-rdc Mar 2, 2026
ef95654
Add powershell argument quote sanitizing in Firewall model.
labre-rdc Mar 2, 2026
86a013a
Merge branch 'main' into firewall-pr
BornToBeRoot Mar 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Globalization;
using System.Linq;
using System.Windows.Data;
using NETworkManager.Models.Network;
using NETworkManager.Localization.Resources;


namespace NETworkManager.Converters;

public class BoolArrayToFwRuleCategoriesConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(string)) return null;
const int expectedLength = 3;
var fallback = GetTranslation(Enum.GetName(NetworkProfiles.NotConfigured), false);
if (value is not bool[] { Length: expectedLength } boolArray)
return fallback;
var result = string.Empty;
var numSelected = boolArray.CountAny(true);
switch (numSelected)
{
case 0:
return fallback;
case < 2:
return GetTranslation(Enum.GetName(typeof(NetworkProfiles),
Array.FindIndex(boolArray, b => b)), false);
}

if (boolArray.All(b => b))
return Strings.All;

for (var i = 0; i < expectedLength; i++)
{
if (boolArray[i])
result += $", {GetTranslation(Enum.GetName(typeof(NetworkProfiles), i), true)}";
}

return result[2..];

}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}

private static string GetTranslation(string key, bool trimmed)
{
return Strings.ResourceManager.GetString(trimmed ? $"{key}_Short3" : key, Strings.Culture);
}
}
2 changes: 1 addition & 1 deletion Source/NETworkManager.Converters/BooleansOrConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public sealed class BooleansOrConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values.Any(value => (bool)value);
return values?.OfType<bool>().Any(value => value) ?? false;
}

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Windows.Data;
using NETworkManager.Interfaces.ViewModels;

namespace NETworkManager.Converters
{
/// <summary>
/// A generic converter that checks a property of items in a collection.
/// If ANY item's property is considered "present" (not null, not empty), it returns Visible.
/// </summary>
/// <typeparam name="T">The type of item in the collection.</typeparam>
public class CollectionPropertyBooleanOrConverter<T> : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// 1. Validate inputs
if (value is not IEnumerable<T> collection)
return false;

if (parameter is not string propertyName || string.IsNullOrEmpty(propertyName))
return false;

// 2. Get PropertyInfo via Reflection or cache.
if (!Cache.TryGetValue(propertyName, out var propertyInfo))
{
propertyInfo = typeof(T).GetProperty(propertyName);
Cache.TryAdd(propertyName, propertyInfo);
}

if (propertyInfo == null)
return false;

// 3. Iterate collection and check property
foreach (var item in collection)
{
if (item == null) continue;

var propValue = propertyInfo.GetValue(item);

if (propValue is true)
return true;
}

return false;
}


public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}

private ConcurrentDictionary<string, PropertyInfo> Cache { get; } = new();
}

// Concrete implementation for XAML usage
public class FirewallRuleViewModelBooleanOrConverter : CollectionPropertyBooleanOrConverter<IFirewallRuleViewModel>;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using NETworkManager.Interfaces.ViewModels;

namespace NETworkManager.Converters
{
/// <summary>
/// A generic converter that checks a property of items in a collection.
/// If ANY item's property is considered "present" (not null, not empty), it returns Visible.
/// </summary>
/// <typeparam name="T">The type of item in the collection.</typeparam>
public class CollectionPropertyVisibilityConverter<T> : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// 1. Validate inputs
if (value is not IEnumerable<T> collection)
return Visibility.Collapsed;

if (parameter is not string propertyName || string.IsNullOrEmpty(propertyName))
return Visibility.Collapsed;

// 2. Get PropertyInfo via Reflection or cache.
if (!Cache.TryGetValue(propertyName, out var propertyInfo))
{
propertyInfo = typeof(T).GetProperty(propertyName);
Cache.TryAdd(propertyName, propertyInfo);
}

if (propertyInfo == null)
return Visibility.Collapsed;

// 3. Iterate collection and check property
foreach (var item in collection)
{
if (item == null) continue;

var propValue = propertyInfo.GetValue(item);

if (HasContent(propValue))
{
return Visibility.Visible;
}
}

return Visibility.Collapsed;
}

private static bool HasContent(object value)
{
if (value == null) return false;

// Handle Strings
if (value is string str)
return !string.IsNullOrWhiteSpace(str);

// Handle Collections (Lists, Arrays, etc.)
if (value is ICollection col)
return col.Count > 0;

// Handle Generic Enumerable (fallback)
if (value is IEnumerable enumValue)
{
var enumerator = enumValue.GetEnumerator();
var result = enumerator.MoveNext(); // Has at least one item
(enumerator as IDisposable)?.Dispose();
return result;
}

// Default: If it's an object and not null, it's "True"
return true;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}

private ConcurrentDictionary<string, PropertyInfo> Cache { get; } = new();
}

// Concrete implementation for XAML usage
public class FirewallRuleViewModelVisibilityConverter : CollectionPropertyVisibilityConverter<IFirewallRuleViewModel>;
}
34 changes: 34 additions & 0 deletions Source/NETworkManager.Converters/EmptyToIntMaxValueConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Globalization;
using System.Windows.Data;

namespace NETworkManager.Converters;

public class EmptyToIntMaxValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
const int fallback = int.MaxValue;
if (targetType == typeof(int))
{
if (value is not string strValue)
return fallback;
if (string.IsNullOrWhiteSpace(strValue))
return fallback;
if (!int.TryParse(strValue, out int parsedIntValue))
return fallback;
return parsedIntValue;
}

if (targetType != typeof(string))
return null;
if (value is not int intValue)
return null;
return intValue is fallback ? string.Empty : intValue.ToString();
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Convert(value, targetType, parameter, culture);
}
}
61 changes: 61 additions & 0 deletions Source/NETworkManager.Converters/EnumToIntConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Globalization;
using System.Windows.Data;


namespace NETworkManager.Converters;

/// <summary>
/// A value converter that facilitates the conversion between enumeration values and their corresponding integer indices or string names.
/// </summary>
/// <remarks>
/// This converter is designed to either:
/// - Convert an enumeration value to its integer index within the enumeration.
/// - Convert an enumeration value to its string representation.
/// When converting back, the same logic is applied to handle appropriate conversion.
/// </remarks>
public class EnumToIntConverter : IValueConverter
{
/// <summary>
/// Converts an Enum value to its corresponding integer index or string representation
/// based on the target type. If the target type is an Enum, the method attempts
/// to return the name of the enum value. If the provided value is an Enum, it
/// returns the integer index of the value within the Enum's definition.
/// </summary>
/// <param name="value">The value to convert. This can be an Enum instance or null.</param>
/// <param name="targetType">The target type for the conversion. Typically either Enum or int.</param>
/// <param name="parameter">An optional parameter for additional input, not used in this method.</param>
/// <param name="culture">The culture information for the conversion process.</param>
/// <returns>
/// If the targetType is an Enum, a string representation of the Enum name is returned.
/// If the value is an Enum, the integer index of the Enum value is returned.
/// If neither condition is met, null is returned.
/// </returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType.IsEnum)
{
return value is null ? string.Empty :
Enum.GetName(targetType, value);
}
if (value is Enum enumVal)
{
return Array.IndexOf(Enum.GetValues(enumVal.GetType()), enumVal);
}

return null;
}

/// Converts a value back into its corresponding enumeration value or integer representation.
/// This method is typically used in two-way data bindings where an integer or string needs
/// to be converted back to the corresponding enum value.
/// <param name="value">The value to be converted back. This can be an integer or a string representation of an enumeration value.</param>
/// <param name="targetType">The type of the target object, typically the type of the enumeration.</param>
/// <param name="parameter">An optional parameter for the conversion. Not used in this implementation.</param>
/// <param name="culture">The culture information to use during the conversion process.</param>
/// <return>The enumeration value corresponding to the input value.</return>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Convert(value, targetType, parameter, culture);
}
}
Loading
Loading