Windowsform和uercontrol,实现对它们的更改。 [英] Windowsform and uercontrol, implementing changes to them.

查看:103
本文介绍了Windowsform和uercontrol,实现对它们的更改。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





我正在编写一个Windows窗体应用程序,我在向用户控件实现代码时遇到问题,



让我们说,我的所有表单都从我的基类继承,在我的基类中我有下面的代码,



< pre lang =vb> 公共 BaseForm
继承 System.Windows.Forms.Form

受保护的 覆盖 Sub OnVisibleChanged(e As System.EventArgs)
MyBase .OnVisibleChanged(e)

如果 .Visible 然后 ' 在表单时为每个按钮创建处理程序显示(变为可见)
对于 每个 myControl As Control Me .Controls
如果 myControl。 GetType GetType (按钮)然后
AddHandler myControl.Click, AddressOf TestModul.ClickHandler
结束 如果
下一步
其他 ' 当表单离开时,从每个按钮中删除处理程序(变得不可见)
对于 每个 myControl 作为控制 .Controls
如果 myControl。 GetType GetType (按钮)然后
RemoveHandler myControl.Click, AddressOf TestModul.ClickHandler
结束 如果
下一步
结束 如果

结束 Sub
结束 Class





测试模块如下:



 模块 TestModul 
公开 Sub ClickHandler(发件人作为 对象,e As System.EventArgs)

