Of all changes that made it into the RIA Services RC release, one of the ones that I'm happiest about is the deletion of a class called ControlParameter.  Yes, ControlParameter is gone, gone, gone--finally!  If you’re wondering how you’ll get your UI-based filters and parameters to work without ControlParameter, do not fret… it’s easy; just use an ElementName binding!

Let’s take a look at the changes related to Filters and Parameters…

ControlParameter is gone… Good Riddance!

Since the inception of RIA Services, the DomainDataSource control has relied upon ControlParameter tags for specifying Filters and Query Parameters that are based on user input.  Here’s a snippet of what you’d often see:

<riaControls:DomainDataSource Name="storeDomainDataSource" AutoLoad="True"
                              LoadedData="storeDomainDataSource_LoadedData" 
                              QueryName="GetStoresQuery">
    <riaControls:DomainDataSource.DomainContext>
        <my:ContactContext />
    </riaControls:DomainDataSource.DomainContext>
 
    <riaControls:DomainDataSource.FilterDescriptors>
        <riaData:FilterDescriptorCollection LogicalOperator="Or">
            <riaControls:FilterDescriptor PropertyPath="StoreName"
                      Operator="Contains">
                <riaData:ControlParameter ControlName="storeFilter"
                                          PropertyName="Text"
                                          RefreshEventName="TextChanged" />
            </riaControls:FilterDescriptor>
            <riaControls:FilterDescriptor PropertyPath="City"
                      Operator="Contains">
                <riaData:ControlParameter ControlName="storeFilter"
                                          PropertyName="Text"
                                          RefreshEventName="TextChanged" />
            </riaControls:FilterDescriptor>
            <riaControls:FilterDescriptor PropertyPath="StateProvince"
                      Operator="Contains">
                <riaData:ControlParameter ControlName="storeFilter"
                                          PropertyName="Text"
                                          RefreshEventName="TextChanged" />
            </riaControls:FilterDescriptor>
        </riaData:FilterDescriptorCollection>
    </riaControls:DomainDataSource.FilterDescriptors>
</riaControls:DomainDataSource>

Here’s what the above code translates into with the Release Candidate approach:

<riaControls:DomainDataSource Name="storeDomainDataSource" AutoLoad="True"
                              LoadedData="storeDomainDataSource_LoadedData" 
                              QueryName="GetStoresQuery" FilterOperator="Or">
    <riaControls:DomainDataSource.DomainContext>
        <my:ContactContext />
    </riaControls:DomainDataSource.DomainContext>
 
    <riaControls:DomainDataSource.FilterDescriptors>
        <riaControls:FilterDescriptor PropertyPath="StoreName"
                  Operator="Contains"
                  Value="{Binding ElementName=storeFilter, Path=Text}" />
        <riaControls:FilterDescriptor PropertyPath="City"
                  Operator="Contains"
                  Value="{Binding ElementName=storeFilter, Path=Text}" />
        <riaControls:FilterDescriptor PropertyPath="StateProvince"
                  Operator="Contains"
                  Value="{Binding ElementName=storeFilter, Path=Text}" />
    </riaControls:DomainDataSource.FilterDescriptors>
</riaControls:DomainDataSource>


Notice that Parameter and FilterDescriptor both allow for their Value properties to use a Binding.  In fact, all properties on Parameter, FilterDescriptor, SortDescriptor, and GroupDescriptor now support bindings (we use DependencyProperty for all of them now).

FilterDescriptorCollection Changes

Before the Release Candidate (as you can see in the first code snippet above), you always had to create a new FilterDescriptorCollection for the FilterDescriptors; this was required because we had a LogicalOperator property on the collection that would determine how the filters were combined.  With the Release Candidate, we’ve made the FilterDescriptors property on DomainDataSource a read-only property, and we give you a collection by default.  This translates into a few noteworthy points:

  1. Your XAML (or code) will no longer create the FilterDescriptorCollection to use as the DomainDataSource.FilterDescriptors property value - instead you just put your FilterDescriptor tags directly into the FilterDescriptors property
  2. The LogicalOperator property has moved up to the DomainDataSource class itself, as a FilterOperator property
  3. The DomainDataSource.FilterDescriptors property will never be null and you cannot set it

Before making this change, it was literally impossible to set the LogicalOperator on the collection through the Properties window in Visual Studio, because apparently, no other collection ever created in the framework had properties on it that would need to be edited.  This was a good indication that the previous design was awkward.

Enum Support

DomainDataSource previously did not support Enum filters; now it does.  Stay tuned to my blog for another post in the near future that goes over this topic.

IgnoredValue Changes

FilterDescriptor.IgnoredValue allows you to specify a value that would indicate that the filter should be completely ignored.  For instance, if you default a filter control to “[Any Value]” you wouldn’t want that string to be used when composing a query; set the IgnoredValue to “[Any Value]” and we will skip right over this FilterDescriptor when composing the query.

Before the RC release, FilterDescriptor.IgnoredValue defaulted to an empty string; this made it especially difficult if you wanted an empty string to actually be used for a filter value.  Additionally, when we compared the the FilterDescriptor.Value to the IgnoredValue, we could very often get type mismatches.  This happened a lot with numeric values; we’d end up trying to compare a numeric Value to a string IgnoredValue, and even if they were the same, we’d find they were not equal.  Both of these behaviors have been changed with the release candidate.

Now, your FilterDescriptor will never accidentally get ignored because of an IgnoredValue default.  We default that property to a static value called FilterDescriptor.DefaultIgnoredValue; it’s just a new object().  So if you were previously relying on the default IgnoredValue of empty string, you will now need to specify IgnoredValue="" within your XAML.

If you were experiencing issues dealing with numeric filters and other filters where you were trying to specify an IgnvoredValue, your issues should now be resolved.  For instance, if you had IgnoredValue="0" on a filter for a numeric property, you likely noticed that the filter wasn’t being ignored--it will now get correctly ignored.

Namespace Consolidation

You will notice that we’ve consolidated all of the DomainDataSource-related classes into the System.Windows.Controls namespace.  You won’t have to register multiple namespaces for working with DomainDataSource anymore.

Closing Down v1

With this Release Candidate, we’re really closing down RIA Services Version 1.  Hopefully you’re recognizing many of these changes as items that you had thought could be improved upon.  And as always, please don’t hesitate to share your feedback with me or my team.