Author Topic: User control help  (Read 545 times)

Phrog30

  • Full Member
  • ***
  • Posts: 225
    • View Profile
User control help
« on: April 10, 2017, 09:12:30 AM »
I have a user control which is just a button that I reuse several times throughout the program.  The image changes depending on if there are active alarms and I show how many alarms are present (btn.Text).  The only way I can get this to work is by a timer.  While this does work it's not very elegant and I would assume not best practice.  So, I tried to create an event based on alarm count.  When the value changes it raises the event.  This works, but it will not work on the button image or text.  Any ideas why?  When I'm using the event I use the same code, but instead on inside of timer tick I just create a sub and call it after the event.  The event works, but the image or text for the button doesn't.

Code: [Select]
Public Class Nav_Active_Alarm

    Dim picAnimate As Boolean = False

    Private mActive_Alarm_Count As Integer
    Public Event Active_Alarm_Count_Changed(ByVal mvalue As Integer)
    Public Property Count() As Integer
        Get
            Count = mActive_Alarm_Count
        End Get
        Set(ByVal value As Integer)
            mActive_Alarm_Count = value
            If Not Me.DesignMode Then
                'RaiseEvent Active_Alarm_Count_Changed(mActive_Alarm_Count)
            End If

        End Set
    End Property

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

        If Not Me.DesignMode Then
            If Main.dt_Active_Alarms IsNot Nothing Then
                If Main.dt_Active_Alarms.Rows.Count = 0 Then
                    btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Static
                    picAnimate = False
                Else
                    If Not picAnimate Then
                        btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Animation
                        picAnimate = True
                    End If
                End If

                If Main.dt_Active_Alarms.Rows.Count > 0 Then
                    btn_Goto_Active_Alarm.Text = Main.dt_Active_Alarms.Rows.Count
                Else
                    btn_Goto_Active_Alarm.Text = Nothing
                End If

            End If
        End If

    End Sub

End Class

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 3585
    • View Profile
    • AdvancedHMI
Re: User control help
« Reply #1 on: April 10, 2017, 10:25:53 AM »
Is this along the lines of what you want to do:
Code: [Select]
Public Class AlarmButton
    Inherits Button

    Public Event AlarmCountChanged As EventHandler(Of AlarmCountChangedEventArgs)

#Region "Properties"
    Private m_AlarmCount As Integer
    Public Property AlarmCount As Integer
        Get
            Return m_AlarmCount
        End Get
        Set(value As Integer)
            If m_AlarmCount <> value Then
                m_AlarmCount = value
                OnAlarmCountChanged(New AlarmCountChangedEventArgs(m_AlarmCount))

                If m_AlarmCount > 0 Then
                    BackgroundImage = m_AlarmImage
                Else
                    BackgroundImage = m_NoAlarmImage
                End If

                Text = m_AlarmCount
            End If
        End Set
    End Property

    Private m_NoAlarmImage As Image
    Public Property NoAlarmImage As Image
        Get
            Return m_NoAlarmImage
        End Get
        Set(value As Image)
            m_NoAlarmImage = value
        End Set
    End Property

    Private m_AlarmImage As Image
    Public Property AlarmImage As Image
        Get
            Return m_AlarmImage
        End Get
        Set(value As Image)
            m_AlarmImage = value
        End Set
    End Property
#End Region

#Region "Events"
    Protected Overridable Sub OnAlarmCountChanged(ByVal e As AlarmCountChangedEventArgs)
        RaiseEvent AlarmCountChanged(Me, e)
    End Sub
#End Region
End Class

'*************************************************************************************************
'* Event args class to pass arguments to event handler
'*************************************************************************************************
Public Class AlarmCountChangedEventArgs
    Inherits EventArgs

#Region "Constructor"
    Public Sub New()
        MyBase.New
    End Sub

    Public Sub New(ByVal AlarmCount As Integer)
        Me.New
        m_AlarmCount = AlarmCount
    End Sub
#End Region

    Private m_AlarmCount As Integer
    Public Property AlarmCount As Integer
        Get
            Return m_AlarmCount
        End Get
        Set(value As Integer)
            m_AlarmCount = value
        End Set
    End Property
End Class

- Add a new class to your project named AlarmButton and add the above code.
- Build the project
- From the Toolbox, add an AlarmButton
- Set AlarmImage and NoAlarmImage
- As you change the AlarmCount your image and text should changed

Phrog30

  • Full Member
  • ***
  • Posts: 225
    • View Profile
Re: User control help
« Reply #2 on: April 10, 2017, 01:16:11 PM »
That doesn't work either.  I can see the event.  But for whatever reason the images don't change.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 3585
    • View Profile
    • AdvancedHMI
Re: User control help
« Reply #3 on: April 10, 2017, 03:22:04 PM »
I posted a demo project (AlarmButtonDemo) showing the images change with the count:

https://sourceforge.net/projects/advancedhmi/files/advancedhmi/3.5/SampleProjects/

Phrog30

  • Full Member
  • ***
  • Posts: 225
    • View Profile
Re: User control help
« Reply #4 on: April 11, 2017, 09:01:05 AM »
Thanks Archie, however, that's not quite what I'm after.  Unless I'm missing something, I would still have to add code for each button.  If I'm correct on that, then what's the point?  What I'm after is a reusable object that you just drag and go.  What I want, I was able to get working but only using a timer, which I guess will be good enough.

