In a C# TBB: how to split a multi SingleLineTextField into seperate strings - tridion

I have a plain textfield in Tridion that can have multiple values. The itemtype is a SingleLineTextField.
In the TBB code I have the following (removed the non-essential parts):
ItemFields itemFields = new ItemFields(folder.Metadata, folder.MetadataSchema);
foreach (ItemField itemField in itemFields)
{
string itemFieldValue = string.Empty;
switch (Utilities.GetFieldType(itemField))
{
case FieldType.SingleLineTextField:
itemFieldValue = itemField.ToString();
break;
}
}
Now the result in case of two entries is just two strings with a character line break in it.
String A
String B
The method used is a generic one, which also works on other fields, so I was looking for some way to find out if a SingleLineTextField has more values in it.

You can cast the field to a SingleLineTextField type, then iterate through the Values collection, something along these lines:
SingleLineTextField field = (SingleLineTextField)itemField;
foreach(string value in field.Values)
{
// do something with value
}
// or if all you want is the count of values
int i = field.Values.Count;

Firstly, I would advise against relying on the ToString() method on objects unless it is specifically documented. In this case it works with the abstract class ItemField, but this may not always be the case.
The TOM.Net API only defines Definition and Name properties for ItemField, so you need to cast your ItemField object to something more specific.
the TextField abstract class, which SingleLineTextField inherits from, defines a ToString() method, but also Value and Values properties, which are much better suited to what you're trying to do. Looking at the documentation, we can see that Values will give us an IList<String> of the values, even if your field is not multi-valued. Perfect!
So, to answer your question, "I was looking for some way to find out if a SingleLineTextField has more values in it", you need to cast your ItemField as a TextField and check the number of Values it provides, thus:
TextField textField = (TextField)itemField;
// If you need to deal with multi-valued fields separately
if (textField.Values.Count > 1)
{
//Logic to deal with multiple values goes here
}
else
{
//Logic to deal with single valued goes here
}
// Much better... If you can deal with any number of values in a generic fashion
foreach (string value in textField.Values)
{
// Generic code goes here
}

Related

JavaFX TextField in Column with Typefilter

