|
@@ -10,6 +10,7 @@ namespace QuickIP.Client;
|
|
|
|
|
|
|
|
public partial class DeviceDetailsWindow : Window
|
|
public partial class DeviceDetailsWindow : Window
|
|
|
{
|
|
{
|
|
|
|
|
+ private const int ApplyConfirmationTimeoutSeconds = 20;
|
|
|
private readonly AgentApiService _agentApiService = new();
|
|
private readonly AgentApiService _agentApiService = new();
|
|
|
private readonly string _baseAddress;
|
|
private readonly string _baseAddress;
|
|
|
private readonly string _localIPv4;
|
|
private readonly string _localIPv4;
|
|
@@ -30,8 +31,16 @@ public partial class DeviceDetailsWindow : Window
|
|
|
|
|
|
|
|
private async void DeviceDetailsWindow_OnLoaded(object sender, RoutedEventArgs e)
|
|
private async void DeviceDetailsWindow_OnLoaded(object sender, RoutedEventArgs e)
|
|
|
{
|
|
{
|
|
|
- await LoadRemoteDetailsAsync();
|
|
|
|
|
- UpdateButtonStates();
|
|
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
|
|
+ await LoadRemoteDetailsAsync();
|
|
|
|
|
+ UpdateButtonStates();
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (Exception ex)
|
|
|
|
|
+ {
|
|
|
|
|
+ ShowStatusMessage($"读取设备信息失败:{ex.Message}");
|
|
|
|
|
+ SetBusyState(false);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private async Task LoadRemoteDetailsAsync()
|
|
private async Task LoadRemoteDetailsAsync()
|
|
@@ -85,13 +94,21 @@ public partial class DeviceDetailsWindow : Window
|
|
|
|
|
|
|
|
private async void RemoteTargetInterfaceComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
private async void RemoteTargetInterfaceComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
{
|
|
{
|
|
|
- if (RemoteTargetInterfaceComboBox.SelectedItem is not RemoteInterfaceInfo selected)
|
|
|
|
|
|
|
+ try
|
|
|
{
|
|
{
|
|
|
- UpdateButtonStates();
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (RemoteTargetInterfaceComboBox.SelectedItem is not RemoteInterfaceInfo selected)
|
|
|
|
|
+ {
|
|
|
|
|
+ UpdateButtonStates();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- await LoadRemoteInterfaceConfigAsync(selected.SystemName, useBusyState: true);
|
|
|
|
|
|
|
+ await LoadRemoteInterfaceConfigAsync(selected.SystemName, useBusyState: true);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (Exception ex)
|
|
|
|
|
+ {
|
|
|
|
|
+ ShowStatusMessage($"读取目标接口配置失败:{ex.Message}");
|
|
|
|
|
+ SetBusyState(false);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private async Task LoadRemoteInterfaceConfigAsync(string interfaceName, bool useBusyState = false)
|
|
private async Task LoadRemoteInterfaceConfigAsync(string interfaceName, bool useBusyState = false)
|
|
@@ -116,14 +133,15 @@ public partial class DeviceDetailsWindow : Window
|
|
|
|
|
|
|
|
var config = result.Data;
|
|
var config = result.Data;
|
|
|
RemoteConfigInterfaceTextBlock.Text = config.Interface;
|
|
RemoteConfigInterfaceTextBlock.Text = config.Interface;
|
|
|
- RemoteConfigIpTextBlock.Text = string.IsNullOrWhiteSpace(config.IP) ? "无" : $"{config.IP}/{config.Prefix}";
|
|
|
|
|
|
|
+ RemoteConfigIpTextBlock.Text = FormatCurrentIp(config);
|
|
|
RemoteConfigGatewayTextBlock.Text = string.IsNullOrWhiteSpace(config.Gateway) ? "无" : config.Gateway;
|
|
RemoteConfigGatewayTextBlock.Text = string.IsNullOrWhiteSpace(config.Gateway) ? "无" : config.Gateway;
|
|
|
RemoteConfigDnsTextBlock.Text = config.DnsSummary;
|
|
RemoteConfigDnsTextBlock.Text = config.DnsSummary;
|
|
|
_suppressConfigChangeHandling = true;
|
|
_suppressConfigChangeHandling = true;
|
|
|
|
|
+ Dhcp4CheckBox.IsChecked = false;
|
|
|
NewIpTextBox.Text = config.IP;
|
|
NewIpTextBox.Text = config.IP;
|
|
|
NewMaskTextBox.Text = PrefixToMask(config.Prefix);
|
|
NewMaskTextBox.Text = PrefixToMask(config.Prefix);
|
|
|
NewGatewayTextBox.Text = config.Gateway;
|
|
NewGatewayTextBox.Text = config.Gateway;
|
|
|
- NewDnsTextBox.Text = config.Dns.FirstOrDefault() ?? string.Empty;
|
|
|
|
|
|
|
+ NewDnsTextBox.Text = config.Dns?.FirstOrDefault() ?? string.Empty;
|
|
|
_suppressConfigChangeHandling = false;
|
|
_suppressConfigChangeHandling = false;
|
|
|
_configValidated = false;
|
|
_configValidated = false;
|
|
|
ShowStatusMessage("已读取Linux端IP配置。");
|
|
ShowStatusMessage("已读取Linux端IP配置。");
|
|
@@ -197,7 +215,8 @@ public partial class DeviceDetailsWindow : Window
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var confirmMessage = $"将要把以下配置应用到接口 {selected.SystemName}:\n\n" +
|
|
var confirmMessage = $"将要把以下配置应用到接口 {selected.SystemName}:\n\n" +
|
|
|
- $"IP:{request.IP}/{request.Prefix}\n" +
|
|
|
|
|
|
|
+ $"模式:{(request.Dhcp4 ? "DHCP 自动获取" : "静态 IPv4")}\n" +
|
|
|
|
|
+ $"IP:{(request.Dhcp4 ? "自动获取" : $"{request.IP}/{request.Prefix}")}\n" +
|
|
|
$"网关:{(string.IsNullOrWhiteSpace(request.Gateway) ? "无" : request.Gateway)}\n" +
|
|
$"网关:{(string.IsNullOrWhiteSpace(request.Gateway) ? "无" : request.Gateway)}\n" +
|
|
|
$"DNS:{(request.Dns.Count == 0 ? "无" : string.Join(", ", request.Dns))}\n\n" +
|
|
$"DNS:{(request.Dns.Count == 0 ? "无" : string.Join(", ", request.Dns))}\n\n" +
|
|
|
"请确认是否继续。";
|
|
"请确认是否继续。";
|
|
@@ -216,7 +235,7 @@ public partial class DeviceDetailsWindow : Window
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ShowStatusMessage($"配置任务已提交:{applyResult.Data.TaskId},正在轮询状态。");
|
|
|
|
|
|
|
+ ShowStatusMessage("配置任务已提交,正在应用并等待连通确认...");
|
|
|
await PollTaskAsync(applyResult.Data.TaskId);
|
|
await PollTaskAsync(applyResult.Data.TaskId);
|
|
|
}
|
|
}
|
|
|
finally
|
|
finally
|
|
@@ -228,6 +247,7 @@ public partial class DeviceDetailsWindow : Window
|
|
|
private async Task PollTaskAsync(string taskId)
|
|
private async Task PollTaskAsync(string taskId)
|
|
|
{
|
|
{
|
|
|
var transientFailureCount = 0;
|
|
var transientFailureCount = 0;
|
|
|
|
|
+ var confirmationRequested = false;
|
|
|
for (var i = 0; i < 20; i++)
|
|
for (var i = 0; i < 20; i++)
|
|
|
{
|
|
{
|
|
|
await Task.Delay(1000);
|
|
await Task.Delay(1000);
|
|
@@ -237,7 +257,7 @@ public partial class DeviceDetailsWindow : Window
|
|
|
if (result.StatusCode is null)
|
|
if (result.StatusCode is null)
|
|
|
{
|
|
{
|
|
|
transientFailureCount++;
|
|
transientFailureCount++;
|
|
|
- ShowStatusMessage($"任务 {taskId} 轮询中,检测到短暂断连,正在重试({transientFailureCount})。");
|
|
|
|
|
|
|
+ ShowStatusMessage($"设备连接短暂中断,正在重试({transientFailureCount})。");
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -247,9 +267,26 @@ public partial class DeviceDetailsWindow : Window
|
|
|
|
|
|
|
|
transientFailureCount = 0;
|
|
transientFailureCount = 0;
|
|
|
var task = result.Data;
|
|
var task = result.Data;
|
|
|
- ShowStatusMessage($"任务 {task.TaskId} / {task.Status} / {task.Step} / {task.Detail}");
|
|
|
|
|
|
|
+ ShowStatusMessage(FormatTaskStatusMessage(task));
|
|
|
|
|
+ if (task.Status == "running" && task.Step == "confirming" && !confirmationRequested)
|
|
|
|
|
+ {
|
|
|
|
|
+ confirmationRequested = true;
|
|
|
|
|
+ var confirm = ShowApplyConfirmationDialog(ApplyConfirmationTimeoutSeconds);
|
|
|
|
|
+ if (confirm)
|
|
|
|
|
+ {
|
|
|
|
|
+ var confirmResult = await _agentApiService.ConfirmApplyTaskAsync(_baseAddress, _password, _localIPv4, taskId);
|
|
|
|
|
+ ShowStatusMessage(confirmResult.Success ? "已发送保留配置确认。" : $"发送确认失败:{confirmResult.Message}");
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ var cancelResult = await _agentApiService.CancelApplyTaskAsync(_baseAddress, _password, _localIPv4, taskId);
|
|
|
|
|
+ ShowStatusMessage(cancelResult.Success ? "已取消保留配置,正在回滚。" : $"发送取消失败:{cancelResult.Message}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (task.Status is "success" or "failed" or "rolled_back")
|
|
if (task.Status is "success" or "failed" or "rolled_back")
|
|
|
{
|
|
{
|
|
|
|
|
+ ShowTaskCompletionDialog(task);
|
|
|
if (RemoteTargetInterfaceComboBox.SelectedItem is RemoteInterfaceInfo selected)
|
|
if (RemoteTargetInterfaceComboBox.SelectedItem is RemoteInterfaceInfo selected)
|
|
|
{
|
|
{
|
|
|
await LoadRemoteInterfaceConfigAsync(selected.SystemName);
|
|
await LoadRemoteInterfaceConfigAsync(selected.SystemName);
|
|
@@ -262,6 +299,93 @@ public partial class DeviceDetailsWindow : Window
|
|
|
ShowStatusMessage($"任务 {taskId} 轮询超时,请稍后手动刷新。");
|
|
ShowStatusMessage($"任务 {taskId} 轮询超时,请稍后手动刷新。");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private bool ShowApplyConfirmationDialog(int timeoutSeconds)
|
|
|
|
|
+ {
|
|
|
|
|
+ var remaining = timeoutSeconds;
|
|
|
|
|
+ var result = false;
|
|
|
|
|
+ var messageTextBlock = new TextBlock
|
|
|
|
|
+ {
|
|
|
|
|
+ Width = 420,
|
|
|
|
|
+ TextWrapping = TextWrapping.Wrap,
|
|
|
|
|
+ FontSize = 13,
|
|
|
|
|
+ Foreground = Brushes.Black,
|
|
|
|
|
+ };
|
|
|
|
|
+ var confirmButton = new Button
|
|
|
|
|
+ {
|
|
|
|
|
+ MinWidth = 88,
|
|
|
|
|
+ MinHeight = 32,
|
|
|
|
|
+ Margin = new Thickness(0, 0, 10, 0),
|
|
|
|
|
+ Content = "确认保留",
|
|
|
|
|
+ IsDefault = true,
|
|
|
|
|
+ };
|
|
|
|
|
+ var cancelButton = new Button
|
|
|
|
|
+ {
|
|
|
|
|
+ MinWidth = 88,
|
|
|
|
|
+ MinHeight = 32,
|
|
|
|
|
+ Content = "取消回滚",
|
|
|
|
|
+ IsCancel = true,
|
|
|
|
|
+ };
|
|
|
|
|
+ var dialog = new Window
|
|
|
|
|
+ {
|
|
|
|
|
+ Title = "确认保留网络配置",
|
|
|
|
|
+ Owner = this,
|
|
|
|
|
+ WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
|
|
|
|
+ ResizeMode = ResizeMode.NoResize,
|
|
|
|
|
+ SizeToContent = SizeToContent.WidthAndHeight,
|
|
|
|
|
+ Content = new StackPanel
|
|
|
|
|
+ {
|
|
|
|
|
+ Margin = new Thickness(18),
|
|
|
|
|
+ Children =
|
|
|
|
|
+ {
|
|
|
|
|
+ messageTextBlock,
|
|
|
|
|
+ new StackPanel
|
|
|
|
|
+ {
|
|
|
|
|
+ Margin = new Thickness(0, 18, 0, 0),
|
|
|
|
|
+ HorizontalAlignment = HorizontalAlignment.Right,
|
|
|
|
|
+ Orientation = Orientation.Horizontal,
|
|
|
|
|
+ Children = { confirmButton, cancelButton },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ void UpdateMessage()
|
|
|
|
|
+ {
|
|
|
|
|
+ messageTextBlock.Text = $"当前客户端仍可连接到设备。是否确认保留这次网络配置?\n\n剩余 {remaining} 秒;超时或取消时,Linux 端会自动回滚。";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var timer = new System.Windows.Threading.DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
|
|
|
|
|
+ timer.Tick += (_, _) =>
|
|
|
|
|
+ {
|
|
|
|
|
+ remaining--;
|
|
|
|
|
+ if (remaining <= 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ timer.Stop();
|
|
|
|
|
+ dialog.DialogResult = false;
|
|
|
|
|
+ dialog.Close();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ UpdateMessage();
|
|
|
|
|
+ };
|
|
|
|
|
+ confirmButton.Click += (_, _) =>
|
|
|
|
|
+ {
|
|
|
|
|
+ result = true;
|
|
|
|
|
+ dialog.DialogResult = true;
|
|
|
|
|
+ dialog.Close();
|
|
|
|
|
+ };
|
|
|
|
|
+ cancelButton.Click += (_, _) =>
|
|
|
|
|
+ {
|
|
|
|
|
+ dialog.DialogResult = false;
|
|
|
|
|
+ dialog.Close();
|
|
|
|
|
+ };
|
|
|
|
|
+ dialog.Closed += (_, _) => timer.Stop();
|
|
|
|
|
+
|
|
|
|
|
+ UpdateMessage();
|
|
|
|
|
+ timer.Start();
|
|
|
|
|
+ dialog.ShowDialog();
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private async void RebootButton_OnClick(object sender, RoutedEventArgs e)
|
|
private async void RebootButton_OnClick(object sender, RoutedEventArgs e)
|
|
|
{
|
|
{
|
|
|
await ExecuteSystemActionAsync(
|
|
await ExecuteSystemActionAsync(
|
|
@@ -297,13 +421,15 @@ public partial class DeviceDetailsWindow : Window
|
|
|
|
|
|
|
|
private RemoteInterfaceConfig? BuildConfigRequest(string interfaceName)
|
|
private RemoteInterfaceConfig? BuildConfigRequest(string interfaceName)
|
|
|
{
|
|
{
|
|
|
- if (string.IsNullOrWhiteSpace(NewIpTextBox.Text))
|
|
|
|
|
|
|
+ var dhcp4 = Dhcp4CheckBox.IsChecked == true;
|
|
|
|
|
+ var prefix = 0;
|
|
|
|
|
+ if (!dhcp4 && string.IsNullOrWhiteSpace(NewIpTextBox.Text))
|
|
|
{
|
|
{
|
|
|
ShowStatusMessage("IP 地址不能为空。");
|
|
ShowStatusMessage("IP 地址不能为空。");
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (!TryMaskToPrefix(NewMaskTextBox.Text, out var prefix))
|
|
|
|
|
|
|
+ if (!dhcp4 && !TryMaskToPrefix(NewMaskTextBox.Text, out prefix))
|
|
|
{
|
|
{
|
|
|
ShowStatusMessage("子网掩码格式不正确。");
|
|
ShowStatusMessage("子网掩码格式不正确。");
|
|
|
return null;
|
|
return null;
|
|
@@ -313,13 +439,25 @@ public partial class DeviceDetailsWindow : Window
|
|
|
return new RemoteInterfaceConfig
|
|
return new RemoteInterfaceConfig
|
|
|
{
|
|
{
|
|
|
Interface = interfaceName,
|
|
Interface = interfaceName,
|
|
|
- IP = NewIpTextBox.Text.Trim(),
|
|
|
|
|
|
|
+ Dhcp4 = dhcp4,
|
|
|
|
|
+ IP = dhcp4 ? string.Empty : NewIpTextBox.Text.Trim(),
|
|
|
Prefix = prefix,
|
|
Prefix = prefix,
|
|
|
- Gateway = NewGatewayTextBox.Text.Trim(),
|
|
|
|
|
- Dns = dns,
|
|
|
|
|
|
|
+ Gateway = dhcp4 ? string.Empty : NewGatewayTextBox.Text.Trim(),
|
|
|
|
|
+ Dns = dhcp4 ? Array.Empty<string>() : dns,
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private static string FormatCurrentIp(RemoteInterfaceConfig config)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (string.IsNullOrWhiteSpace(config.IP))
|
|
|
|
|
+ {
|
|
|
|
|
+ return config.Dhcp4 ? "DHCP 自动获取,暂无 IPv4" : "无";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var text = $"{config.IP}/{config.Prefix}";
|
|
|
|
|
+ return config.Dhcp4 ? $"{text} (DHCP)" : text;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private static string PrefixToMask(int prefix)
|
|
private static string PrefixToMask(int prefix)
|
|
|
{
|
|
{
|
|
|
if (prefix < 0 || prefix > 32)
|
|
if (prefix < 0 || prefix > 32)
|
|
@@ -390,6 +528,19 @@ public partial class DeviceDetailsWindow : Window
|
|
|
UpdateButtonStates();
|
|
UpdateButtonStates();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private void ConfigModeChanged_OnChanged(object sender, RoutedEventArgs e)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (_suppressConfigChangeHandling)
|
|
|
|
|
+ {
|
|
|
|
|
+ UpdateButtonStates();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ _configValidated = false;
|
|
|
|
|
+ ShowStatusMessage("配置模式已变更,请重新点击“2. 校验配置”。");
|
|
|
|
|
+ UpdateButtonStates();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private void ShowStatusMessage(string message)
|
|
private void ShowStatusMessage(string message)
|
|
|
{
|
|
{
|
|
|
ApplyStatusMessageStyle(message);
|
|
ApplyStatusMessageStyle(message);
|
|
@@ -457,6 +608,33 @@ public partial class DeviceDetailsWindow : Window
|
|
|
return markers.Any(marker => message.Contains(marker, StringComparison.Ordinal));
|
|
return markers.Any(marker => message.Contains(marker, StringComparison.Ordinal));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private static string FormatTaskStatusMessage(RemoteTaskResult task)
|
|
|
|
|
+ {
|
|
|
|
|
+ return task.Status switch
|
|
|
|
|
+ {
|
|
|
|
|
+ "success" => string.IsNullOrWhiteSpace(task.Detail) ? "配置已成功应用。" : task.Detail,
|
|
|
|
|
+ "failed" => string.IsNullOrWhiteSpace(task.Detail) ? "配置应用失败。" : task.Detail,
|
|
|
|
|
+ "rolled_back" => string.IsNullOrWhiteSpace(task.Detail) ? "配置应用失败,已自动回滚。" : task.Detail,
|
|
|
|
|
+ _ => task.Step switch
|
|
|
|
|
+ {
|
|
|
|
|
+ "validating" => "正在校验配置...",
|
|
|
|
|
+ "writing_netplan" => "正在写入 Linux 网络配置...",
|
|
|
|
|
+ "applying" => "正在应用 Linux 网络配置...",
|
|
|
|
|
+ "confirming" => string.IsNullOrWhiteSpace(task.Detail) ? "等待确认保留配置..." : task.Detail,
|
|
|
|
|
+ "rolling_back" => "配置应用失败,正在自动回滚...",
|
|
|
|
|
+ _ => string.IsNullOrWhiteSpace(task.Detail) ? "正在处理,请稍候..." : task.Detail,
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void ShowTaskCompletionDialog(RemoteTaskResult task)
|
|
|
|
|
+ {
|
|
|
|
|
+ var message = FormatTaskStatusMessage(task);
|
|
|
|
|
+ var title = task.Status == "success" ? "应用配置成功" : "应用配置失败";
|
|
|
|
|
+ var image = task.Status == "success" ? MessageBoxImage.Information : MessageBoxImage.Warning;
|
|
|
|
|
+ MessageBox.Show(this, message, title, MessageBoxButton.OK, image);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private void UpdateButtonStates()
|
|
private void UpdateButtonStates()
|
|
|
{
|
|
{
|
|
|
var hasSelectedInterface = RemoteTargetInterfaceComboBox.SelectedItem is RemoteInterfaceInfo;
|
|
var hasSelectedInterface = RemoteTargetInterfaceComboBox.SelectedItem is RemoteInterfaceInfo;
|
|
@@ -466,10 +644,11 @@ public partial class DeviceDetailsWindow : Window
|
|
|
ReloadInterfaceConfigButton.IsEnabled = canEdit;
|
|
ReloadInterfaceConfigButton.IsEnabled = canEdit;
|
|
|
ValidateConfigButton.IsEnabled = canEdit;
|
|
ValidateConfigButton.IsEnabled = canEdit;
|
|
|
ApplyConfigButton.IsEnabled = !_isBusy && _configValidated && hasSelectedInterface;
|
|
ApplyConfigButton.IsEnabled = !_isBusy && _configValidated && hasSelectedInterface;
|
|
|
- NewIpTextBox.IsEnabled = canEdit;
|
|
|
|
|
- NewMaskTextBox.IsEnabled = canEdit;
|
|
|
|
|
- NewGatewayTextBox.IsEnabled = canEdit;
|
|
|
|
|
- NewDnsTextBox.IsEnabled = canEdit;
|
|
|
|
|
|
|
+ Dhcp4CheckBox.IsEnabled = canEdit;
|
|
|
|
|
+ NewIpTextBox.IsEnabled = canEdit && Dhcp4CheckBox.IsChecked != true;
|
|
|
|
|
+ NewMaskTextBox.IsEnabled = canEdit && Dhcp4CheckBox.IsChecked != true;
|
|
|
|
|
+ NewGatewayTextBox.IsEnabled = canEdit && Dhcp4CheckBox.IsChecked != true;
|
|
|
|
|
+ NewDnsTextBox.IsEnabled = canEdit && Dhcp4CheckBox.IsChecked != true;
|
|
|
RebootButton.IsEnabled = !_isBusy;
|
|
RebootButton.IsEnabled = !_isBusy;
|
|
|
ShutdownButton.IsEnabled = !_isBusy;
|
|
ShutdownButton.IsEnabled = !_isBusy;
|
|
|
}
|
|
}
|