This is a Graphical Budget Calculator that allows you to view your household finances at different times during each year. You can view a (readonly) year summary, 4 quarters, the 3 months which make up 1 quarter, 12 monthly graphs, or the editable individual months.
Each of the different views uses the same properties, which are editable only in the editable individual months views. This readonly/writable effect is achieved by wrapping the properties classes in a readonly wrapper class, or for writable properties, simply using the unwrapped classes.
The values contained in the relevant properties are displayed as an interactive histogram, besides the propertygrid editor/viewer. Moving your mouse over the bars in the graph brings up values in the statusbar at the bottom of the form.
The eight main properties used in this application are expandable properties, opening up to reveal child properties or further expandable properties, which in some cases, depending on the current view, allow editing the values, in other cases the properties remain readonly.
The Total Income property and each of the Outgoing expandable properties has a coloured rectangle drawn in the propertygrid, which corresponds to the colours of the coloured bars in the histogram.
The expandable properties in the PropertyGrid are achieved through TypeConverter (ExpandableObjectConverter) attributes on the properties classes. The coloured rectangles in the PropertyGrid are achieved through UITypeEditor classes. This functionality isn't offered out of the box in the PropertyGrid. Using Class and Property level Attributes make this possible.
Imports System.Drawing.Design Public Class TypeEditor0 Inherits UITypeEditor Public Overrides Function GetPaintValueSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean Return True End Function Public Overrides Sub PaintValue(ByVal e As System.Drawing.Design.PaintValueEventArgs) Dim img As New Bitmap(19, 12) Dim gr As Graphics = Graphics.FromImage(img) gr.Clear(Color.FromArgb(215, 215, 195)) e.Graphics.DrawImage(img, New Point(2, 2)) MyBase.PaintValue(e) End Sub End Class
This class contains some regular, and some expanding properties
Imports System.ComponentModel Imports System.Globalization Imports System.Drawing.Design <System.Serializable()> Public Class properties Private _net As Decimal <CategoryAttribute("(Monthly Income)"), RefreshProperties(RefreshProperties.All), DisplayName("Net monthly pay")> Public Property net() As Decimal Get Return _net End Get Set(ByVal value As Decimal) _net = value totalIncome = (net + pension + otherIncome1 + otherIncome2).ToString("c2") End Set End Property Private _pension As Decimal <CategoryAttribute("(Monthly Income)"), RefreshProperties(RefreshProperties.All), DisplayName("Pension")> Public Property pension() As Decimal Get Return _pension End Get Set(ByVal value As Decimal) _pension = value totalIncome = (net + pension + otherIncome1 + otherIncome2).ToString("c2") End Set End Property Private _otherIncome1 As Decimal <CategoryAttribute("(Monthly Income)"), RefreshProperties(RefreshProperties.All), DisplayName("Income from Savings + Investments")> Public Property otherIncome1() As Decimal Get Return _otherIncome1 End Get Set(ByVal value As Decimal) _otherIncome1 = value totalIncome = (net + pension + otherIncome1 + otherIncome2).ToString("c2") End Set End Property Private _otherIncome2 As Decimal <CategoryAttribute("(Monthly Income)"), RefreshProperties(RefreshProperties.All), DisplayName("Other Income")> Public Property otherIncome2() As Decimal Get Return _otherIncome2 End Get Set(ByVal value As Decimal) _otherIncome2 = value totalIncome = (net + pension + otherIncome1 + otherIncome2).ToString("c2") End Set End Property Private _totalIncome As String <CategoryAttribute("(Monthly Income)"), RefreshProperties(RefreshProperties.All), ReadOnlyAttribute(True), DisplayName("Total Income"), Editor(GetType(TypeEditor0), GetType(UITypeEditor))> Public Property totalIncome() As String Get Return _totalIncome End Get Set(ByVal value As String) _totalIncome = value End Set End Property Private _houseHold As New Household <CategoryAttribute("(Monthly Outgoings)"), DisplayName("Household"), Editor(GetType(TypeEditor3), GetType(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> Public Property houseHold() As Household Get Return _houseHold End Get Set(ByVal value As Household) _houseHold = value End Set End Property Private _transport As New Transport <CategoryAttribute("(Monthly Outgoings)"), DisplayName("Transport"), Editor(GetType(TypeEditor8), GetType(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> Public Property transport() As Transport Get Return _transport End Get Set(ByVal value As Transport) _transport = value End Set End Property Private _finance As New Finance <CategoryAttribute("(Monthly Outgoings)"), DisplayName("Finance"), Editor(GetType(TypeEditor2), GetType(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> Public Property finance() As Finance Get Return _finance End Get Set(ByVal value As Finance) _finance = value End Set End Property Private _leisure As New Leisure <CategoryAttribute("(Monthly Outgoings)"), DisplayName("Leisure"), Editor(GetType(TypeEditor5), GetType(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> Public Property leisure() As Leisure Get Return _leisure End Get Set(ByVal value As Leisure) _leisure = value End Set End Property Private _regularBills As New RegularBills <CategoryAttribute("(Monthly Outgoings)"), DisplayName("Regular Bills"), Editor(GetType(TypeEditor7), GetType(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> Public Property regularBills() As RegularBills Get Return _regularBills End Get Set(ByVal value As RegularBills) _regularBills = value End Set End Property Private _insurance As New Insurance <CategoryAttribute("(Monthly Outgoings)"), DisplayName("Insurance"), Editor(GetType(TypeEditor4), GetType(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> Public Property insurance() As Insurance Get Return _insurance End Get Set(ByVal value As Insurance) _insurance = value End Set End Property Private _children As New Children <CategoryAttribute("(Monthly Outgoings)"), DisplayName("Children"), Editor(GetType(TypeEditor1), GetType(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> Public Property children() As Children Get Return _children End Get Set(ByVal value As Children) _children = value End Set End Property Private _otherBills As New OtherBills <CategoryAttribute("(Monthly Outgoings)"), DisplayName("Other Bills"), Editor(GetType(TypeEditor6), GetType(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> Public Property otherBills() As OtherBills Get Return _otherBills End Get Set(ByVal value As OtherBills) _otherBills = value End Set End Property Public Function getValues() As Decimal() Dim decValue As Decimal Decimal.TryParse(Me.totalIncome, NumberStyles.Currency, CultureInfo.CurrentCulture, decValue) Dim values() As Decimal = {decValue, Me.houseHold.totalHousehold, Me.transport.totalTransport, Me.finance.totalFinance, Me.leisure.totalLeisure, Me.regularBills.totalRegularBills, Me.insurance.totalInsurance, Me.children.totalChildren, Me.otherBills.totalOtherBills, 0} values(9) = values(0) - values.Skip(1).Take(8).Sum Return values End Function End Class
This is an example of the readonly wrapper classes used in this application.
Imports System.ComponentModel <TypeConverter(GetType(ExpandableObjectConverter))> <System.Serializable()> Public Class RegularBillsWrapper Private _instance As RegularBills Public Sub New(ByVal c As RegularBills) _instance = c End Sub <DisplayName("Council Tax"), RefreshProperties(RefreshProperties.All)> Public ReadOnly Property councilTax() As Decimal Get Return _instance.councilTax End Get End Property <DisplayName("Gas/Electricity/Water"), RefreshProperties(RefreshProperties.All)> Public ReadOnly Property amenities() As Decimal Get Return _instance.amenities End Get End Property <DisplayName("Phone/Television"), RefreshProperties(RefreshProperties.All)> Public ReadOnly Property communications() As Decimal Get Return _instance.communications End Get End Property <ReadOnlyAttribute(True), Browsable(False), DisplayName("Total Regular Bills Outgoings")> Public ReadOnly Property totalRegularBills() As Decimal Get Return councilTax + amenities + communications End Get End Property Public Overrides Function ToString() As String Return totalRegularBills.ToString("c2") End Function End Class