silverlight 4 combo box

silverlight 4 combo box

Old forum URL: forums.lhotka.net/forums/t/8535.aspx


germie posted on Monday, February 15, 2010

i know this is more a silverlight/xaml question but maybe someone here has had the same issue. i am using two CslaDataProviders in my Xaml.

        <csla:CslaDataProvider x:Key="data"
                               ObjectType="Business.bizMaintUsers, Business"
                               FactoryMethod="GetUsers"
                               DataChangedHandler="{StaticResource DataErrorDialog}"
                               IsInitialLoadEnabled="True" />
        <csla:CslaDataProvider x:Key="plantsData"
                               ObjectType="Business.bizPlants, Business"
                               FactoryMethod="GetPlants"
                               DataChangedHandler="{StaticResource DataErrorDialog}"
                               IsInitialLoadEnabled="True"
                               DataChanged="CslaDataProvider_plantsDataChanged" />

one to load info into a DataGrid (data) and one to load info into a Combo Box (plantsData) with value/key info. i have the DataGrid bound like this

DataContext="{Binding Data, Source={StaticResource data}}"

and the Combo Box inside the DataGrid

<swcd:DataGridTemplateColumn Header="Plant">
   <swcd:DataGridTemplateColumn.CellEditingTemplate>
      <DataTemplate>
         <ComboBox x:Name="cboUsers"                                          
                   ItemsSource="{Binding Source={StaticResource plantsData},Path=Data, Mode=TwoWay}"
                   DisplayMemberPath="PlantName"
                   SelectedValuePath="Sysid"
                   SelectedValue="{Binding Mode=TwoWay, Path=PlantId}"  />
      </DataTemplate>
   </swcd:DataGridTemplateColumn.CellEditingTemplate>
</swcd:DataGridTemplateColumn>

the problem i am having is that the combo box will get loaded with the correct info but it does not get set automatically. the only way i got it to work is by using the

DataChanged="CslaDataProvider_plantsDataChanged"

and in the code behind i refresh the DataGrid info

Private Sub CslaDataProvider_plantsDataChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
  Dim dp As Csla.Silverlight.CslaDataProvider = Resources("data")
  dp.Refresh()
End Sub

after the data is refreshed the Combo Box is set correctly but there seems to be a more efficient way to do this so im not making two calls to get the data. any ideas?

germie

 

 

 

 

 

 

 

RockfordLhotka replied on Monday, February 15, 2010

Could it be a bug in the SL4 combobox? In SL2 and SL3 they didn't have a way to bind to the selected id value, so everyone had to write their own subclass (see some of the CSLA samples for example). I'd heard they fixed this in SL4, but haven't had time to look - but since it is a new feature, perhaps it doesn't totally work yet?

Peran replied on Tuesday, February 16, 2010

I had a similar issue in Silverlight 3 using MVVM rather than DataProviders.  Essentially you need to make sure your NameValueList is bound to the combobox before you bind the BusinessObject, with 2 asynchronous data fetches you have no idea which one will be bound to the combobox first, so you may get inconsistent results.  This is probably correct behaviour for the ComboBox because if a value is bound to a combobox and that value is not in the combobox list an exception would be generated (which is currently being swallowed by the UI).

In my ViewModel I ensure all my NameValueLists have been fetched before I fetch the BusinessObject. It looks like you are doing something similar with the event handler and I think if you made IsInitialLoadEnabled="False"on x:Key="data" you would only be making one call to fetch the data.

Thinking about my solution now, I have modified my ViewModel to solve a particular UI issue which may not be in the spirit of MVVM...maybe an alternative would be extend the combobox to force a rebind of SelectedItem/Value whenever the Items list changes???

 

 

Peran

RockfordLhotka replied on Tuesday, February 16, 2010

Peran

Thinking about my solution now, I have modified my ViewModel to solve a particular UI issue which may not be in the spirit of MVVM...maybe an alternative would be extend the combobox to force a rebind of SelectedItem/Value whenever the Items list changes???

I'm not sure you violated the spirit of the pattern. The viewmodel is part of the UI layer, and so is by definition UI-specific. As long as your viewmodel doesn't use any XAML or view-specific types you are good.

It seems like a perfectly reasonable idea that the viewmodel might control the order in which data is retrieved.

Another solution is to use a unit of work object to get all required data for the view. Often this is a ReadOnlyBase object that, on the server, calls the factory methods of all the required business objects and returns them to the UI as a unit. That avoids the ordering issue (somewhat) because all required objects arrive on the client at the same time.

germie replied on Tuesday, February 16, 2010

RockfordLhotka
Another solution is to use a unit of work object to get all required data for the view.

are there any UOW samples? that sounds like it will work the best

ajj3085 replied on Tuesday, February 16, 2010

It would just be a command object with properties containing the various data.

RockfordLhotka replied on Tuesday, February 16, 2010

I use a ROB for fetching data and a Command object for updates. ROB is more efficient if all you are doing is retrieving data.

I have a full sample as part of the code in the CSLA .NET Core 3.8 video series.

The basic structure is:

public class UoW : ReadOnlyBase<UoW>
{
  private Customer _customer;
  public Customer Customer
  {
    get { return _customer; }
  }

  private void DataPortal_Fetch()
  {
    _customer = Customer.GetCustomer();
  }
}

Just add a static factory, more properties and more factory calls in the DP_Fetch() method. In many cases you'll also pass a criteria object that contains enough criteria to know which objects to actually get in DP_Fetch().

Note that other types, like Customer in this example, are entirely normal - you don't do anything different in their implementation.

germie replied on Tuesday, February 16, 2010

thanks rocky, i havent had a chance to see those videos yet. but i did get it working right by changing the

Private Sub CslaDataProvider_plantsDataChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
  Dim dp As Csla.Silverlight.CslaDataProvider = Resources("data")
  dp.Refresh()
End Sub

to dp.Rebind() and the CB loads and gets set with only one call Smile don't know why i didn't think of that first. but thanks for your responces (peran and andy too) and i will be checking out your Core 3.8 videos soon.

germie

Copyright (c) Marimer LLC