CSLA .NET

From Rockford Lhotka's Expert C# 2005 and VB 2005 Business Objects books

Welcome to CSLA .NET Sign in | Join | Help
in Search

binding to business object with property datatypes as enum

Last post 10-22-2008, 10:53 AM by Shazam. 28 replies.
Page 1 of 2 (29 items)   1 2 Next >
Sort Posts: Previous Next
  •  07-11-2007, 8:43 PM 15998

    binding to business object with property datatypes as enum


    I have a business object I want to use for binding. There are a series of combobox on the form that are populated via a bindingsource which sets the DataSource, DataMember, ValueMemeber. THis populates the combo with available values. Now, I bind all the controls on teh form to my business object. The BO has a property which I set to be bound to the SelectedValue of the combo. The property in question is defined as an enum. It seems like the binding mechanism cannot read/write from the property when defined as an enum. If I change it to Integer, it all works correctly.

    Does anyone know the cause of this issue? Is there a work around or something I need to do to make this work? If I has to use integers for my properites, it will not be pretty, I have dozens of enums and the code will get very ugly fast.

    Thanks in advance for any assistance you may provide.

  •  07-11-2007, 10:59 PM 16007 in reply to 15998

    Re: binding to business object with property datatypes as enum

    Enums *are* integers. The enum values are only around in your source code. When it is compiled, they all become integers. Suppose you have an enum with members Red, White, and Blue. Red = 0, White = 1, and Blue = 2.

    You probably want your enum options to display with a user-friendly value in the combo box (like Red, White, or Blue). I think you're going to need an additional object that represents the list of those values. I haven't tried this, but perhaps you could use reflection against the Enum to generate the list? I'm not sure if reflection will let you retrieve "Red" out of the enum type, but it could be worth exploring.
  •  07-12-2007, 8:11 AM 16017 in reply to 16007

    Re: binding to business object with property datatypes as enum

    Hi,

    Thanks for your reply.

    So, what is happening is that I am not binding the combobox to the enum values. I am binding the combo box to a List object that contains the values loaded from the database. However, to represent the values loaded in the database, I use enums in the application.

    So, for example I have,

    Public Enum MyEnum

    Red

    White

    Blue

    End Enum

     

    And in my business object, I have a property

    public property SomeColor as MyEnum

    Get...

    Set...

    End property.

     

    I have a binding source that is set to an Object of a ReadOnlyList  that is used to populate the combobox. Then, in my business object for the overall form, I have a property like above. I bind teh SelectedValue to the property in the Business Object so that when an object is being edited, the combobox shows the right value.

    I put a breakpoint on teh Get and Set routine in teh property. When I change the value in the combobox, the set never gets called, but the Get is getting called 2 or 3 times. Then the form goes into a state where I cannot even take teh focus of the combobox in question, can't even close the form with the controlbox.

    I am going to do some isolated testing today, but there seems to be a limitation here...hoping I am wrong though.

     

    Rick.

  •  07-12-2007, 10:47 AM 16027 in reply to 16017

    Re: binding to business object with property datatypes as enum

    I'm a bit confused.

    Enums are a static construct, and building a list of values from the database is, by definition, a dynamic thing to do.  So I'm concerned about keeping the list of values in the enum the same as the list of items in the database.  It just feels like a design mismatch to me.

    Why not load an NVList (from NameValueListBase) from the database and bind it to the combobox?  That's what it's for! :)

  •  07-12-2007, 11:03 AM 16029 in reply to 16027

    Re: binding to business object with property datatypes as enum

    Hello,

    Ok, so binding a list of items to the combobox is not the issue.

    Yes, we have enums that are kept in sync with values from the database, good or bad, that is how it was done.

    I bind the combobox based on an id that will give me a group of related possible values for a particular domain from the database (also b/c we are supporting multiple languages, this is in teh database). This is fine.

    My issue is with the business object that has attributes of those enum types.

    The business object has a property, for example, a car object, with a color property, wher the only options are red,white,blue as the enum above. So, when declaring the property on the Car object, it is delcared as the enum type. Why? So that when developers are coding against the property, they immediatly see the options for the enum...this is very common practice throughout the entire .Net framework.

    So, I have a winform to manage my 'car' object. I use a combobox to give the user the limited choices they have on colors. I load the available values from the database in teh appropriate language for the user. I bind all the controls on my winform to by Car object. The combobox selected value is bound to the color property whose datatype is defined as the colors enum above.

    The winform is not behaving nicely in this situation. It is not calling the Set on teh property when the value is changed. It is calling the get,but not changing the value in the combobox based on teh value of the property when the property datatype is the enum.

    Please note that my issue has nothing to do with loading the combobox, it has to do with binding the comboboxes on the form to properties of my business object.

  •  07-12-2007, 11:35 AM 16030 in reply to 16029

    Re: binding to business object with property datatypes as enum

    I know this is down the path of a general .Net thing now, but I am trying to do a proof of concept with the CSLA framework with our existing application. And this is how I came accross this. Here is a sample app I whipped up that will demonstrate the problem.

    Public Enum MyEnum

    One = 1

    Two

    Three

    Four

    End Enum

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim sortedList As Collections.ArrayList = New ArrayList

    sortedList.Add(New myItems(-1, ""))

    sortedList.Add(New myItems(1, "One"))

    sortedList.Add(New myItems(2, "Two"))

    sortedList.Add(New myItems(3, "Three"))

    sortedList.Add(New myItems(4, "Four"))

    ComboBox1.DataSource = sortedList

    ComboBox1.DisplayMember = "Value"

    ComboBox1.ValueMember = "Key"

    Dim _bo As MyBO = New MyBO()

    MyBOBindingSource.DataSource = _bo

    End Sub

    Public Class myItems

    Private Dim _key As Integer

    Private Dim _value As String

    Public Property Key() As Integer

    Get

    Return _key

    End Get

    Set(ByVal value As Integer)

    _key = value

    End Set

    End Property

    Public Property Value() As String

    Get

    Return _value

    End Get

    Set(ByVal value As String)

    _value = value

    End Set

    End Property

    Public Sub New(ByVal key As Integer, ByVal value As String)

    _key = key

    _value = value

    End Sub

    End Class

    End Class

     

    Public Class MyBO

    Public Property X() As EnumClassLibrary.MyEnum

    Get

    Return _x

    End Get

    Set(ByVal value As EnumClassLibrary.MyEnum)

    _x = value

    End Set

    End Property

    Private _x As EnumClassLibrary.MyEnum

    Public Sub New()

    X = EnumClassLibrary.MyEnum.Four

    End Sub

  •  07-12-2007, 12:15 PM 16032 in reply to 15998

    Re: binding to business object with property datatypes as enum

    How do you bounf to the selecedvalue of the combo?
  •  07-12-2007, 12:52 PM 16033 in reply to 16032

    Re: binding to business object with property datatypes as enum

    I am binding using the propeties window - Data - Data Bindings - SelectedValue and setting the SelectedValue to MyBOBindingSource.PropertyName.

    So, from the SelectedValue property under data bindings, a data source has been created bound to my business object. I then use this binding source to bind to all the controls.

  •  07-12-2007, 1:49 PM 16037 in reply to 16007

    Re: binding to business object with property datatypes as enum

    That's not quite true; enums are first class members.  by default, using an enum will have the actual enum name display in the combobox, if you were to databind them.  In other words, Red, White and Blue woudl be displayed, not 0, 1, or 2.

    Also, not all enums are ints; you CAN create enums which inherit from short or long, as you need, although I think that's discouraged.
  •  07-12-2007, 4:48 PM 16043 in reply to 16037

    Re: binding to business object with property datatypes as enum

    Rick,

    I have a similar setup to yours where I have a "lookup" table in the database with values to populate combo boxes.  I also have corresponding enums with these "lookup" values.  As far as I know, it is not possible to bind a combobox directly to an enum property.  I'm assuming that your business object also stores the database id of the lookup item that was selected so that it can be persisted back to the database.  What I do is bind the combobox to this lookup id property on the business object.  Then in the get accessor of the enum property I call a static/shared helper method that "maps" the database id of the lookup item to the correct value in the enum.  So your get accessor for the enum property on the business object would look something like this (c#):


    public MyEnum SomeColor

       get 
       { 
          return EnumHelper.GetMyEnumValue(m_colorId); 
       } 
    }

    The implementation is a little tedious, but it gets the job done.  It's also much better than looking at code like this:

    if (m_colorId == 1)   && 1 stands for Red

    If anybody knows a better way, please let us know.

    Dustin

  •  07-12-2007, 5:18 PM 16045 in reply to 16043

    Re: binding to business object with property datatypes as enum

    Why not wrap the enum in a NVL? In other words, create an object that inherits from NVLB, where the DataPortal_Fetch() method merely loads the list from the enum. You can enumerate the values in an enum (using reflection if nothing else).

    Given an enum like

      public enum MyEnum
      {
        Red,
        Blue,
        Green
      }

    You'd have a class like:

      [Serializable]
      public class MyEnumList : Csla.NameValueListBase<MyEnum,string>
      {
        public static MyEnumList GetList()
        {
          return Csla.DataPortal.Fetch<MyEnumList>(new Criteria(typeof(MyEnumList)));
        }

        private MyEnumList()
        { /* require use of factory method */ }

        [Csla.RunLocal]
        protected override void DataPortal_Fetch(object criteria)
        {
          this.IsReadOnly = false;
          foreach (MyEnum item in Enum.GetValues(typeof(MyEnum)))
            Add(new Csla.NameValueListBase<MyEnum, string>.NameValuePair(
              item, Enum.GetName(typeof(MyEnum), item)));
          this.IsReadOnly = true;
        }
      }

    Then you can bind it like you'd bind any other object/list to a combobox, as long as the object's property is of type MyEnum:

        MyEnum _color;
        public MyEnum Color
        {
          [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
          get
          {
            CanReadProperty(true);
            return _color;
          }
          [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
          set
          {
            CanWriteProperty(true);
            if (!_color.Equals(value))
            {
              _color = value;
              PropertyHasChanged();
            }
          }
        }

     


    Rocky
  •  07-12-2007, 8:50 PM 16051 in reply to 16045

    Re: binding to business object with property datatypes as enum

    Hey Rocky,

    In summary, that code worked perfectly. After analyzing my problem set more after I got a sample project working with it, I added a few requirements to my list. I follow the pattern you posted. But, in my case, I have a 'master' enum which is an enum of all the available enums that we have. When I say enums in this context I am referring to different domain of lookup values. So, I have an enum of all lookup value types, and enums of each individual lookup. In total, dozens upon dozens of enums -- lots of entities managed in this system.

    So, I wanted to make your code sample generic so that I only had one class to deliver my lookups to the UI, and not one class per lookup/enum. I managed to get this to work, it wasn't too tricky, I will post the code here as I think the pattern might help others.

    I have custom combobox that is dedicated to showing the lookup values based on the enums. I gave it a property with the type of the "master' enum so that a consumer can pick the lookup domain to popluate the box with:

    Protected Overrides Sub OnCreateControl()

    MyBase.OnCreateControl()

    For Each bindings As System.Windows.Forms.Binding In DataBindings

    bindings.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged

    Next

    If Not Me.DesignMode Then

     

    Me.DataSource = AMSCSLA.ValueList.GetValueList(AMSDomain)

    Me.DisplayMember = "Value"

    Me.ValueMember = "Key"

    End If

    End Sub

    Public Property AMSDomain() As AMS.Framework.AMSDomains

    Get

    Return _amsDomain

    End Get

    Set(ByVal value As AMS.Framework.AMSDomains)

    _amsDomain = value

    End Set

    End Property

     

    In here, pass the master domain type to my NVL. In my NL I do this:

     

    Public Shared Function GetValueList(ByVal domain As AMS.Framework.AMSDomains) As ValueList

    Return Csla.DataPortal.Fetch(Of ValueList)(New DomainCriteria(domain))

    End Function

    Protected Overloads Sub DataPortal_Fetch(ByVal thecriteria As DomainCriteria)

    Me.IsReadOnly = False

    Dim enumName As String = [Enum].GetName(GetType(AMSDomains), CType(thecriteria.Domain, Integer))

    Dim enumTypeHandle As System.Runtime.Remoting.ObjectHandle = System.Activator.CreateInstance("AMS.Framework", "AMS.Framework.AMSDomainValues." & enumName)

    Dim enumType As [Enum] = CType(enumTypeHandle.Unwrap(), [Enum])

    For Each item As Object In [Enum].GetValues(enumType.GetType)

    Add(New Csla.NameValueListBase(Of [Enum], String).NameValuePair( _

    item, [Enum].GetName(enumType.GetType, item)))

    Next

    Me.IsReadOnly = True

    End Sub

    Protected Class DomainCriteria

    Public Property Domain() As AMS.Framework.AMSDomains

    Get

    Return _domain

    End Get

    Set(ByVal value As AMS.Framework.AMSDomains)

    _domain = value

    End Set

    End Property

    Private _domain As AMS.Framework.AMSDomains

    Public Sub New(ByVal domain As AMS.Framework.AMSDomains)

    _domain = domain

    End Sub

    End Class

    End Class

     

    I use a little reflection to create an insance of the type of enum specified by the domain (this makes a requirment that the text of the master domain match the actual domain, but that will be managable). I will have left to do after this is add in a call to my lookup table to get the string text for the NVL in the users culture so the UI displays correctly and to sort the values by that text.

     

    Thanks very much for your post, you definitely got me down the right path.

     

    Regards,

     

    Rick.

  •  07-13-2007, 9:15 AM 16059 in reply to 16051

    Re: binding to business object with property datatypes as enum

    Wow.  That's a pretty good idea.  I'll have to try to modify my system to use something like this.  It's quite a bit less tedious than what I'm currently using.

    Dustin

  •  04-02-2008, 7:55 PM 22483 in reply to 16059

    Re: binding to business object with property datatypes as enum

    Here's another suggestion:

    I created a class called EnumNVL which creates a NameValueList from any Enum Type.

    Sample Usage in form:

    EnumNVL envlDateRangeTypes = EnumNVL.GetEnumNVL(typeof(DateRangeType));
    // The parameter for the GetEnumNVL() method is any valid Enum, ie., GetEnumNVL(typeof(AnyValidEnum)).
    // The substitutable parameter in this example uses the Enum type "DateRangeType".

    cbxDateRangeTypes.DataSource = envlDateRangeTypes
    cbxDateRangeTypes.DisplayMember = "Value";
    cbxDateRangeTypes.ValueMember = "Key";
    cbxDateRangeTypes.SelectedIndex = 0;

    Here's is the EnumNVL class:

    [Serializable]
    public class EnumNVL : Csla.NameValueListBase<Enum, string>
    {
       
    private static Type _Type = null;
       
    public static EnumNVL GetEnumNVL(Type type)
       
    {
          
    _Type = type;
          
    return Csla.DataPortal.Fetch<EnumNVL>(new Criteria(typeof(EnumNVL)));
       }

       private EnumNVL()
       
    { /* require use of factory method */ }

       [Csla.RunLocal]
       protected override void DataPortal_Fetch(object criteria)
       {
          
    this.IsReadOnly = false;
          
    foreach (Enum item in Enum.GetValues(_Type))
             Add(new Csla.NameValueListBase<Enum, string>.NameValuePair(
                
    item, Enum.GetName(_Type, item)));
          
    this.IsReadOnly = true;
       }
    }

    -- Update:

    Cine's brilliant generic version below is a great modification. Here is an example of how I use his code:

    EnumNVL<DateRangeType> enumNVL = EnumNVL<DateRangeType>.GetEnumNVL();

    // The KEY POINT is that with your more general code, I can cast the type to int as follows:
    int dbColumnValue = (int)enumNVL[0].Key;

    // I could not do that cast with my code!

  •  04-02-2008, 11:12 PM 22488 in reply to 22483

    • Cine is not online. Last active: 09-07-2008, 9:41 PM Cine
    • Top 500 Contributor
    • Joined on 03-26-2008
    • HCMC, Vietnam
    • Posts 17
    • Points 250

    Re: binding to business object with property datatypes as enum

    Even more general:

       class Program
       {
          static void Main(string[] args)
          {
             foreach (NameValueListBase<hest, string>.NameValuePair s in HestNVL.GetEnumNVL())
                Console.WriteLine(string.Format("{0} {1}", (int)s.Key, s.Value));
          }
       }
       [Serializable]
       public class EnumNVL<T> : NameValueListBase<T, string>
       {
          public static EnumNVL<T> GetEnumNVL()
          {
             return DataPortal.Fetch<EnumNVL<T>>(new Criteria(typeof(T)));
          }

          protected EnumNVL()
          { /* require use of factory method */ }

          [RunLocal]
          protected override void DataPortal_Fetch(object criteria)
          {
             Criteria c = (Criteria)criteria;
             IsReadOnly = false;
             foreach (T item in Enum.GetValues(c.ObjectType))
                Add(new NameValuePair(item, Enum.GetName(c.ObjectType, item)));
             IsReadOnly = true;
          }
       }
       [Serializable]
       public enum hest
       {
          red,
          green
       }
       [Serializable]
       public class HestNVL : EnumNVL<hest> { }

Page 1 of 2 (29 items)   1 2 Next >
View as RSS news feed in XML

Please contact Magenic for your .NET consulting and CSLA .NET mentoring needs.
Please consider making a donation to help support the ongoing development of CSLA .NET.

Make donation through PayPal - it's fast, free and secure!
Why donate?
Powered by Community Server, by Telligent Systems