I have a simple JavaFX Table with a column like this:
#FXML
private TableColumn<PropertyModel, String> columnPropertyProdValue;
Within the initialize method I used this
columnPropertyProdValue.setCellFactory(TextFieldTableCell.forTableColumn());
in order to get an textarea at a double click event on this column. This is working fine.
The column should store different property values but the datatype depends on a different column in the table. The first column "datatype" defines the datatype like boolean, string or integer and the property column should store its value. But in the moment it is always a String.
Its fine for me if I store the property value as a String in the database but the application should check for correctness of the datatype at runtime.
Does anyone has a good idea how to realize that?
Thanks a lot
Hauke
For TextInputControl and subclasses you can apply TextFormatter. This class allows you to control input. For example (for float number):
setTextFormatter(new TextFormatter<String>(
s -> {
if (s.getControlNewText().isEmpty())
return s;
try{
Float.parseFloat(s.getControlNewText());
return s;
} catch (NumberFormatException e) {
return null;
}
}

How To Put String Value in String Array ?? Code Attached (Error: Object reference not set to an instance of an object.)

i am getting error "Object reference not set to an instance of an object." my is here,
public class UserProfession
{
public UserProfession()
{
}
public System.String[] Designation
{
get;
set;
}
}
then i am using it like,
UserProfession.Designation[0] =txt_Search.Text.ToString();
Error i mentioned you hopes for your suggestions .
-Thanks
When you make an assignment to an array property, like this:
UserProfession.Designation[0] =txt_Search.Text.ToString();
what you are actually doing is calling the get section for that property... not the set. This returns the object supported the property... the whole object, and not just the index. Index lookup does not happen until after the object is returned. Once you have that object, accessing an index works in the normal way.
You get this specific exception because you have the expression UserProfession.Designation that should return a reference to an array object, but because you never initialize the array there is nothing there when you then try to find reference the 0th element. At this point the framework discovers that the array (your "object reference") is "not set to an instance of an object"... which is just a fancy way of saying it's null.
In other words, you need to have an already existing array to hold the value you want to assign. That means doing something like this:
Designation = new String[10];
public String[] Designation
{
get;
set;
}
However, notice that we never used the set section? So you can simplify that further, like this:
Designation = new String[10];
public String[] Designation {get;private set;}
This will keep client code from completely swapping an entire array out from under your object, but otherwise will provide the full functionality of an array property. If you provide your own backing store for the array, you could even get rid of the setter entirely with no loss of functionality:
private string[] _designation = new string[10];
public string[] Designation {get {return _designation;} }
But let's add one more wrinkle: your desire to assign the to array before initializing it indicates to me that you likely don't really know how big it will be up front. If that's the case, you probably want a collection of some kind instead of an array. A generic List is a convenient and very compatible replacement for an array. That would look like this:
private List<string> _designation = new List<string>();
public List<string> Designation {get {return _designation;}}
You can still access items in that list by index, just like you would with an array. The only difference you need to worry about right now is how you add new items:
UserProfession.Designation.Add(txt_Search.Text);
Also notice that I removed the .ToString() call. Since your .Text property is almost certainly already a string, calling the .ToString() method is just silly.
You will have to initialize the object, before assigning the value. The initialization should be done just once. I have initialized the array size to ten. You can have your own values here. If you want to resize dynamically, you can use ArrayList
int length = 10;
UserProfession.Designation = new System.String[length];
UserProfession.Designation[0] =txt_Search.Text.ToString();
For more information: http://msdn.microsoft.com/en-us/library/aa287601(v=vs.71).aspx
it must initialize the value before we use because, currently, it is null.
you better add the initialization code in the constructor function.

Enumerations and String values in ASP.NET

I'm looking for some best practice advice on enumerations and retrieving an associated string value. Given this:
public enum Fruits {
Apple,
Orange,
Grapefruit,
Melon
}
What is the best way to get a related string value of the name? Eg. "Grapefruit", given that the string value may not match the representation in the enumeration. eg "Casaba Melon"
My current thinking is function accepting an enum and returning a string, but would that not mean hard coding the string values (which I prefer not to do)? Is using a resources file where the string can be retrieved via the enumeration too heavy handed?
To answer your question, you can decorate your enums with attributes to give them proper display string. Here are some examples
Using Attributes with Enums
Enum With String Values In C#
The main limitation of this approach is if you ever need to internationalize your application, I don't know of a way to make attribute strings change value based on thread locale (or whatever way you use to distinguish locales).
R0MANARMY has already given a very nice solution. I'll provide this alternative, less nice, one though still. You can probably make this culture sensitive easier.
Say you have the enum
public enum NicePeople
{
SomeGuy,
SomeOtherGuy
}
You can then make an extension method like this
public static class MyExtensions
{
public static string GetName(this NicePeople tst)
{
switch (tst)
{
case NicePeople.SomeGuy:
return "Some Nice guy";
case NicePeople.SomeOtherGuy:
return "Another Nice Guy";
default:
throw new Exception("Naw");
}
}
}
And get your serial killers name like this
NicePeople.SomeGuy.GetName()

Flex Dictionary Sorting

I have the following dictionary in flex, and i d like to sort it by value. Couldn't find any resource.
'1'=>2, '0' =>1, '3'=>4 ..
Any ideas ? How can i sort this by value ?
I searched around for a similar solution, except that I needed to sort the dictionary map and return a sorted collection relating key value pairs. After failing to find a published solution I put together the approach below. This method takes a dictionary as input, creates an array maintaining the association then sorts the resultant array using array.sortOn() and returns the sorted results back as an array. "key" and "value" fields in the array in the example below are used for clarity, but any field name could be used.
This example assumes a string object as a key and a numeric object as a value, though of course any object type could be used, and field parameters adjusted.
The approach below could also be used for sorting by key instead of value by using "key" as the sort field for the sortOn method, and you could use different sort options than the descending numeric sort I used here( AS3 SortOn() documentation) Code below is intentionally non-generic to simplify it for example purposes.
public static function sortDictionaryByValue(d:Dictionary):Array
{
var a:Array = new Array();
for (var dictionaryKey:Object in d)
{
a.push({key:dictionaryKey,value:d[dictionaryKey]});
}
a.sortOn("value",[Array.NUMERIC|Array.DESCENDING]);
return a;
}
Probably not the best way to do it but it works:
var a:Array = new Array();
for each (var v:Number in dict)
{
a.push(v);
}
a.sort();

GridView - Sorting Enum in Alphabetical Order

When sorting on a column in the GridView bound to an Enum, it sorts by the order of the Enum. I need it to sort by the string representation of the Enum. Here are the options I have seen, of which I like none of them.
Reorder the Enum in alphabetical order - Bad because now the presentation is relying on the Business and Data Access Layer to "pre-sort" the data.
Create a new object (datatable, new list, whatever) with myEnum.ToString() and bind this to the GridView - This one is not bad, but I would rather not.
In my search, check to see if the column sorted is an Enum, then sort by the string representation of the column - Do I have to say why this is bad?
Number 2 would be my favorite so far, but like I said, I don't like it.
More info just in case - I am binding a List of IWhatever to the grid, and 2 columns are enums that need to be sorted by strings. There are also guid-type, string, and decimal columns in the grid that need to be sorted.
Try to use ViewModels. Basically you create ViewModel Objects that contains your Model Object (your IWhatever). This ViewModel exposes then new Properties and Methods which are used in your View. In Your case you would expose a property with the string representation of your Enum. The advantage is, that you could do any transformation logic you want.
See MVVM Pattern. http://en.wikipedia.org/wiki/Model_View_ViewModel
EDIT: Little Example:
public class WhateverViewModel
{
public WhateverViewModel(IWhatever model)
{
this.model = model;
}
...
public string MyEnumView
{
get
{
return model.MyEnum.ToString();
}
}
public string MyEnumView2
{
get
{
switch(model.MyEnum)
{
case MyEnumType.A: return "Hello";
case MyEnumType.B: return "World";
}
}
}
}

Resources