I know that in C#, properties are supposed to be quick operations (not reading data from a network or file system, etc.) However, I am building a Silverlight app and I need to bind a XAML element to some network data on a ViewModel. As far as I am aware,开发者_运维技巧 binding can only be done to properties, not methods. Should I break the guideline here, or is there another way around this that's not occurring to me?
<ListBox ItemsSource="{Binding Users}" />
public IEnumerable<User> Users
{
get
{
// may be cached
return expensiveNetworkCall();
}
}
Actually, although I haven't used it yet, you can bind to methods with the ObjectDataProvider
. See here: http://www.thomasclaudiushuber.com/blog/2008/01/10/bind-to-methods-with-objectdataprovider/
I would break the rule and bind to the property. Although, as @Tom states, you can bind to a method, it will not make a difference user-experience wise. You could use an ObservableCollection
(instead of IEnumerable
) and load the users on another thread. Maybe even with an explicit command bound to a button to initiate the expensive call.
I think the concern here is - should you make your users wait for the complete binding to take place? You could spawn that activity off to another method and return what you got (nothing in the beginning, something next time they call).
You could also let the users know that the values are not yet all available and give them the chance to refresh and then start showing the results of the long running network related process.
Properties should only be used for simple data / member access and should never represent a lengthy operation such as a network call. A method is much more appropriate for this scenario.
Having it as a method may be convenient today for your UI scenario but will lead to problems down the road. Binding diretly to a method is not supported as easily as properties because a method implies an operation that probably shouldn't be bound to the UI. For example if the underlying network connection hangs it will lead to a direct hang in hte UI. This is a quick way to frustrate users.
Here's an alternative approach
- Instead of an
IEnumerable<Users>
use aBindingCollection<Users>
- Have the
BindingCollection<Users>
start off as empty and queue a network request for the users - When the network request is completed update the
BindingCollection<Users>
with the found data (make sure to Invoke back to the UI thread)
精彩评论