StrataFrame Forum

Custom Fields

http://forum.strataframe.net/Topic28918.aspx

By Ian Hammond - 11/9/2010

Hi,

I am trying to populate a grid from 2 BO's by creating custom fields in the 'master' BO. My code for the custom field properties is :



#region " Custom Field Properties"

private const String constComputerName = "computerName";

private const String constLoggedIn = "loggedIn";

[
Browsable(false)]

[
BusinessFieldDisplayInEditor()]

[
Description("computerName")]

[
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

public String computerName

{

get { return this.CurrentRow[constComputerName].ToString(); }

set { this.CurrentRow[constComputerName]= value; }

}

[
Browsable(false)]

[
BusinessFieldDisplayInEditor()]

[
Description("loggedIn")]

[
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

public Boolean loggedIn

{

get { return (Boolean)this.CurrentRow[constLoggedIn]; }

set { this.CurrentRow[constLoggedIn] = value; }

}

#endregion



My form has the following event enabled:



private void hlsUserNamesBO1_ParentFormLoading()

{

this.hlsUserNamesBO1.FillUserNames();

this.hlsUserProfilesBO1.FillAllProfiles();

foreach (HLSUserNamesBO row in this.hlsUserNamesBO1.GetEnumerable())

{

this.hlsUserProfilesBO1.Filter= "userId = " + row.userId;

this.hlsUserNamesBO1.computerName = this.hlsUserProfilesBO1.computerName;

this.hlsUserNamesBO1.loggedIn = this.hlsUserProfilesBO1.loggedIn;

}

}



When I hit the assignment to computerName I get the exception

"Column 'computerName' does not belong to table HLSUserNames."

Can anyone please advise, many thanks
By Greg McGuffey - 11/9/2010

The problem is that the user BO doesn't have the columns defined. You have two options here. Either create them via code or add them to your query to fill the user BO. The second is easier, the first is more bullet proof.

Using SQL
Just add two columns to your FillUserNames() method:

, '' As computerName
, 0 As loggedIn

This will ensure that the columns are in the data table and can be set.

Using Code
This is handled within the properties them selves. Below shows the basics (just typed in, so no promises there aren't typos/syntax errors!)
 

#region " Custom Field Properties"

private const String constComputerName = "computerName";

private const String constLoggedIn = "loggedIn";

[
Browsable(false)]

[
BusinessFieldDisplayInEditor()]

[
Description("computerName")]

[
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

public String computerName

{
get
{

  //-- Establish return var with default value set.
  string name = String.Empty;

  //-- If the column exists, get value.
  if(this.CurrentDataTable.Columns.Contains(
constComputerName))
  {
    name =
this.CurrentRow[constComputerName].ToString();
  }
  return name;
}
set
{
  //-- If the column doesn't exists, create it, using default value of type.
  if(!this.CurrentDataTable.Columns.Contains(
constComputerName))
  {
   
this.CurrentDataTable.Columns.Add(
constComputerName, typeof(string));
  }

  //-- Column is now ensured to be created and we can set value.
 
this.CurrentRow[constComputerName]= value;
}
}
By Ian Hammond - 11/9/2010

Many thanks for that snippet, problem solved.
By Greg McGuffey - 11/10/2010

Excellent! Glad that helped.
By Ian Hammond - 11/11/2010

Having sorted the problem with the data binding to custom fields I have come across the following issue:

On my dataview grid I have 4 columns, user name, description, computer name(custom) and logged in flag(custom)

The username,description are loaded from UserNameBO and computer name and logged in are loaded from UserProfilesBO.

I have 3 buttons Add User, Edit User, Delete User.

Edit User: This transfers control to another form that allows me to change parameters associated with the user. When I return to the calling form I reload the UserameBO to refresh the data view grid. I then get the error:

Thd following exception occurred in the DataGridView:

System.Reflection.TargetInvocationExceptions: Exception has bee thrown by the target of an invocation,-->

System.InvalidCastException: Specified cats is not valid.

at ........HLSUserNamesBO.get_loggedIn() followed by line no.

I presume this error is due the fact that the computerName and loggedIn are not being refreshed when I refresh the usernames. Could anyone throw some light on this issue, or is there some event I should be setting similar to the parentLoading.

Many thanks
By Edhy Rijo - 11/11/2010

Hi Ian,

Not that my suggestion  will resolve the problem with the DataGrid, but unless you need to modify data in the grid itself, I would use a ListView.

StrataFrame ListView is greatly automated to handle the BO, a childForm dialog and it is very easy to setup.  The ListView can even move the record pointer in the BO if you want it to.

There are plenty of samples on how to use the ListView and also the StrataFlix sample application uses a listview and childform dialogs the way I believe you want it to.

If you want to go with the ListView and need some help, just let us know.Smile
By Greg McGuffey - 11/11/2010

Ian,

First I would reinforce Edhy's suggestion that unless you need in-place editing, a ListView is much easier to user, much lighter weight. The SF ListView also has all the goodness Edhy mentioned related to easily hooking the ListView up to ChildFormDialogs etc.

However, to address your problem, the most common cause for this is that the column doesn't have the correct value in it (i.e. it can't be cast to a boolean). I'd set a break on the line that loads the BO and then step through it, looking at the data table.  Since this works when you load it, you must be doing something a bit differently when you refresh grid.  You might also set a break in the get of the loggedIn property and see what the data table looks like (get_loggedIn is the method generated by the compiler for the get of a property).
By Ian Hammond - 11/12/2010

Thanks for the suggestion, I have decided to try the ListView route. I have used the ChildDialogFormSample as a guide. I have it partially functioning. The issues I have at the moment are:

1) My computer name and logged in values are not displayed.

2) My call to SeekToPrimaryKey(list.SelectedItems[0].Tag) seems to generate an exception, it seems that it can't find the record with the index value, which I have confirmed is in the table.

I would appreciate a shove in the right direction on this, many thanks.
By Edhy Rijo - 11/12/2010

Hi Iam,

The listview has a property named AutoNavigateToSelectedRecord, if you set this to True, you can then just reference the BO and no need to seek the record.

Here are the settings I use for the ListView:

  1. I drop an instance of the BO I will use in the ListView in the fom.  I do this so I can manipulate the data in the BO instead of the ListView where I may not have all the fields I need to work with.
  2. PopulationDataSourceSettings (Method to Execute) CopyDataFrom(BusinessLayerBase,BusinessCloneDataType).  Make sure the "Tag Field" is the PK of your table.
  3. When using the population type in #2, you must tell the ListView to use the BO in step 1, so do this in the ListPopulating event using code like this (sorry VB)

e.Parameters(0).Value = Me.BizTransactionItems1
e.Parameters(1).Value = MicroFour.StrataFrame.Business.BusinessCloneDataType.ClearAndFillFromDefaultView
  • AutoNavigateToSelectedRecord = True
  • BusinesObject = the one dropped in step 1.
  • ChildForm =  whatever childformdialog you will be using.
Make sure you populate your BO either manually or at the form load.
By Ian Hammond - 11/12/2010

Hi,

That info made quite a difference, thanks. I am still having problems populating the computerName and Logged in columns. I have used the listView row populating event as shown below:

private void listViewUserNames_RowPopulating(MicroFour.StrataFrame.UI.Windows.Forms.RowPopulatingEventArgs e)

{

HLSUserNamesBO loBO= (HLSUserNamesBO)e.BusinessObject;

this.hlsUserProfilesBO1.FillProfileByUser(loBO.userId);

// e.Values[2].DisplayValue= this.hlsUserProfilesBO1.computerName;

// e.Values[3].DisplayValue= this.hlsUserProfilesBO1.loggedIn.ToString();

}

I have commented out the DisplayValue because they cause the exception:

Object reference not set to an instance of an object.

The e.Values has a count of zero.

I can't see what the demo does that I'm not can you please advise.

By Edhy Rijo - 11/12/2010

Very good Ian.

You don't need to do anything in the RowPopulating event.  I understand you want to display the ComputerName and LoggeIn values which are not part of the hlsUserProfilesBO1  BO, if so, you need to create those Custom Field Properties and suggested by Greg in the hlsUserProfilesBO1 BO, then in the ListView Populating Settings, you need to add those fields to the "Display Fields" listbox and then reference them in the "Columns" listbox with their index values (take a look at the image below).


http://forum.strataframe.net/Uploads/Images/4203e507-acd3-4782-bf1d-ffe5.png

P.S.
There are many ways to do this.  Look in the forums for Custom Field Properties, also in the help file.
By Ian Hammond - 11/15/2010

This issue is now resolved, I have since discovered the PopulateThroughEvent setting.
By Edhy Rijo - 11/15/2010

Congratulations!
By Greg McGuffey - 11/15/2010

I'm glad you got it working Ian and thanks for all the help Edhy (the ListView guru)!