Метод с generi c и несколькими параметрами - PullRequest
2 голосов
/ 07 апреля 2020

Я хочу включить / отключить элементы управления в приложении Windows Forms в соответствии с привилегиями пользователя.

Сначала я подумал о написании метода в каждом классе форм, который проверял бы учетные данные пользователя, а затем включал / отключить его элементы управления. Но потом я понял, что могу (возможно) создать метод класса stati c, который будет принимать форму в качестве параметра и выполнять работу.

Поэтому я начал писать его, предполагая, что иногда мне хотелось бы включить элементы управления одной или двух панелей, а не всей формы. Итак, мне нужны следующие параметры:

  • различное количество панелей и / или
  • класс формы.

Мои трудности с этой задачей в том, что я получаю сообщение об ошибке, пытаясь изменить аргумент панели, и я понятия не имею, как установить параметр, который может принимать любой класс формы. Все мои классы форм, очевидно, наследуются от класса Formi c, но я не знаю, как это применить.

Вот что я получил:

public static void Enable(TableLayoutPanel[] containers = null)
    {
        if (MyOF.isEnabled)
        {
            return;
        }
        else
        {
            try
            {
                foreach (TableLayoutPanel table in containers)
                {
                    foreach (Control control in table.Controls)
                    {
                        control.Enabled = false;
                    }
                }
            }
            catch (NullReferenceException)
            {
            }
        }
    }

Ответы [ 3 ]

1 голос
/ 07 апреля 2020

Один из простых способов, которым я могу думать о том, что вы пытаетесь сделать, заключается в следующем. Позвольте мне уйти отсюда c. Я работал над проектами, в которых все элементы управления форм были построены из метаданных. И мета пришла с информацией о лицензировании. Таким образом, когда элемент управления был размещен там, где он должен, он также был отключен или установлен только для чтения на основе метаданных, но вся функция была бы скрыта, если информация о лицензировании ограничивала доступ к нему. Возвращаясь к вашему подходу, это не плохой подход, и я вижу, что это можно сделать. И это можно сделать двумя способами (быстро из моей головы).

  1. Использование пользовательских элементов управления в качестве поверхности для компонентов, которые вы хотите включить / отключить. Создайте интерфейс
public interface IDisableableControl // make your fine name, no methods needed - marker interface
 . .  . . . 
public class MyFineUserControl : UserControl, IDisableableControl 

И в вашем static методе, который вы собираетесь написать, передайте форму, найдите все элементы управления, которые реализуют этот интерфейс, и работайте так, как вы хотите.

2. Точно так же вы можете использовать свойство Tag, которое доступно для каждого элемента управления. При этом вы можете фактически установить свой сложный объект безопасности, который может поступать из метаданных, хранящихся в БД, а затем оценить этот объект, хранящийся в Tag, для применения вашей конфигурации

Ваш метод должен быть рекурсивным

internal static void SetAllControls(Control parent)
{
    // Do something with control, for example parent.Enabled = false
    if (parent is IDisableableControl)
    {
       // here you use your logic, evaluate your parent you're dialing with and
       // enable/disable correspondingly 
       parent.Enabled = false;
       return;
    }
    foreach(var c in parent.Controls)
        SetAllControls(c);
} 

В реальной жизни ваш ТОП-родитель будет формой, и его не нужно будет отключать, но это точно будут дети. Фактически, в большинстве случаев, когда вы находите UserControl, который реализует IDisableableControl, который должен быть концом строки, это означает, что вам не нужно go в дочерних элементах управления, так как все они находятся на этом родительском элементе и все будет отключен

1 голос
/ 07 апреля 2020

Если мы помним, что класс Form является производным от Control (косвенно, производным от ContainerControl, который происходит от ScrollableControl, который происходит от Control), а свойство Enabled принадлежит Control class, мы можем написать метод, который включит любого дочернего элемента управления (включая элементы управления Form или TableLayoutPanel), так как коллекция Controls также принадлежит классу Control:

public static void EnableChildren(Control control, bool enabled = true)
{
    foreach (Control child in control.Controls)
    {
        child.Enabled = enabled;
    }
}

И затем, если мы также хотим иметь возможность использовать это с набором элементов управления (как в вашем примере), мы можем написать перегрузку, которая принимает набор:

public static void EnableChildren(IEnumerable<Control> controls = null, 
    bool enabled = true)
{
    if (controls == null) return;

    foreach (var control in controls)
    {
        EnableChildren(control, enabled);
    }
}

Теперь мы можем использовать это с Form или набором TableLayoutPanel элементов управления (или любым элементом управления, у которого есть элементы управления в его Controls коллекции).

Примеры использования:

var myForm = new Form1();

EnableChildren(this);     // 'this' is the current form
EnableChildren(myForm);   // a separate instance of a form control
EnableChildren(tableLayoutPanel1, false);  // A single TableLayoutPanel control

var tableLayoutPanels = new [] {tableLayoutPanel1, tableLayoutPanel2, tableLayoutPanel3};
EnableChildren(tableLayoutPanels);  // An array of tableLayoutPanel controls
0 голосов
/ 07 апреля 2020

Мне удается выполнить sh то, что я пытался сделать с помощью приведенного ниже кода, который представляет собой смесь всех полезных ответов, которые я получил:

public static void EnableContainer(params Control[] containers)
    {
        if(containers.Count() == 0) { return; }
        if (MyOF.isEnabled)
        {
            return;
        }
        else
        {
            try
            {
                foreach (var container in containers)
                {
                    foreach (Control control in container.Controls)
                    {
                        control.Enabled = false;
                    }
                }
            }
            catch (NullReferenceException)
            {
            }
        }
    }
    public static void EnableForm<form>(form f) where form : Form
    {
        if (MyOF.isEnabled)
        {
            return;
        }
        else
        {
            foreach(Control control in f.Controls)
            {
                control.Enabled = false;
            }
        }
    }

Сообщество может предложить улучшения, поскольку я далеко не профессиональный программист. Спасибо всем еще раз.

...