propertygrid - user selectable unit

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Lee

    propertygrid - user selectable unit

    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

  • Marc Gravell

    #2
    Re: propertygrid - user selectable unit

    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.Componen tModel;

    public enum UnitOfCurrency { GBP, USD, INR, EUR } // etc
    public class CurrencyAmountC onverter : TypeConverter
    {
    public override bool CanConvertFrom( ITypeDescriptor Context context,
    Type sourceType)
    {
    return sourceType == typeof(string) ||
    base.CanConvert From(context, sourceType);
    }
    public override object ConvertFrom(ITy peDescriptorCon text context,
    System.Globaliz ation.CultureIn fo culture, object value)
    {
    string text = value as string;
    if (text == null) return base.ConvertFro m(context, culture,
    value);
    return CurrencyAmount. Parse(text);
    }
    public override bool
    GetCreateInstan ceSupported(ITy peDescriptorCon text context)
    {
    return true;
    }
    public override object CreateInstance( ITypeDescriptor Context
    context, System.Collecti ons.IDictionary propertyValues)
    {
    decimal amount = (decimal)proper tyValues["Amount"];
    UnitOfCurrency unit = (UnitOfCurrency )propertyValues["Unit"];
    return new CurrencyAmount( unit, amount);
    }
    public override bool GetPropertiesSu pported(ITypeDe scriptorContext
    context)
    {
    return true;
    }
    public override PropertyDescrip torCollection
    GetProperties(I TypeDescriptorC ontext context, object value, Attribute[]
    attributes)
    {
    return TypeDescriptor. GetProperties(t ypeof(CurrencyA mount),
    attributes).Sor t(new string[] { "Amount", "Unit" });
    }
    }

    [TypeConverter(t ypeof(CurrencyA mountConverter) )]
    [ImmutableObject (true)]
    public struct CurrencyAmount : IEquatable<Curr encyAmount>, IComparable,
    IComparable<Cur rencyAmount>
    {
    public static CurrencyAmount operator *(CurrencyAmoun t lhs, decimal
    rhs)
    {
    return new CurrencyAmount( lhs.Unit, lhs.Amount * rhs);
    }
    public int CompareTo(Curre ncyAmount other)
    {
    int result = this.Unit.Compa reTo(other.Unit );
    if (result == 0) result = this.Amount.Com pareTo(other.Am ount);
    return result;
    }
    int IComparable.Com pareTo(object other)
    {
    return CompareTo((Curr encyAmount)othe r);
    }
    public override int GetHashCode()
    {
    return _amount.GetHash Code() * 7 + _unit.GetHashCo de();
    }
    public override bool Equals(object obj)
    {
    return base.Equals((Cu rrencyAmount)ob j);
    }
    public bool Equals(Currency Amount amount)
    {
    return (amount == this);
    }
    public static bool operator <(CurrencyAmoun t lhs, CurrencyAmount
    rhs)
    {
    return lhs.Unit == rhs.Unit && lhs.Amount < rhs.Amount;
    }
    public static bool operator >(CurrencyAmoun t lhs, CurrencyAmount
    rhs)
    {
    return lhs.Unit == rhs.Unit && lhs.Amount rhs.Amount;
    }
    public static bool operator <=(CurrencyAmou nt lhs, CurrencyAmount
    rhs)
    {
    return lhs.Unit == rhs.Unit && lhs.Amount <= rhs.Amount;
    }
    public static bool operator >=(CurrencyAmou nt lhs, CurrencyAmount
    rhs)
    {
    return lhs.Unit == rhs.Unit && lhs.Amount >= rhs.Amount;
    }
    public static bool operator ==(CurrencyAmou nt lhs, CurrencyAmount
    rhs)
    {
    return lhs.Unit == rhs.Unit && lhs.Amount == rhs.Amount;
    }
    public static bool operator !=(CurrencyAmou nt 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.IsNullO rEmpty(value)) throw new
    ArgumentNullExc eption();
    string[] parts = value.Split(':' );
    if (parts.Length != 2) throw new ArgumentExcepti on();
    return new CurrencyAmount(
    (UnitOfCurrency )Enum.Parse(typ eof(UnitOfCurre ncy),
    parts[0].Trim(), true),
    decimal.Parse(p arts[1].Trim()));

    }
    }

    Comment

    • Marc Gravell

      #3
      Re: propertygrid - user selectable unit

      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 GetStandardValu es, ...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

      Comment

      • Marc Gravell

        #4
        Re: propertygrid - user selectable unit

        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:
        Provides a base class that can be used to design value editors that can provide a user interface (UI) for representing and editing the values of objects of the supported data types.

        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

        Comment

        • Nico

          #5
          Re: propertygrid - user selectable unit

          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.Ne t. 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

          Comment

          • Lee

            #6
            Re: propertygrid - user selectable unit

            Marc,

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

            Lee

            Comment

            Working...