Guidance on using CSLA’s EditableRootList for Management UIs

by JasonRShaver 28. October 2009 17:01

 

I commonly have the situation in my Silverlight 3 Line-of-business (LOB) applications of having a screen with the left side being a EditableRootList (such as CustomerList) and the right side being the EditableRoot (such as Customer) that is being edited.  As a note, you may want to use the “stretch” button at the top right of this blog to make the code more readable.  What I want is a UI where I can:

·         Add or Delete items from the list on the left

·         Modify items on the right

·         Have my Apply button save ALL the changes in the list.

Here are some of the key points in the XAML file, note the “emphasized” sections:

Defining the resources and CslaDataProviders:

<UserControl.Resources>

            <csla:CslaDataProvider x:Key="Customer"

                           ManageObjectLifetime="False"

                           IsInitialLoadEnabled="False"

                           ObjectType="Entities.Customer"

                           DataChanged="Customer_DataChanged" />

            <csla:CslaDataProvider x:Key="CustomerList"

                           ManageObjectLifetime="True"

                           IsInitialLoadEnabled="True"

                           ObjectType="Entities.CustomerList "

                           FactoryMethod="GetAll"

                           Saved="CustomerList_Saved"/>

            <core:NullToBooleanConverter x:Key="NullToBooleanConverter" />

            <core:VisibilityConverter x:Key="VisibilityConverter" />

            <core:DeletedToOpacityConverter x:Key="DeletedToOpacityConverter" />

</UserControl.Resources>

Defining the left side ListBox:

      <ListBox x:Name="listCustomers" ItemsSource="{Binding Source={StaticResource CustomerList}, Path=Data}"

                        SelectionChanged="listCustomers_SelectionChanged" >

            <ListBox.ItemTemplate>

                  <DataTemplate>

                        <StackPanel Orientation="Horizontal">

                              <TextBlock Text="{Binding Path=Name}"  

     Opacity="{Binding IsDeleted, Converter={StaticResource DeletedToOpacityConverter}}" />

                              <TextBlock Text="(Deleted)" Foreground="Red" Margin="2,0,0,0"

                                         Visibility="{Binding IsDeleted, Converter={StaticResource VisibilityConverter}}" />

                              <TextBlock Text="(New)" Foreground="Red" Margin="2,0,0,0"

                                         Visibility="{Binding IsNew, Converter={StaticResource VisibilityConverter}}" />

                        </StackPanel>

                  </DataTemplate>

            </ListBox.ItemTemplate>

      </ListBox>

And in your code behind, I put these helpers

      private CslaDataProvider CustomerProvider

      {

            get { return ((CslaDataProvider)this.Resources["Customer"]); }

      }

      private Customer Customer

      {

            get { return CustomerProvider.ObjectInstance as Customer; }

      }

      private CslaDataProvider CustomerListProvider

      {

            get { return ((CslaDataProvider)this.Resources["CustomerList"]); }

      }

      private CustomerList CustomerList

      {

            get { return CustomerListProvider.ObjectInstance as CustomerList; }

      }

And the general event handlers look like this:

      private void listCustomers_SelectionChanged(object sender, SelectionChangedEventArgs e)

      {

            CustomerProvider.ObjectInstance = listCustomers.SelectedItem;

      }

private void btnApply_Click(object sender, RoutedEventArgs e)

      {

            CustomerListProvider.Save();

      }

private void btnNewCustomer_Click(object sender, RoutedEventArgs e)

      {

            CustomerProvider.FactoryMethod = "NewCustomer";

            CustomerProvider.FactoryParameters.Clear();

            CustomerProvider.Refresh();

      }

private void btnDeleteCustomer_Click(object sender, RoutedEventArgs e)

      {

            this.CustomerProvider.Delete();

      }          

private void Customer_DataChanged(object sender, EventArgs e)

      {

            var ThisItem = Customer as Customer;

            if (ThisItem != null && ThisItem.IsNew)

                  if (CustomerList.Contains(ThisItem) == false)

                        this.CustomerList.Add(ThisItem);

      }

      private void CustomerList_Saved(object sender, Csla.Core.SavedEventArgs e)

      {

            CustomerListProvider.Refresh();

      }

And the “converters” required to make this work:

public class VisibilityConverter : IValueConverter

      {

            public object Convert(object value,Type targetType,object parameter,CultureInfo culture)

            {

                  bool visibility = (bool)value;

                  return visibility ? Visibility.Visible : Visibility.Collapsed;

            }

 

            public object ConvertBack(object value,Type targetType,object parameter,CultureInfo culture)

            {

                  Visibility visibility = (Visibility)value;

                  return (visibility == Visibility.Visible);

            }

      }

public class DeletedToOpacityConverter : IValueConverter

      {

            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

            {

                  bool IsDeleted = (bool)value;

                  return IsDeleted ? (Double)0.3 : (Double)1.0;

            }

 

            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

            {

                  throw new NotSupportedException();

            }

      }

And finally you need to make sure you EditableRootList implementations have a DataPortal_Update() implementation.  Here is a simple one:

protected void DataPortal_Update()

      {

         foreach (var Item in this)

         {

            Item.Save();

         }

      }

If you found this useful, please leave a comment.  If you find a way to do it better, PLEASE leave a comment.  

 

Tags:

Blog

About the author

I am a software developer working for Microsoft in Redmond, WA.  In addition, my wife and I own TTXOnline, what is likely the 3rd largest table tennis store in the US.

Month List

Page List