469,945 Members | 1,813 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,945 developers. It's quick & easy.

propertygrid - user selectable unit

Lee
Hi,

Using the propertygrid, is it possible to have a user selectable 'unit
of measure' for a field.

For example, I am looking at using a propertygrid for defining inputs
into a calculation. Some of the inputs can be either monetary or
percantage. The ideal scenario is where the user enters the value and
immediately to the right of the value field is a drop down, defaulted
to %,which allows a currency to be selected.

I'm very new to c# so apologies if this is straightforward.

Thanks
Lee

Oct 14 '06 #1
5 2834
Hard to do "all in one", as the PropertyGrid uses the TypeConverter,
which allows for text conversions [inclusive or] list of available
options.

What you can do, however, is to split the two, and have the
TypeConverter be able to parse the entire string, else enter the value
and unit on separate lines in the grid.

See enclosed example (just add a CurrencyAmount property to your class
;-p).

Marc

using System;
using System.ComponentModel;

public enum UnitOfCurrency { GBP, USD, INR, EUR } // etc
public class CurrencyAmountConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context,
Type sourceType)
{
return sourceType == typeof(string) ||
base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
string text = value as string;
if (text == null) return base.ConvertFrom(context, culture,
value);
return CurrencyAmount.Parse(text);
}
public override bool
GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}
public override object CreateInstance(ITypeDescriptorContext
context, System.Collections.IDictionary propertyValues)
{
decimal amount = (decimal)propertyValues["Amount"];
UnitOfCurrency unit = (UnitOfCurrency)propertyValues["Unit"];
return new CurrencyAmount(unit, amount);
}
public override bool GetPropertiesSupported(ITypeDescriptorContext
context)
{
return true;
}
public override PropertyDescriptorCollection
GetProperties(ITypeDescriptorContext context, object value, Attribute[]
attributes)
{
return TypeDescriptor.GetProperties(typeof(CurrencyAmount ),
attributes).Sort(new string[] { "Amount", "Unit" });
}
}

[TypeConverter(typeof(CurrencyAmountConverter))]
[ImmutableObject(true)]
public struct CurrencyAmount : IEquatable<CurrencyAmount>, IComparable,
IComparable<CurrencyAmount>
{
public static CurrencyAmount operator *(CurrencyAmount lhs, decimal
rhs)
{
return new CurrencyAmount(lhs.Unit, lhs.Amount * rhs);
}
public int CompareTo(CurrencyAmount other)
{
int result = this.Unit.CompareTo(other.Unit);
if (result == 0) result = this.Amount.CompareTo(other.Amount);
return result;
}
int IComparable.CompareTo(object other)
{
return CompareTo((CurrencyAmount)other);
}
public override int GetHashCode()
{
return _amount.GetHashCode() * 7 + _unit.GetHashCode();
}
public override bool Equals(object obj)
{
return base.Equals((CurrencyAmount)obj);
}
public bool Equals(CurrencyAmount amount)
{
return (amount == this);
}
public static bool operator <(CurrencyAmount lhs, CurrencyAmount
rhs)
{
return lhs.Unit == rhs.Unit && lhs.Amount < rhs.Amount;
}
public static bool operator >(CurrencyAmount lhs, CurrencyAmount
rhs)
{
return lhs.Unit == rhs.Unit && lhs.Amount rhs.Amount;
}
public static bool operator <=(CurrencyAmount lhs, CurrencyAmount
rhs)
{
return lhs.Unit == rhs.Unit && lhs.Amount <= rhs.Amount;
}
public static bool operator >=(CurrencyAmount lhs, CurrencyAmount
rhs)
{
return lhs.Unit == rhs.Unit && lhs.Amount >= rhs.Amount;
}
public static bool operator ==(CurrencyAmount lhs, CurrencyAmount
rhs)
{
return lhs.Unit == rhs.Unit && lhs.Amount == rhs.Amount;
}
public static bool operator !=(CurrencyAmount lhs, CurrencyAmount
rhs)
{
return lhs.Unit != rhs.Unit || lhs.Amount != rhs.Amount;
}
private readonly decimal _amount;
private readonly UnitOfCurrency _unit;
public decimal Amount { get { return _amount; } }
public UnitOfCurrency Unit { get { return _unit; } }
public CurrencyAmount(UnitOfCurrency unit, decimal amount)
{
_amount = amount;
_unit = unit;
}
public override string ToString()
{
return _unit.ToString() + ": " + _amount;
}
public static CurrencyAmount Parse(string value)
{
if (value != null) value = value.Trim();
if (string.IsNullOrEmpty(value)) throw new
ArgumentNullException();
string[] parts = value.Split(':');
if (parts.Length != 2) throw new ArgumentException();
return new CurrencyAmount(
(UnitOfCurrency)Enum.Parse(typeof(UnitOfCurrency),
parts[0].Trim(), true),
decimal.Parse(parts[1].Trim()));

}
}

Oct 14 '06 #2
I forgot to say; if the drop-down is runtime (not simply an enum) then
you need a type converter for that too ;-p Specifically, you'd look at
the GetStandardValues, ...Supported and ...Exclusive methods. Note that
the context gives you the parent object, so you should be able to do
some clever "likely options" code if you want...

Marc

Oct 14 '06 #3
An alternative answer (sorry; brain not firing 100% this evening ;-p):
look into UITypeEditor implementations; this is basically a way of
providing a drop-down UI.

This would allow you to place a custom control or two on the drop down,
with the appropriate values into the screen. Look at:
http://msdn2.microsoft.com/en-us/lib...ypeeditor.aspx
In particular, think GetEditStyle() returning DropDown, EditValue
showing your control. You can also do "Modal", which displays the
elipsis.

In terms of what this looks like : think "dock", "anchor" etc; it can
look like whatever you want...

Marc

Oct 14 '06 #4
Hello Lee,

Marc already gave you some pointers for workarounds. This is a fact
that you won't be able to have an editable number + its unit in the
same property row with the Microsoft PropertyGrid. So I have no other
solution to give you. However, if representing your data in a single
row is a strong requirement for you and you can consider a commercial
package, you can try Smart PropertyGrid.Net. There is a screenshot of
this value+unit property in action at
http://www.visualhint.com/visualhint...etfeature6.gif. I can tell
you that from the end-user point of view this is very practical. If you
have any question, you can contact me there
(http://www.visualhint.com/helpdesk).

Best regards,

Nicolas Cadilhac @ VisualHint (http://www.visualhint.com)
Home of Smart PropertyGrid for .Net and MFC

Lee wrote:
Hi,

Using the propertygrid, is it possible to have a user selectable 'unit
of measure' for a field.

For example, I am looking at using a propertygrid for defining inputs
into a calculation. Some of the inputs can be either monetary or
percantage. The ideal scenario is where the user enters the value and
immediately to the right of the value field is a drop down, defaulted
to %,which allows a currency to be selected.

I'm very new to c# so apologies if this is straightforward.

Thanks
Lee
Oct 15 '06 #5
Lee
Marc,

Many thanks for the responses. I will investigate the UITypeEditor
class which sounds very promising..

Lee

Oct 15 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Dave Girvitz | last post: by
1 post views Thread by margoulin | last post: by
1 post views Thread by SDK | last post: by
4 posts views Thread by Bernie Yaeger | last post: by
4 posts views Thread by phcmi | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.