Как вызвать с действием? - PullRequest
0 голосов
/ 28 апреля 2009

Я всегда устанавливаю модификаторы в моей форме на private , мне не нравятся внутренние и публичные.

До сих пор я вызывал так:

public string Addtext
{
    if(InvokeRequired)
    {
         Invoke((MethodInvoker)delegate
         {
             textbox.text = value;
         });
    }
    else
        textbox.text = value;
}

Но добавление такого свойства для каждого члена моей формы просто не является объектно-ориентированным.

Я хочу создать функцию, которая будет вызывать параметр (действие). Я старался изо всех сил, но мне это не удалось - для этого необходимо, чтобы члены формы были public или internal : (

    public void PerformActionOnForm(Action<FormMain> action)
    {
        var form = Form.ActiveForm as FormMain;
        object s = action.Clone();
        if (form != null)
        {
            form.PerformAction(action);
        }
    }

    public void PerformAction(Action<FormMain> action)
    {
        if (InvokeRequired)
            Invoke(action, this);
        else
            action(this);
    }

две проблемы в моем коде:

Требуется изменить свойство, которое я хочу изменить! = Private: (

Не работает, если форма не в фокусе.

Ответы [ 3 ]

2 голосов
/ 28 апреля 2009

Каким образом добавляются свойства для данных, к которым необходимо получить доступ или задать их вне области действия формы «не ориентированы на объект вообще?» Это действительно ваш единственный вариант. Код в анонимном делегате (или в любом случае в любом случае) выполняется в контексте, в котором он был объявлен. Единственный способ обойти проблемы видимости - это отражение, и это большой вонючий запах кода . Создайте свои свойства и используйте их соответствующим образом.

Что касается вашего второго варианта, я предполагаю, что вы хотите выполнить это в своей "основной форме". У вас есть два варианта: предположить, что существует только один экземпляр, и сохранить его как статическое свойство в классе, назначив его в конструкторе экземпляра.

public partial class MainForm : Form
{
    private static MainForm singletonInstance;

    public static MainForm SingletonInstance
    {
        get { return singletonInstance; }
    }

    public MainForm() : base()
    {
        InitializeComponent();

        singletonInstance = this;
    }
}

public void PerformActionOnForm(Action<FormMain> action)
{
    var form = MainForm.SingletonInstance;
    // object s = action.Clone(); What was this for?
    if (form != null)
    {
        form.PerformAction(action);
    }
}

Другая работает только в том случае, если все ваши формы должным образом "принадлежат", и единственная форма без владельца - это ваша основная форма. В этом случае вы можете сделать это:

public void PerformActionOnForm(Action<FormMain> action)
{
    var form = Form.ActiveForm.TopLevelControl as FormMain;
    // object s = action.Clone(); What was this for?
    if (form != null)
    {
        form.PerformAction(action);
    }
}
1 голос
/ 28 апреля 2009

Вызов компонента пользовательского интерфейса из потока, не являющегося пользовательским интерфейсом

Если предположить, что у вас есть только один цикл сообщений (99% в этом случае), тогда:

public static class SynchronizedInvoker
{
    public static void Invoke(Action action)
    {
        Form form = Application.OpenForms.Cast<Form>().FirstOrDefault();
        if (form != null && form.InvokeRequired)
            form.Invoke(action);
        else
            action();
    }
}

Позвонив по коду:

SynchronizedInvoker.Invoke(() => myForm.Text = myText);

Доступ к частным компонентам пользовательского интерфейса

Доступ к закрытым членам пользовательского интерфейса не отличается от доступа других закрытых членов к объектам .NET. Частный член не имеет доступа к другим объектам. Если вы все еще хотите получить доступ, вам в любом случае придется передать ссылку на компонент пользовательского интерфейса вызывающей стороне или использовать отражение, чтобы разрешить путь к закрытому объекту.

Пример передачи ссылки компонента UI вызывающей стороне:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ThreadPool.QueueUserWorkItem(delegate { MyWorker.Run(button1); }); 
    }
}

class MyWorker
{
    public static void Run(Button button)
    {
        SynchronizedInvoker.Invoke(() => button.Text = "running");
        Thread.Sleep(5000); // do some important work here
        SynchronizedInvoker.Invoke(() => button.Text = "finished");
    }
}

Использование отражения технически возможно, но не идеально. Вам необходимо знать путь к закрытому члену, а для этого требуется информация о внутренних объектах. Затем вы должны спросить себя, почему вы сделали его приватным.

0 голосов
/ 28 апреля 2009

Почему у вас так много возможных точек входа в форму, которые можно вызывать из других потоков? Выполните маршалинг потока вниз (контроллер вашей формы может помочь), и вам не придется беспокоиться о шаблонном коде, подобном этому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...