2014-10-06 11 views
0

Я новичок в C# и как бы крыло его. с помощью Microsoft Visual C# 2010Невозможно получить доступ к размещенному объекту C# (showdialog dispose)

Я проверил множество подобных постов и ни одно из предложений не похоже, чтобы помочь

Я получаю следующее сообщение об ошибке: «Не удается получить доступ к расположенную объект» , который ссылается на главную форму здесь

private void btn_RunPkgs_Click(object sender, EventArgs e) 
     { 
      RunPackages rp = new RunPackages();  
      this.Hide(); 
      rp.ShowDialog();//The error points to this line 
      this.Show(); 
     } 

вот код, который взрывается, когда проверка безопасности не удалась.

private void securityCheck() 
     { 
      if (MyGlobals.FormCheck("RUN_JOBS") == 1) 
      { 
       InitializeComponent(); 
      } 
      else 
      { 
       //this.BeginInvoke(new MethodInvoker(this.Close)); 
       //this.DialogResult = System.Windows.Forms.DialogResult.Cancel; 
       MessageBox.Show("You do not have permission to access this form!"); 
       //this.Close(); 
       this.Dispose(); 
      }    
     } 

EDIT Похоже, я собираюсь пойти с идеей Адриано Репетти в проставления безопасности, где я называю эту страницу, но я немного нервничаю, имеющие какую-либо безопасность на этой странице.

private void btn_RunPkgs_Click(object sender, EventArgs e) 
     { 
      if (MyGlobals.FormCheck("RUN_JOBS") == 1) 
      { 
       RunPackages rp = new RunPackages(); 
       this.Hide(); 
       rp.ShowDialog(); 
       this.Show();     
      } 
      else 
      { 
       MessageBox.Show("Not for You!");    
      } 
     } 

     private void btn_ListUpdater_Click(object sender, EventArgs e) 
     { 
      if (MyGlobals.FormCheck("MDM") == 1) 
      { 
       ListUpdater lu = new ListUpdater(); 

       this.Hide(); 
       lu.ShowDialog(); 
       this.Show(); 
      } 
      else 
      { 
       MessageBox.Show("Private!"); 
      }    
     } 

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

namespace RunPackages 
{ 
    public partial class ListUpdater : Form 
    { 
     public ListUpdater() 
     {    
      InitializeComponent(); 
      this.Load += new EventHandler(securityCheck); 
     }  

