1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
24 // Jackson Harper jackson@ximian.com
28 using System
.ComponentModel
;
30 namespace System
.Windows
.Forms
{
32 [TypeConverter (typeof (ListBindingConverter
))]
33 public class Binding
{
35 private string property_name
;
36 private object data_source
;
37 private string data_member
;
39 private BindingMemberInfo binding_member_info
;
40 private Control control
;
42 private BindingManagerBase manager
;
43 private PropertyDescriptor control_property
;
44 private PropertyDescriptor is_null_desc
;
47 private Type data_type
;
49 #region Public Constructors
50 public Binding (string propertyName
, object dataSource
, string dataMember
)
52 property_name
= propertyName
;
53 data_source
= dataSource
;
54 data_member
= dataMember
;
55 binding_member_info
= new BindingMemberInfo (dataMember
);
57 #endregion // Public Constructors
59 #region Public Instance Properties
60 public BindingManagerBase BindingManagerBase
{
66 public BindingMemberInfo BindingMemberInfo
{
68 return binding_member_info
;
73 public Control Control
{
79 public object DataSource
{
85 public bool IsBinding
{
87 if (control
== null || !control
.Created
)
89 if (manager
== null || manager
.IsSuspended
)
96 public string PropertyName
{
101 #endregion // Public Instance Properties
103 #region Protected Instance Methods
104 protected virtual void OnFormat (ConvertEventArgs cevent
)
107 Format (this, cevent
);
110 protected virtual void OnParse (ConvertEventArgs cevent
)
113 Parse (this, cevent
);
115 #endregion // Protected Instance Methods
118 internal void SetControl (Control control
)
120 if (control
== this.control
)
123 control_property
= TypeDescriptor
.GetProperties (control
).Find (property_name
, true);
125 if (control_property
== null)
126 throw new ArgumentException (String
.Concat ("Cannot bind to property '", property_name
, "' on target control."));
127 if (control_property
.IsReadOnly
)
128 throw new ArgumentException (String
.Concat ("Cannot bind to property '", property_name
, "' because it is read only."));
130 data_type
= control_property
.PropertyType
; // Getting the PropertyType is kinda slow and it should never change, so it is cached
131 control
.Validating
+= new CancelEventHandler (ControlValidatingHandler
);
133 this.control
= control
;
136 internal void Check (BindingContext binding_context
)
138 if (control
== null || control
.BindingContext
== null)
141 manager
= control
.BindingContext
[data_source
, data_member
];
143 manager
.AddBinding (this);
144 manager
.PositionChanged
+= new EventHandler (PositionChangedHandler
);
146 is_null_desc
= TypeDescriptor
.GetProperties (manager
.Current
).Find (property_name
+ "IsNull", false);
151 internal void PullData ()
153 if (IsBinding
== false || manager
.Current
== null)
156 data
= control_property
.GetValue (control
);
157 SetPropertyValue (data
);
160 internal void PushData ()
162 if (manager
== null || manager
.IsSuspended
|| manager
.Current
== null)
165 if (is_null_desc
!= null) {
166 bool is_null
= (bool) is_null_desc
.GetValue (manager
.Current
);
168 data
= Convert
.DBNull
;
173 PropertyDescriptor pd
= TypeDescriptor
.GetProperties (manager
.Current
).Find (binding_member_info
.BindingField
, true);
175 data
= manager
.Current
;
177 data
= pd
.GetValue (manager
.Current
);
180 data
= FormatData (data
);
181 SetControlValue (data
);
184 internal void UpdateIsBinding ()
189 private void SetControlValue (object data
)
191 control_property
.SetValue (control
, data
);
194 private void SetPropertyValue (object data
)
196 PropertyDescriptor pd
= TypeDescriptor
.GetProperties (manager
.Current
).Find (binding_member_info
.BindingField
, true);
199 data
= ParseData (data
, pd
.PropertyType
);
200 pd
.SetValue (manager
.Current
, data
);
203 private void ControlValidatingHandler (object sender
, CancelEventArgs e
)
205 object old_data
= data
;
207 // If the data doesn't seem to be valid (it can't be converted,
208 // is the wrong type, etc, we reset to the old data value.
213 SetControlValue (data
);
217 private void PositionChangedHandler (object sender
, EventArgs e
)
222 private object ParseData (object data
, Type data_type
)
224 ConvertEventArgs e
= new ConvertEventArgs (data
, data_type
);
227 if (data_type
.IsInstanceOfType (e
.Value
))
229 if (e
.Value
== Convert
.DBNull
)
232 return ConvertData (e
.Value
, data_type
);
235 private object FormatData (object data
)
237 if (data_type
== typeof (object))
240 ConvertEventArgs e
= new ConvertEventArgs (data
, data_type
);
243 if (data_type
.IsInstanceOfType (e
.Value
))
246 return ConvertData (data
, data_type
);
249 private object ConvertData (object data
, Type data_type
)
251 TypeConverter converter
= TypeDescriptor
.GetConverter (data
.GetType ());
252 if (converter
!= null && converter
.CanConvertTo (data_type
))
253 return converter
.ConvertTo (data
, data_type
);
255 if (data
is IConvertible
) {
256 object res
= Convert
.ChangeType (data
, data_type
);
257 if (data_type
.IsInstanceOfType (res
))
265 public event ConvertEventHandler Format
;
266 public event ConvertEventHandler Parse
;