Cascading dropdown list


  • We have a Silverlight 4 app that has a view which I think is a good candidate for Reactive Extensions. It has several dropdown lists. The first dropdown list is a list of US states. The second dropdown list is a list of counties based on the selected US state. The rest of the dropdown lists cascade down based on the selection above it. Is it a good strategy to us Rx to handle the asynchronous calls for the dropdown data? My thought is to subscribe to the observable collection of US states and before making a service call to get the list of counties. Can you point me to an example of doing something like this.

    Thank you!

    2012年3月1日 下午 06:27


  • Hi,

    There are many ways to do this with Rx.

    You can use Observable.FromEventPattern to convert an event such as SelectionChanged into an observable.  Create a change observable for each control.  Then write a SelectMany query using each change observable to make service requests asynchronously.  Add ObserveOnDispatcher to marshal the results to the UI thread (note that this extension is in System.Reactive.Windows.Threading.dll).  Subscribe to each query and modify the target control whenever new items are received.

    Below is an untested example.  This should help to give you some direction, but there are still lots of things you'll have to consider.  For example, do you need to prevent users from updating the UI while service requests are in flight?  Do you need to be able to interrupt requests?  (Search this forum for TakeUntil and Repeat.)  How are you going to model service requests?  Do you prefer to use commands instead of the SelectionChanged event (if you're using MVVM)?  Do you prefer bindings on ItemsSource instead of manipulating the controls in code (also related to MVVM)?

    Searching this forum will provide answers to these questions.

    You may also want to check out Rxx, which provides a bunch of convience wrappers for making web requests and features for creating reactive views and view models in Silverlight 4.

    public static class SelectorExtensions
    	public static IObservable<T> ItemSelectedObservable<T>(this Selector control)
    		return Observable.FromEventPattern<SelectionChangedEventHandler, SelectionChangedEventArgs>(
    			eh => control.SelectionChanged += eh, 
    			eh => control.SelectionChanged -= eh)
    			.Select(e => (T) e.EventArgs.AddedItems[0]);
    IObservable<UsState> stateSelected = usStatesComboBox.ItemSelectedObservable<UsState>();
    IObservable<County> countySelected = countiesComboBox.ItemSelectedObservable<County>();
    IObservable<IList<County>> newCountyChoices = 
    	from state in stateSelected
    	from countyChoices in GetCountyChoices(state)	// returns IObservable<IList<County>>
    	select countyChoices;
    IObservable<IList<Town>> newTownChoices = 
    	from county in countySelected
    	from townChoices in GetTownChoices(county)	// returns IObservable<IList<Town>>
    	select townChoices;
    	counties =>
    	towns =>

    - Dave

    • 已編輯 Dave Sexton 2012年3月1日 下午 08:26 Wording and code fixes
    2012年3月1日 下午 08:24