public void Unload() { if (Loaded) { Plugin.Log.Notice("Object Manager Unloading..."); Alerts.ToList().ForEach(a => { a.Destroy(); Plugin.Log.Info("Destroyed: " + a.FileName); }); Alerts.Clear(); CustomAlertFiles = Enumerable.Empty <string>(); Loaded = false; } }
private void ResetState() { LiveAccounts.Clear(); DemoAccounts.Clear(); Accounts.Clear(); accountsByName.Clear(); Bots.Clear(); Alerts.Clear(); Sessions.Clear(); State = ExecutionStateEx.Uninitialized; }
private void UpdateAlerts() { Server.Value.DocumentStore.OpenAsyncSession(Server.Value.SelectedDatabase.Value.Name).LoadAsync <AlertsDocument>(Constants.RavenAlerts).ContinueOnSuccessInTheUIThread( alertsDoc => { Alerts.Clear(); if (alertsDoc != null) { foreach (var alert in alertsDoc.Alerts) { Alerts.Add(alert); } } OnPropertyChanged(() => Alerts); OnPropertyChanged(() => UnOnserverdAlerts); OnPropertyChanged(() => AlertsTitle); }); }
private void RegisterToChanges() { ShowObserved.PropertyChanged += (sender, args) => { AlertsToSee = ShowObserved.Value ? Alerts : UnobservedAlerts; OnPropertyChanged(() => AlertsToSee); }; ServerAlerts.CollectionChanged += (sender, args) => { Alerts.Clear(); foreach (var serverAlert in ServerAlerts) { Alerts.Add(new AlertProxy(serverAlert)); } }; ShowObserved.Value = false; Alerts.CollectionChanged += (sender, args) => UpdateUnobserved(); OnPropertyChanged(() => ServerAlerts); }
public async Task ValidateAzureResources() { Alerts.Clear(); if (this.TargetSubscription == null) { this.AddAlert(AlertType.Error, "Target Azure Subscription must be provided for template generation.", this.ResourceGroup); } else { if (this.TargetSubscription.Locations == null || this.TargetSubscription.Locations.Count() == 0) { this.AddAlert(AlertType.Error, "Target Azure Subscription must have one or more Locations instantiated.", this.ResourceGroup); } } if (this.ResourceGroup == null) { this.AddAlert(AlertType.Error, "Target Resource Group must be provided for template generation.", this.ResourceGroup); } else { if (this.ResourceGroup.TargetLocation == null) { this.AddAlert(AlertType.Error, "Target Resource Group Location must be provided for template generation.", this.ResourceGroup); } else { // It is possible that the Target Location is no longer in the Target Subscription // Sample case, user first connected to Azure Commercial as source (and set as initial target) // but then logged into a different account for the target and target is now USGov. if (this.TargetSubscription != null && this.TargetSubscription.Locations != null) { if (!this.TargetSubscription.Locations.Contains(this.ResourceGroup.TargetLocation)) { this.AddAlert(AlertType.Error, "Target Resource Group Location '" + this.ResourceGroup.TargetLocation.ToString() + "' is not available in Subscription '" + this.TargetSubscription.ToString() + "'. Select a new Target Location.", this.ResourceGroup); } } } } foreach (MigrationTarget.StorageAccount targetStorageAccount in this.StorageAccounts) { await targetStorageAccount.CheckNameAvailability(this.TargetSubscription); if (!targetStorageAccount.IsNameAvailable) { this.AddAlert(AlertType.Error, "Target Name for Storage Account '" + targetStorageAccount.ToString() + "' already exists within Azure Environment " + this.TargetSubscription.AzureEnvironment.ToString() + ". A new (available) target name must be specified.", targetStorageAccount); } if (targetStorageAccount.BlobStorageNamespace == null || targetStorageAccount.BlobStorageNamespace.Trim().Length <= 0) { this.AddAlert(AlertType.Error, "Blob Storage Namespace for Target Storage Account '" + targetStorageAccount.ToString() + "' must be specified.", targetStorageAccount); } if (!this.IsStorageAccountVmDiskTarget(targetStorageAccount)) { this.AddAlert(AlertType.Warning, "Target Storage Account '" + targetStorageAccount.ToString() + "' is not utilized within this Resource Group Deployment as a Virtual Machine Disk Target. Consider removing to avoid creation of a non-utilized Storage Account.", targetStorageAccount); } } foreach (MigrationTarget.VirtualNetwork targetVirtualNetwork in this.VirtualNetworks) { foreach (MigrationTarget.Subnet targetSubnet in targetVirtualNetwork.TargetSubnets) { if (targetSubnet.NetworkSecurityGroup != null) { MigrationTarget.NetworkSecurityGroup networkSecurityGroupInMigration = this.SeekNetworkSecurityGroup(targetSubnet.NetworkSecurityGroup.ToString()); if (networkSecurityGroupInMigration == null) { this.AddAlert(AlertType.Error, "Virtual Network '" + targetVirtualNetwork.ToString() + "' Subnet '" + targetSubnet.ToString() + "' utilizes Network Security Group (NSG) '" + targetSubnet.NetworkSecurityGroup.ToString() + "', but the NSG resource is not added into the migration template.", targetSubnet); } } } } foreach (MigrationTarget.NetworkSecurityGroup targetNetworkSecurityGroup in this.NetworkSecurityGroups) { if (targetNetworkSecurityGroup.TargetName == string.Empty) { this.AddAlert(AlertType.Error, "Target Name for Network Security Group must be specified.", targetNetworkSecurityGroup); } } foreach (MigrationTarget.LoadBalancer targetLoadBalancer in this.LoadBalancers) { if (targetLoadBalancer.TargetName == string.Empty) { this.AddAlert(AlertType.Error, "Target Name for Load Balancer must be specified.", targetLoadBalancer); } if (targetLoadBalancer.FrontEndIpConfigurations.Count == 0) { this.AddAlert(AlertType.Error, "Load Balancer must have a FrontEndIpConfiguration.", targetLoadBalancer); } else { if (targetLoadBalancer.LoadBalancerType == MigrationTarget.LoadBalancerType.Internal) { if (targetLoadBalancer.FrontEndIpConfigurations.Count > 0) { if (targetLoadBalancer.FrontEndIpConfigurations[0].TargetSubnet == null) { this.AddAlert(AlertType.Error, "Internal Load Balancer must have an internal Subnet association.", targetLoadBalancer); } else { // russell if (targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIPAllocationMethod == IPAllocationMethodEnum.Static) { if (!IPv4CIDR.IsIpAddressInAddressPrefix(targetLoadBalancer.FrontEndIpConfigurations[0].TargetSubnet.AddressPrefix, targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress)) { this.AddAlert(AlertType.Error, "Load Balancer '" + targetLoadBalancer.ToString() + "' IP Address '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress + "' is not valid within Subnet '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetSubnet.ToString() + "' Address Prefix '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetSubnet.AddressPrefix + "'.", targetLoadBalancer); } else { if (targetLoadBalancer.FrontEndIpConfigurations[0].TargetVirtualNetwork != null && targetLoadBalancer.FrontEndIpConfigurations[0].TargetVirtualNetwork.GetType() == typeof(Azure.Arm.VirtualNetwork) && IPv4CIDR.IsValidIpAddress(targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress) // Only worth passing to Azure for Availability validation if the IP address is valid. ) { Arm.VirtualNetwork armVirtualNetwork = (Arm.VirtualNetwork)targetLoadBalancer.FrontEndIpConfigurations[0].TargetVirtualNetwork; (bool isAvailable, List <String> availableIps) = await armVirtualNetwork.IsIpAddressAvailable(targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress); if (!isAvailable) { this.AddAlert(AlertType.Error, "Load Balancer '" + targetLoadBalancer.ToString() + "' IP Address '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress + "' is not available within Virtual Network '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetVirtualNetwork.ToString() + "'.", targetLoadBalancer); } } } } } } } else { if (targetLoadBalancer.FrontEndIpConfigurations[0].PublicIp == null) { this.AddAlert(AlertType.Error, "Public Load Balancer must have either a Public IP association.", targetLoadBalancer); } else { // Ensure the selected Public IP Address is "in the migration" as a target new Public IP Object bool publicIpExistsInMigration = false; foreach (Azure.MigrationTarget.PublicIp publicIp in this.PublicIPs) { if (publicIp.TargetName == targetLoadBalancer.FrontEndIpConfigurations[0].PublicIp.TargetName) { publicIpExistsInMigration = true; break; } } if (!publicIpExistsInMigration) { this.AddAlert(AlertType.Error, "Public IP '" + targetLoadBalancer.FrontEndIpConfigurations[0].PublicIp.TargetName + "' specified for Load Balancer '" + targetLoadBalancer.ToString() + "' is not included in the migration template.", targetLoadBalancer); } } } } } foreach (Azure.MigrationTarget.AvailabilitySet availablitySet in this.AvailablitySets) { if (availablitySet.TargetVirtualMachines.Count == 0) { this.AddAlert(AlertType.Error, "Availability Set '" + availablitySet.ToString() + "' does not contain any Virtual Machines. Remove the Availability Set from the Target Resources for export or associate Virtual Machines to the Availability Set.", availablitySet); } else if (availablitySet.TargetVirtualMachines.Count == 1) { this.AddAlert(AlertType.Warning, "Availability Set '" + availablitySet.ToString() + "' only contains a single VM. Only utilize an Availability Set if additional VMs will be added; otherwise, a single VM instance should not reside within an Availability Set.", availablitySet); } if (!availablitySet.IsManagedDisks && !availablitySet.IsUnmanagedDisks) { this.AddAlert(AlertType.Error, "All OS and Data Disks for Virtual Machines contained within Availablity Set '" + availablitySet.ToString() + "' should be either Unmanaged Disks or Managed Disks for consistent deployment.", availablitySet); } } foreach (Azure.MigrationTarget.VirtualMachine virtualMachine in this.VirtualMachines) { if (virtualMachine.TargetName == string.Empty) { this.AddAlert(AlertType.Error, "Target Name for Virtual Machine '" + virtualMachine.ToString() + "' must be specified.", virtualMachine); } if (virtualMachine.TargetAvailabilitySet == null) { if (virtualMachine.OSVirtualHardDisk.TargetStorage != null && virtualMachine.OSVirtualHardDisk.TargetStorage.StorageAccountType != StorageAccountType.Premium_LRS) { this.AddAlert(AlertType.Warning, "Virtual Machine '" + virtualMachine.ToString() + "' is not part of an Availability Set. OS Disk should be migrated to Azure Premium Storage to receive an Azure SLA for single server deployments. Existing configuration will receive no (0%) Service Level Agreement (SLA).", virtualMachine.OSVirtualHardDisk); } foreach (Azure.MigrationTarget.Disk dataDisk in virtualMachine.DataDisks) { if (dataDisk.TargetStorage != null && dataDisk.TargetStorage.StorageAccountType != StorageAccountType.Premium_LRS) { this.AddAlert(AlertType.Warning, "Virtual Machine '" + virtualMachine.ToString() + "' is not part of an Availability Set. Data Disk '" + dataDisk.ToString() + "' should be migrated to Azure Premium Storage to receive an Azure SLA for single server deployments. Existing configuration will receive no (0%) Service Level Agreement (SLA).", dataDisk); } } } else { bool virtualMachineAvailabitySetExists = false; foreach (MigrationTarget.AvailabilitySet targetAvailabilitySet in this.AvailablitySets) { if (targetAvailabilitySet.ToString() == virtualMachine.TargetAvailabilitySet.ToString()) { virtualMachineAvailabitySetExists = true; } } if (!virtualMachineAvailabitySetExists) { this.AddAlert(AlertType.Error, "Virtual Machine '" + virtualMachine.ToString() + "' utilizes Availability Set '" + virtualMachine.TargetAvailabilitySet.ToString() + "'; however, the Availability Set is not included in the Export.", virtualMachine); } } if (virtualMachine.TargetSize == null) { this.AddAlert(AlertType.Error, "Target Size for Virtual Machine '" + virtualMachine.ToString() + "' must be specified.", virtualMachine); } else { // Ensure that the selected target size is available in the target Azure Location if (this.ResourceGroup != null && this.ResourceGroup.TargetLocation != null) { if (this.ResourceGroup.TargetLocation.VMSizes == null || this.ResourceGroup.TargetLocation.VMSizes.Count == 0) { this.AddAlert(AlertType.Error, "No ARM VM Sizes are available for Azure Location '" + this.ResourceGroup.TargetLocation.DisplayName + "'.", virtualMachine); } else { // Ensure selected target VM Size is available in the Target Azure Location Arm.VMSize matchedVmSize = this.ResourceGroup.TargetLocation.SeekVmSize(virtualMachine.TargetSize.Name); if (matchedVmSize == null) { this.AddAlert(AlertType.Error, "Specified VM Size '" + virtualMachine.TargetSize.Name + "' for Virtual Machine '" + virtualMachine.ToString() + "' is invalid as it is not available in Azure Location '" + this.ResourceGroup.TargetLocation.DisplayName + "'.", virtualMachine); } } } if (virtualMachine.OSVirtualHardDisk.TargetStorage.StorageAccountType == StorageAccountType.Premium_LRS && !virtualMachine.TargetSize.IsStorageTypeSupported(virtualMachine.OSVirtualHardDisk.StorageAccountType)) { this.AddAlert(AlertType.Error, "Premium Disk based Virtual Machines must be of VM Series 'B', 'DS', 'DS v2', 'DS v3', 'GS', 'GS v2', 'Ls' or 'Fs'.", virtualMachine); } } foreach (Azure.MigrationTarget.NetworkInterface networkInterface in virtualMachine.NetworkInterfaces) { // Seek the inclusion of the Network Interface in the export object bool networkInterfaceExistsInExport = false; foreach (Azure.MigrationTarget.NetworkInterface targetNetworkInterface in this.NetworkInterfaces) { if (String.Compare(networkInterface.SourceName, targetNetworkInterface.SourceName, true) == 0) { networkInterfaceExistsInExport = true; break; } } if (!networkInterfaceExistsInExport) { this.AddAlert(AlertType.Error, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' is used by Virtual Machine '" + virtualMachine.ToString() + "', but is not included in the exported resources.", virtualMachine); } if (virtualMachine.TargetSize != null) { if (networkInterface.EnableAcceleratedNetworking && !virtualMachine.TargetSize.IsAcceleratedNetworkingSupported) { this.AddAlert(AlertType.Error, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' has Accelerated Networking enabled, but the Virtual Machine must be of VM Series 'D', 'DSv2', 'DSv3', 'E', 'ESv3', 'F', 'FS', 'FSv2', 'Ms' or 'Mms' to support Accelerated Networking.", networkInterface); } else if (!networkInterface.EnableAcceleratedNetworking && virtualMachine.TargetSize.IsAcceleratedNetworkingSupported) { this.AddAlert(AlertType.Recommendation, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' has Accelerated Networking disabled and the Virtual Machine Size '" + virtualMachine.TargetSize.ToString() + "' can support Accelerated Networking. Consider enabling Accelerated Networking.", networkInterface); } } if (networkInterface.NetworkSecurityGroup != null) { MigrationTarget.NetworkSecurityGroup networkSecurityGroupInMigration = this.SeekNetworkSecurityGroup(networkInterface.NetworkSecurityGroup.ToString()); if (networkSecurityGroupInMigration == null) { this.AddAlert(AlertType.Error, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' utilizes Network Security Group (NSG) '" + networkInterface.NetworkSecurityGroup.ToString() + "', but the NSG resource is not added into the migration template.", networkInterface); } } foreach (Azure.MigrationTarget.NetworkInterfaceIpConfiguration ipConfiguration in networkInterface.TargetNetworkInterfaceIpConfigurations) { if (ipConfiguration.TargetVirtualNetwork == null) { this.AddAlert(AlertType.Error, "Target Virtual Network for Virtual Machine '" + virtualMachine.ToString() + "' Network Interface '" + networkInterface.ToString() + "' must be specified.", networkInterface); } else { if (ipConfiguration.TargetVirtualNetwork.GetType() == typeof(MigrationTarget.VirtualNetwork)) { MigrationTarget.VirtualNetwork virtualMachineTargetVirtualNetwork = (MigrationTarget.VirtualNetwork)ipConfiguration.TargetVirtualNetwork; bool targetVNetExists = false; foreach (MigrationTarget.VirtualNetwork targetVirtualNetwork in this.VirtualNetworks) { if (targetVirtualNetwork.TargetName == virtualMachineTargetVirtualNetwork.TargetName) { targetVNetExists = true; break; } } if (!targetVNetExists) { this.AddAlert(AlertType.Error, "Target Virtual Network '" + virtualMachineTargetVirtualNetwork.ToString() + "' for Virtual Machine '" + virtualMachine.ToString() + "' Network Interface '" + networkInterface.ToString() + "' is invalid, as it is not included in the migration / template. Either include the source Virtual Network in the Migration Template (if this is the first time migration needing a new ARM Virtual Network), or select an existing ARM Virtual Network and Subnet to migrate the Virtual Machine into.", networkInterface); } } } if (ipConfiguration.TargetSubnet == null) { this.AddAlert(AlertType.Error, "Target Subnet for Virtual Machine '" + virtualMachine.ToString() + "' Network Interface '" + networkInterface.ToString() + "' must be specified.", networkInterface); } else { if (!IPv4CIDR.IsValidCIDR(ipConfiguration.TargetSubnet.AddressPrefix)) { this.AddAlert(AlertType.Error, "Target Subnet '" + ipConfiguration.TargetSubnet.ToString() + "' used by Virtual Machine '" + virtualMachine.ToString() + "' has an invalid IPv4 Address Prefix: " + ipConfiguration.TargetSubnet.AddressPrefix, ipConfiguration.TargetSubnet); } else { if (ipConfiguration.TargetPrivateIPAllocationMethod == IPAllocationMethodEnum.Static) { if (!IPv4CIDR.IsIpAddressInAddressPrefix(ipConfiguration.TargetSubnet.AddressPrefix, ipConfiguration.TargetPrivateIpAddress)) { this.AddAlert(AlertType.Error, "Target IP Address '" + ipConfiguration.TargetPrivateIpAddress + "' is not valid in Subnet '" + ipConfiguration.TargetSubnet.ToString() + "' Address Prefix '" + ipConfiguration.TargetSubnet.AddressPrefix + "'.", networkInterface); } } } } if (ipConfiguration.TargetPublicIp != null) { MigrationTarget.PublicIp publicIpInMigration = this.SeekPublicIp(ipConfiguration.TargetPublicIp.ToString()); if (publicIpInMigration == null) { this.AddAlert(AlertType.Error, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' IP Configuration '" + ipConfiguration.ToString() + "' utilizes Public IP '" + ipConfiguration.TargetPublicIp.ToString() + "', but the Public IP resource is not added into the migration template.", networkInterface); } } } } ValidateVMDisk(virtualMachine.OSVirtualHardDisk); foreach (MigrationTarget.Disk dataDisk in virtualMachine.DataDisks) { ValidateVMDisk(dataDisk); if (!dataDisk.Lun.HasValue || dataDisk.Lun.Value == -1) { this.AddAlert(AlertType.Error, "Data Disk '" + dataDisk.ToString() + "' must have a valid LUN Index assigned.", dataDisk); } else { if (dataDisk.Lun > virtualMachine.TargetSize.maxDataDiskCount - 1) { this.AddAlert(AlertType.Error, "Data Disk '" + dataDisk.ToString() + "' LUN index " + dataDisk.Lun.Value.ToString() + " exceeds the maximum LUN of " + (virtualMachine.TargetSize.maxDataDiskCount - 1).ToString() + " allowed by VM Size '" + virtualMachine.TargetSize.ToString() + "'.", dataDisk); } int lunCount = virtualMachine.DataDisks.Where(a => a.Lun == dataDisk.Lun).Count(); if (lunCount > 1) { this.AddAlert(AlertType.Error, "Multiple data disks are assigned to LUN " + dataDisk.Lun.ToString() + " on Virtual Machine '" + virtualMachine.ToString() + "'. Data Disk LUNs must be unique.", dataDisk); } } } if (!virtualMachine.IsManagedDisks && !virtualMachine.IsUnmanagedDisks) { this.AddAlert(AlertType.Error, "All OS and Data Disks for Virtual Machine '" + virtualMachine.ToString() + "' should be either Unmanaged Disks or Managed Disks for consistent deployment.", virtualMachine); } } foreach (Azure.MigrationTarget.Disk targetDisk in this.Disks) { ValidateDiskStandards(targetDisk); } // todo now asap - Add test for NSGs being present in Migration //MigrationTarget.NetworkSecurityGroup targetNetworkSecurityGroup = (MigrationTarget.NetworkSecurityGroup)this.SeekNetworkSecurityGroup(targetSubnet.NetworkSecurityGroup.ToString()); //if (targetNetworkSecurityGroup == null) //{ // this.AddAlert(AlertType.Error, "Subnet '" + subnet.name + "' utilized ASM Network Security Group (NSG) '" + targetSubnet.NetworkSecurityGroup.ToString() + "', which has not been added to the ARM Subnet as the NSG was not included in the ARM Template (was not selected as an included resources for export).", targetNetworkSecurityGroup); //} // todo add error if existing target disk storage is not in the same data center / region as vm. if (AfterResourceValidation != null) { await AfterResourceValidation.Invoke(); } }
public AlertsViewModel(IAlertService alertService, IUserDialogs userDialogs, IMvxMessenger mvxMessenger, AppHelper appHelper) : base(userDialogs, mvxMessenger, appHelper) { _alertService = alertService; ClearAlertsCommand = ReactiveCommand .CreateFromObservable <Unit, string>((param) => { return(_appHelper.RequestConfirmation(AppResources.Alerts_Confirm_Clear) .Do((_) => _userDialogs.ShowLoading(AppResources.Alerts_Deleting_Alerts)) .SelectMany((_) => string.IsNullOrEmpty(SonIdentity) ? _alertService.ClearSelfAlerts() : _alertService.ClearAlertsOfSon(SonIdentity)) .Do((_) => _userDialogs.HideLoading())); }); ClearAlertsCommand.Subscribe((alertsDeleted) => { Debug.WriteLine("Alerts Deleted -> " + alertsDeleted); Alerts.Clear(); DataFound = false; }); ClearAlertsCommand.ThrownExceptions.Subscribe(HandleExceptions); RefreshCommand = ReactiveCommand .CreateFromObservable <Unit, IList <AlertEntity> >((param) => { if (PopupNavigation.PopupStack.Count > 0) { PopupNavigation.PopAllAsync(); } return(string.IsNullOrEmpty(SonIdentity) ? alertService.GetSelfAlerts(CountAlertsOption.Value, AntiquityOfAlertsOption.Value, AlertLevelFilter) : _alertService.GetAlertsBySon(SonIdentity, CountAlertsOption.Value, AntiquityOfAlertsOption.Value, AlertLevelFilter)); }); RefreshCommand.Subscribe((AlertsEntities) => { Alerts.ReplaceRange(AlertsEntities); ResetCommonProps(); }); RefreshCommand.IsExecuting.Subscribe((IsLoading) => IsBusy = IsLoading); RefreshCommand.ThrownExceptions.Subscribe(HandleExceptions); DeleteAlertCommand = ReactiveCommand .CreateFromObservable <AlertEntity, string>((AlertEntity) => alertService.DeleteAlertOfSon(AlertEntity.Son.Identity, AlertEntity.Identity) .Do((_) => Alerts.Remove(AlertEntity))); DeleteAlertCommand.IsExecuting.Subscribe((IsLoading) => IsBusy = IsLoading); DeleteAlertCommand.Subscribe((_) => { _userDialogs.ShowSuccess(AppResources.Alerts_Deleted); if (Alerts.Count() == 0) { DataFound = false; } }); DeleteAlertCommand.ThrownExceptions.Subscribe(HandleExceptions); AllCategory.PropertyChanged += (sender, e) => { if (e.PropertyName == "IsFiltered") { foreach (var category in AlertsLevelCategories) { category.IsEnabled = !AllCategory.IsFiltered; if (AllCategory.IsFiltered) { category.IsFiltered = true; } } } }; foreach (AlertCategoryModel AlertCategory in AlertsLevelCategories) { AlertCategory.PropertyChanged += (sender, e) => { if (e.PropertyName == "IsFiltered") { var AlertCategoryModel = sender as AlertCategoryModel; UpdateAlertFilter(AlertCategoryModel); } }; } }