James

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 3585
    • View Profile
    • AdvancedHMI
Re: User control help
« Reply #5 on: April 11, 2017, 09:03:11 AM »
What do you want to control the count? Is it linked to a value in the PLC?

Phrog30

  • Full Member
  • ***
  • Posts: 225
    • View Profile
Re: User control help
« Reply #6 on: April 11, 2017, 09:39:30 AM »
The PLC does know the count, but I'm using a variable in .NET code.  I was actually being lazy and just used the row count in a grid: Main.dt_Active_Alarms.Rows.Count

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 3585
    • View Profile
    • AdvancedHMI
Re: User control help
« Reply #7 on: April 11, 2017, 01:04:30 PM »
I updated the project with the button alarm count linked to a DataGridView row count

You can also control it through a PLC value by inheriting it into a control based off one of the existing control classes that will give it the ComComponent and the PLCAddress* properties.

Phrog30

  • Full Member
  • ***
  • Posts: 225
    • View Profile
Re: User control help
« Reply #8 on: April 11, 2017, 01:20:38 PM »
Thank you Archie, I will look at that when I get a chance later today or tomorrow.  Your support and help is stellar!!

James

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 3585
    • View Profile
    • AdvancedHMI
Re: User control help
« Reply #9 on: April 11, 2017, 01:30:07 PM »
I updated the project again to add an AlarmButtonToDGV that links to the DataGridView through a DatGridViewLink property, therefore encapsulating the code in the control.

Phrog30

  • Full Member
  • ***
  • Posts: 225
    • View Profile
Re: User control help
« Reply #10 on: April 20, 2017, 12:07:53 PM »
Archie, your code worked well.  Thank you.  However, can you explain to me why this code doesn't work?
Code: [Select]
Public Class Nav_Active_Alarm

Private mActive_Alarm_Count As Integer
Public Event Active_Alarm_Count_Changed(ByVal mvalue As Integer)
Public Property Count() As Integer
    Get
        Count = mActive_Alarm_Count
    End Get
    Set(ByVal value As Integer)
        mActive_Alarm_Count = value
        If Not Me.DesignMode Then
            RaiseEvent Active_Alarm_Count_Changed(mActive_Alarm_Count)
            test()
        End If

    End Set
End Property

Private Sub test()

    If Not Me.DesignMode Then

        If mActive_Alarm_Count = 0 Then
            Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Static
            'console or msgbox will work but updating the image will not
        Else
            Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Animation
                'console or msgbox will work but updating the image will not
            End If

    End If

End Sub

End Class

I can see the event working by either a console write or message box, but images, text, etc. will not update.  However, if I call this code from a timer, it will.  I'm at a loss for why this wouldn't work.  So, for future reference can you explain how I could make this work?  A colleague mentioned I needed to refresh or update for this to work, but I tried and it made no difference.

Thanks in advance...

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 3585
    • View Profile
    • AdvancedHMI
Re: User control help
« Reply #11 on: April 20, 2017, 02:26:07 PM »
However, can you explain to me why this code doesn't work?
Code: [Select]
Get
        Count = mActive_Alarm_Count
    End Get
This piece of code does not return any value, so when something tries to get the Count property, it will return nothing. I would have thought the compiler would have flagged it as an error.
   
Code: [Select]
Private Sub test()
    If Not Me.DesignMode Then
        If mActive_Alarm_Count = 0 Then
            Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Static
        Else
            Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Animation
         End If
    End If
In your test subroutine there is a reference to an undefined object. Based on the Me qualifier, that would tell me it is referring to an object within the class, but there is no btn-Goto_Active_Alarm object in the Nav_Active_Alarm class.

Phrog30

  • Full Member
  • ***
  • Posts: 225
    • View Profile
Re: User control help
« Reply #12 on: April 20, 2017, 03:58:20 PM »
Archie-
I actually am getting a valid value on "Count".  I can add this to the console and see it return the correct value.  Like I said, I can add a timer and on tick it will run the same identical code that you see and it works.  That's the part I'm having trouble to understand.  It's no big deal, just something that is bugging me why I can't figure it out.

I don't see any error or warnings.  By the way, this is a user control and there is a button named "btn_Goto_Active_Alarm".

James

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 3585
    • View Profile
    • AdvancedHMI
Re: User control help
« Reply #13 on: April 20, 2017, 04:48:11 PM »
By the way, this is a user control and there is a button named "btn_Goto_Active_Alarm".
After I posted that it occurred to me that you said it was a UserControl which means Visual Studio generated a partial class that has the definition of any items you add using the designer.

As for the Getter, try it like this:

Get
   Return mActive_Alarm_Count
End Get

Phrog30

  • Full Member
  • ***
  • Posts: 225
    • View Profile
Re: User control help
« Reply #14 on: April 21, 2017, 11:43:04 AM »
I tried but that didn't make any difference.  I'm still seeing the event, but I can't get text or images, etc, to change.  I added a text changed event:

Code: [Select]
Private Sub txtChanged(sender As Object, e As EventArgs) Handles MyBase.TextChanged

        Console.WriteLine("im changed")

       
End Sub

and I'm seeing this event, but the actual text isn't changing.