Dim mySender As Control = sender
MessageBox.Show(mySender.Name + vbCrLf + mySender.Parent.Name)
If (mySender.Parent。 GetType ()。ToString()。包含( UserControl))然后
MessageBox.Show( 它是一个用户控件
结束 如果

结束 Sub
结束 模块



到目前为止一切正常,但问题是将代码实现到我的usercontrols,这些代码都是从我写的baseusercontrol继承而来的下面:



 公共  BaseUserControl 
继承 System.Windows.Forms.UserControl

受保护的 覆盖 Sub OnVisibleChanged(e As System.EventArgs)
MyBase .OnVisibleChanged(e)

如果 .Visible 然后 ' 在显示表单时显示每个按钮的处理程序(变为可见)
对于 每个 myControl 作为控制 Me .Controls
If myControl。 GetType GetType (按钮)然后
AddHandler myControl.Click, AddressOf TestModul.ClickHandler
结束 如果
下一步
其他 ' 当表格离开时,从每个按钮中删除处理程序(变得不可见)
对于 每个 myControl 作为控制 .Controls
如果 myControl。 GetType GetType (按钮)然后
RemoveHandler myControl.Click, AddressOf TestModul.ClickHandler
结束 如果
下一步
结束 如果

结束 Sub

结束





此程序必须执行以下操作,只要按下按钮,它必须显示一个消息框并显示名称那个按钮和包含按钮的表格。



我尝试了什么:



跟踪它没有进入这个条件,



 如果 myControl。 GetType     GetType (按钮)然后 





并将其视为错误条件。我删除了If语句并再次看到它没有读取代码行

  AddHandler  myControl .Click, AddressOf  TestModul.ClickHandler 



所以再次不会对按钮进行更改。 />


在我的表单上工作正常,因为我打开它并在这些类的名称之后手动删除了继承行,I刚刚删除了行' Inherits baseusercontrol '并重写了它。然后它奏效了。 





但我不应该为所有其他课程这样做。什么是自动化的方式?





提前感谢您的帮助。

解决方案

要让您的控件作为容器,您需要从 ContainerControl 派生。在您的情况下,表单是您放在控件上的按钮的容器。



对于测试,从Panel派生非常方便。这是因为您可以显示例如一个边界。





最后:CP 设计嵌套控件 [ ^ ]



希望它有所帮助。



[Edit1] OnVisible故事

注意:我建议您不要像在代码中那样频繁地添加和删除事件处理程序。相反,你应该尝试在事件处理程序中检查parent.Visible。



这里有一个想法如何解决OnVisible请求作为控件的默认行为。我在c#中做过(我不知道VB),但我确定将它转换为VB是没有问题的。

  public   partial   class  MyPanel:Panel  //   ContainerControl // UserControl  
{
Form lastParent = ;

// 安装事件处理程序到控件
protected 覆盖 void OnParentChanged(EventArgs e)
{
// 调用基类
.OnParentChanged(E);

// 从以前的托管表单中删除处理程序
if (lastParent!= null
{
lastParent.VisibleChanged - = ParentVisibleChanged;
lastParent = null ;
}

// 找到新的托管表单。最有可能相同,但谁知道
控制父= .Parent;
while (parent!= null
{
if (parent Form)
{
lastParent =(Form)parent;
lastParent.VisibleChanged + = ParentVisibleChanged;
break ;
}
parent = parent.Parent;
}
}

受保护 void ParentVisibleChanged( object sender,EventArgs e)
{
// 仅调试
MessageBox.Show( ParentVisibleChanged );

// 执行表单可见更改所需的操作
// 应始终为真。
if (lastParent!= null
{
if (lastParent.Visible)
{
}
else
{
}
}
}
...
.....
}


我会改变发布的方法如下:



 受保护的 覆盖  Sub  OnVisibleChanged(e  As  System.EventArgs)
MyBase .OnVisibleChanged(e)

CheckControlCollection( Me .Visible)

结束 Sub





 私人  Sub  CheckControlCollection(myHost 作为控制,将声明为  boolean 
对于 每个 myControl 作为控制 myHost.Controls
如果 myControl。 GetType GetType (按钮)然后
如果状态 AddHandler myControl.Click, AddressOf TestModul.ClickHandler
如果 state 然后 RemoveHandler myControl.Click, AddressOf TestModul.ClickHandler
结束 如果

如果 myControl.Controls.Count> 0 然后
CheckControlCollection(myControl,state) ' < - 由于其中的错误,我修改了此行...
结束 如果
下一步
结束 Sub





但请注意 - 此代码未经过测试...

这两种方法仍然属于您的基础形式。您不需要将它集成到usercontrol或任何其他容器控件。

您的usercontrol中的代码不起作用,因为usercontrol不会更改它的Visible-State。如果你想以相同的方式在usercontrol中执行它,你应该覆盖另一种方法 - 但我更喜欢这种方式...



附加:

如果您有其他问题(对于此代码或其他内容),您只需要对此答案/解决方案发表评论,或者您应该评论我的一条评论。在这两种情况下,我收到一条消息,如果我再次在线,我会回答 - 如果可能的话...... ;-)



附加(2):

>>我修改了代码,因为它有错...





附加(3) - 修改后的ClickHandler:

 公共  Sub  ClickHandler(sender 作为 对象,e 作为 System.EventArgs)

Dim mySender As Control = sender
Dim myChildPath As String = mySender.Name

< span class =code-keyword>执行
如果 mySender.Parent Nothing 然后 退出
mySender = mySen der.Parent
myChildPath + = vbCrLf + mySender.Name
Loop

MessageBox.Show(myChildPath)

结束 Sub


Hi,

I'm programming a windows form application, I'm having a problem in implementing a code to my user controls,

let's say, all my forms inherit from my base class and in my base class I have the code below,

Public Class BaseForm
    Inherits System.Windows.Forms.Form

    Protected Overrides Sub OnVisibleChanged(e As System.EventArgs)
        MyBase.OnVisibleChanged(e)

        If Me.Visible Then ' create Handler to each Button when Form is shown (becomes visible)
            For Each myControl As Control In Me.Controls
                If myControl.GetType Is GetType(Button) Then
                    AddHandler myControl.Click, AddressOf TestModul.ClickHandler
                End If
            Next
        Else ' remove Handler from each Button when Form is left (becomes unvisible)
            For Each myControl As Control In Me.Controls
                If myControl.GetType Is GetType(Button) Then
                    RemoveHandler myControl.Click, AddressOf TestModul.ClickHandler
                End If
            Next
        End If

    End Sub
End Class



The test module is as follows:

Module TestModul
    Public Sub ClickHandler(sender As Object, e As System.EventArgs)

        Dim mySender As Control = sender
        MessageBox.Show(mySender.Name + vbCrLf + mySender.Parent.Name)
        If (mySender.Parent.GetType().ToString().Contains("UserControl")) Then
            MessageBox.Show("Its a user control")
        End If

    End Sub
End Module


So far everything is working properly, but the problem is with implementing the code to my usercontrols which all inherit from my baseusercontrol which is written below:

Public Class BaseUserControl
    Inherits System.Windows.Forms.UserControl

   Protected Overrides Sub OnVisibleChanged(e As System.EventArgs)
        MyBase.OnVisibleChanged(e)

        If Me.Visible Then ' create Handler to each Button when Form is shown (becomes visible)
            For Each myControl As Control In Me.Controls
                If myControl.GetType Is GetType(Button) Then
                    AddHandler myControl.Click, AddressOf TestModul.ClickHandler
                End If
            Next
        Else ' remove Handler from each Button when Form is left (becomes unvisible)
            For Each myControl As Control In Me.Controls
                If myControl.GetType Is GetType(Button) Then
                    RemoveHandler myControl.Click, AddressOf TestModul.ClickHandler
                End If
            Next
        End If

    End Sub

End Class



this procedure must do as follows, anytime a button is pressed it must show me a messagebox and display the name of that button and the form which contains the button.

What I have tried:

as is traced it it does not enter this condition,

If myControl.GetType Is GetType(Button) Then



and see's it as a false condition. I removed the If statement and saw that again it doesn't read the line of code

AddHandler myControl.Click, AddressOf TestModul.ClickHandler


so again the change will not be done on the buttons.

Well in on of my forms it's working, because I opened it and manually removed the line of inheritence after the name of those classes, I just removed the line ' Inherits baseusercontrol' and rewrote it. then it worked.



But I shouldn't do this for all other classes. What would be the automated way to that?


In advance thank you for your help.

解决方案

To let act your Control as a Container you Need to derive from ContainerControl. In your case the form is the Container for the button you placed on your control.

For tests it is very convinient to derive from Panel. This because you can show e.g. a border.

[Edit]
Finally: The harder (but probably correct) way is described here on CP Designing Nested Controls[^]

Hope it helps.

[Edit1] The OnVisible Story
Note: I would suggest to avoid adding and removing event handlers frequently like you do it in your code. Instead you should try with checking parent.Visible in your event handler.

Here an idea how you can solve the "OnVisible" request as a Default behaviour of your control. I did it in c# (I don't know VB) but I'm sure it is no Problem for you to convert it to VB.

 public partial class MyPanel : Panel // ContainerControl //UserControl
 {
     Form lastParent= null;

     // Install Event handler to the control
     protected override void OnParentChanged(EventArgs e)
     {
         // Call base class
         base.OnParentChanged(e);

         // Remove handler from previous hosting form
         if (lastParent != null)
         {
             lastParent.VisibleChanged -= ParentVisibleChanged;
             lastParent = null;
         }

         // Find the new hosting form. Most probably the same, but who knows
         Control parent = this.Parent;
         while (parent != null)
         {
             if (parent is Form)
             {
                 lastParent = (Form)parent;
                 lastParent.VisibleChanged += ParentVisibleChanged;
                 break;
             }
             parent = parent.Parent;
         }
     }

     protected void ParentVisibleChanged(object sender, EventArgs e)
     {
         // Debug only
         MessageBox.Show("ParentVisibleChanged");

         // Do what you need to do for form visible change
         // Should always be true.
         if (lastParent != null)
         {
             if (lastParent.Visible)
             {
             }
             else
             {
             }
         }
     }
  ...
  .....
}


I would change the posted methods like this :

Protected Overrides Sub OnVisibleChanged(e As System.EventArgs)
        MyBase.OnVisibleChanged(e)

        CheckControlCollection(Me , Me.Visible)

End Sub



Private Sub CheckControlCollection(myHost As Control , state as boolean)
        For Each myControl As Control In myHost.Controls
            If myControl.GetType Is GetType(Button) Then
                if state then AddHandler myControl.Click, AddressOf TestModul.ClickHandler
                if not state then RemoveHandler myControl.Click, AddressOf TestModul.ClickHandler
            End If

            If myControl.Controls.Count > 0 Then
                CheckControlCollection(myControl , state) ' <- I have modified this line because of a mistake in it ...
            End If
        Next
End Sub



But please note - this code is not tested ...
Both methods still belong to your baseform. You don't need to integrate it to the usercontrol or any other containercontrol.
Your code in your usercontrol doesn't work because the usercontrol doesn't change it's Visible-State. If you want to do it in the usercontrol in the same way you should override annother method - but I prefer THIS way ...

Additional :
If you have further question (to this code or something else) you only need to comment this answer / solution or you should comment one of my comments. In both cases I get a message and if I'm online again I answer - if possible ... ;-)

Additional (2) :
>> I modified the code because of a mistake in it ...


Additional (3) - modified ClickHandler :

Public Sub ClickHandler(sender As Object, e As System.EventArgs)

    Dim mySender As Control = sender
    Dim myChildPath As String = mySender.Name

    Do
        If mySender.Parent Is Nothing Then Exit Do
          mySender = mySender.Parent
        myChildPath += vbCrLf + mySender.Name
    Loop

    MessageBox.Show(myChildPath)

End Sub


这篇关于Windowsform和uercontrol,实现对它们的更改。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