     private void securityCheck(object sender, EventArgs e) 
     { 
      if (MyGlobals.FormCheck("MDM1") == 0) 
      { 
       MessageBox.Show("Not Allowed!"); 
       this.Close(); 
      }  
     } 
+0

'this.Dispose()', что вы пытаетесь Dispose? Почему ты это называешь? –

+0

Я написал проверку безопасности, если пользователь терпит неудачу для этой конкретной формы, я хочу, чтобы она отображала окно с сообщением об ошибке и закрывала эту форму, возвращаясь к основной форме. Я сначала попробовал это. Clos – Lazer

+2

Это потому, что вы 'Disposing' формы во время' ShowDialog' так взрываются, потому что он не может ссылаться на себя после этого момента, так что угадайте, есть ли еще код, который вы нам не показываете. – Belogix

ответ

2

После того, как форма была удалена почти все его методы не могут быть доступны (и большинство его свойств являются недопустимыми) ,

В вашей первой строке btn_RunPkgs_Click() вы создаете объект и располагаете его внутри своего конструктора. Per se, даже если довольно плохая привычка вам может даже позвонить Dispose() из конструктора, он может даже работать, но затем вы попытаетесь использовать такой объект ShowDialog() сгенерирует ObjectDisposedException. Обратите внимание, что этот код также приведет к тому же результату (исключение):

RunPackages rp = new RunPackages(); 
rp.Dispose(); 

Да вы может проверка IsDisposed но это не делает код читабельным и проблема (ИМО) является вы смешиваете вещи. Конструктор не должен содержать такую ​​логику.

Пункт не только , где вы располагаете своей формой.Что лучше это делать даже не создать такую ​​форму (позвольте мне предположить, потому что вы называете InitializeComponent(), что securityCheck() вызывается в виде конструктора), для этого вы можете использовать фабричный статический метод:

public static bool TryShowDialog(Form currentForm) 
{ 
    if (MyGlobals.FormCheck("RUN_JOBS") != 1) 
     return false; 

    if (currentForm != null) 
     currentForm.Hide(); 

    RunPackages dlg = new RunPackages(); 
    dlg.ShowDialog(); 

    if (currentForm != null) 
     currentForm.Show(); 

    return true; 
} 

Ваша функция вызова затем будет снижена до:

private void btn_RunPkgs_Click(object sender, EventArgs e) 
{ 
    RunPackages.TryShowDialog(this); 
} 

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

public static bool ShowDialog<T>(Form currentForm, string authorizationId) 
    where T : Form, new() 
{ 
    if (MyGlobals.FormCheck(authorizationId) != 1) 
     return false; 

    if (currentForm != null) 
     currentForm.Hide(); 

    T dlg = new T(); 
    T.ShowDialog(); 

    if (currentForm != null) 
     currentForm.Show(); 

    return true; 
} 

Используется как это (теперь код повторно используется везде):

SecurityHelpers.ShowDialog<RunPackages>(this, "RUN_JOBS"); 

Пожалуйста, обратите внимание, что вызывающий код может быть упрощен (authorizationId может быть атрибутом на RunPackages, например, и также currentForm можно вывести из текущей активной формы).

EDIT Вызов Close() не лучше, если оконная ручка не была создана (давайте упростить немного: она создается, когда отображается окно) внутренне он позвонит Dispose() (то выше относится).

+0

Я использую функцию безопасности на каждой странице, я превратил ее в глобальный метод/класс/thingie (я новичок и не знаю терминов) , Я могу переместить безопасность на вызывающую страницу. Я дам вам попытку и дам вам знать. Все еще не уверен, почему this.Close не работает. – Lazer

+0

@Lazer Закрыть() не работает, потому что ... окно еще не было видимым. Вы все еще в конструкторе (BTW он не должен содержать никакой логики, но что нужно для создания самого объекта) –

+0

Я немного нервничаю из-за отсутствия безопасности на целевой странице, но эта идея работает для меня. Закончилось, так как это было намного проще. Спасибо, что объяснили простым словам, почему функции Close() и Dispose() не работают. – Lazer

3

Вы не можете распоряжаться формой в самой форме. Метод ShowDialog() пытается получить доступ к форме при выходе для таких вещей, как DialogResult.

-1

Использовать флаг. Например изменить код, например:

public bool IsDisposed; 
    private void securityCheck() 
      { 
       if (MyGlobals.FormCheck("RUN_JOBS") == 1) 
       { 
        InitializeComponent(); 
       } 
       else 
       { 
        //this.BeginInvoke(new MethodInvoker(this.Close)); 
        //this.DialogResult = System.Windows.Forms.DialogResult.Cancel; 
        MessageBox.Show("You do not have permission to access this form!"); 
        //this.Close(); 
        this.Dispose(); 
        this.IsDisposed = true; 
       }  


     } 

Тогда:

private void btn_RunPkgs_Click(object sender, EventArgs e) 
     { 
      RunPackages rp = new RunPackages();  
      if(rp.IsDisposed) 
       return; 
      this.Hide(); 
      rp.ShowDialog();//The error points to this line 
      this.Show(); 
     } 
+0

Это не сработало – Lazer

1

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

Вместо этого я хотел бы попробовать другой подход

private void securityCheck() 
    { 
     if (MyGlobals.FormCheck("RUN_JOBS") == 1) 
     { 
      InitializeComponent(); 
     } 
     else 
     { 
      Label message = new Label(); 
      message.Dock = DockStile.Fill; 
      message.Text("You do not have permission to access this form!."); 
      message.TextAlign = ContentAlignment.MiddleCenter; 
      this.Controls.Add(message); 
     }  
    } 

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

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

Если вы настаиваете на закрытии формы во время ее фаз конструктора, то вы могли бы получить некоторые советы от this question

+0

+1 Cool, но у меня были некоторые проблемы, не включая InitializeComponent() в другом. Ссылка тоже была полезной, но в итоге я столкнулся с ответом Адриано Репетти – Lazer

0

я придумал следующее, может кто-нибудь сказать мне, если есть какая-либо проблемы с этим?

namespace RunPackages 
{ 
    public partial class ListUpdater : Form 
    { 

     public ListUpdater() 
     {    
      InitializeComponent(); 
      this.Load += new EventHandler(securityCheck); 
     }  

     private void securityCheck(object sender, EventArgs e) 
     { 
      if (MyGlobals.FormCheck("MDM1") == 0) 
      { 
       MessageBox.Show("Not allowed!"); 
       this.Close(); 
      }  
     } 

и т.д ...

+1

Я бы поставил под вопрос (или - лучше - опубликуйте его на CodeReview как новый вопрос) в любом случае ... вам не нужно присоединять обработчик событий, yo can просто переопределите метод OnLoad. Более того, если это что-то широко используемое, вы можете переместить его в базовый класс (и, на самом деле, вы знаете, я бы полностью переместил его вне вашей формы, но это еще одна история ...) –

Смежные вопросы