Category Archives: Silverlight 4

Datagrid Visibility and DomainDataSource DataView Count

Problem

The problem was relatively simple. Hide or show a datagrid depending on whether the datasource had rows or not.

I created a converter that converted the datasource row count to a visibility property, and implemented it like so

 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            DomainDataSource lv_item = value as DomainDataSource;
            Boolean lv_rowsExist = (lv_item.DataView.Count > 0);

            if (lv_rowsExist)
                    return Visibility.Visible;

            return Visibility.Collapsed;
        }

<sdk:DataGrid Visibility=”{Binding ElementName=domaindatasource1, Converter={StaticResource domainDataSourceRowsToVisibilityConverter} ….etc

And subsequently the converter was NEVER called after I called the datasource load event….I was baffled.

Solution

Once I found the solution it was pretty obvious, and perhaps those of you using the MVVM design pattern would have spotted it right away.

Anyone created a MVVM viewmodel knows to implement a PropertyEvent changed handler. Its called a PROPERTY event changed handler for a reason. I knew the DomainDataSource would implement something like this, but why wasnt it firing when I loaded data? Well…it was. I had just bound my the visibility of my datagrid to the DomainDataSource object itself..not a property. When loading data the DDS itself wasnt changing…so there was no reason to call the converter.

The solution of course was to bind the Visibility to the DDS Data Count PROPERTY! Like so

Visibility=”{Binding ElementName=domaindatasource1, Path=Data.Count, Converter={StaticResource domainDataSourceRowsToVisibilityConverter}….etc

This property DID change everytime I loaded data, and ergo the converter was properly called.

I won’t forget this one to soon!

Advertisements

Global BusyIndicator for DomainDataContext

Problem:

With Asynchronous calls in Silverlight its important to let the user know something is happening when they request data. At first I put a BusyIndictor in the Navigation content, which was ugly because it left a large border showing around the BusyIndicator for those elements that are not part of the Navigation content.

Solution

What I was looking for was some way, on an application level, to show a BusyIndicator. I came across this post by Bryan Sampica which was very useful.  http://weblogs.asp.net/bryansampica/archive/2010/07/09/global-busyindicator-for-domaincontext.aspx

This worked perfectly on a DomainContext level, BUT, I was using a bunch of DomainDataSources, which would always be busy for longer than the DomainContext itself. Which meant the BusyIndicator dissapeared before the actual data was available…what a pity.

So I kept the concept of using a BusyIndicator as the rootvisual, but ditched the domaincontext class extension. And then just manipulated the Global BusyIndicator depending on whether the DomainDataSource is loading or not.

Something like this.

domainDataSource1.Load();
BusyIndicator busy = (BusyIndicator)App.Current.RootVisual;
busy.IsBusy = true;

private void DomainDataSource1_LoadedData(object sender, LoadedDataEventArgs e)
{

BusyIndicator busy = (BusyIndicator)App.Current.RootVisual;
                busy.IsBusy = false;
}

The DomainDataSource1’s LoadedData event is handled by DomainDataSource1_LoadedData

Images not showing at runtime

Problem:

Just came across this frustrating little quirk. I’ve defined all my logos and background images etc. in the Silverlight stylesheet Styles.xaml. Both the images and stylesheet are in the /Assets/ folder. The images all showed fine at design time, but at runtime none showed.

No combination of back/forward-slashes, absolute paths, using PNG’s vs GIFS, changing the build action of the images etc made a difference.

Solution:

So I went back to the basics. I dragged and dropped an image control onto the master page, and set the resource to point to one of my images. And this is what the codebehind ended up looking like:

<Image Source=”/TrackAndTrace;component/Assets/Logo.png” />

Applying this logic to my Stylesheet solved the problems!

Strangely enought microsofts documentation didn’t provide my with any insight to this method of specifying an image source. So I’m not sure WHAT it is I’m actually specifying and WHY…which is always frustrating.

http://msdn.microsoft.com/en-us/library/system.windows.controls.image.source(v=VS.100).aspx

Is ‘TrackAndTrace’ a reference to a path, the application name, the namespace???

MVVM or domaindatasource

I spent a day delving into the basics of the MVVM model and implementing it in my current project. It took me several hours to implment a simple example using strict MVVM practises. Using DomainDataSource takes me minutes to do the same thing.
The only info I find on the interwebs regarding DDS vs MVVM boils down to “Don’t use DDS, its bad practise”….I’m not convinced. But they days are young. I expect that somewhere down the road I’ll realise I’ve made a huge design flaw and end up refactoring/redesigning everything…hehe

ComboBox and DataForms using DomainDataSource

Problem:

I couldnt believe how tricky this was to implement, mainly because the lack of accurate or useful info on the web.

Basically all I wanted to do was populate a combobox within a dataform and set the selectedvalue. Apparently Silverlight 4 adds some new properties to the  combobox which make this easier. However most info is pre-silverlight 4 and based on examples not using the DomainDataSource.

Solution:

I think the main trick to this solution was to implement the datasource for the combobox as a staticresource .

 <UserControl.Resources>
 <riaControls:DomainDataSource x:Key=”shipmentStatusDomainDataSource”
                   QueryName=”GetShipmentStatus”
                   AutoLoad=”True” SubmittedChanges=”shipmentStatusDomainDataSource_SubmittedChanges” LoadedData=”shipmentStatusDomainDataSource_LoadedData”>
                <riaControls:DomainDataSource.DomainContext>
                    <ds:OrdersDomainContext/>
                </riaControls:DomainDataSource.DomainContext>
            </riaControls:DomainDataSource>
</UserControl.Resources>

 <toolkit:DataForm
 ….
<toolkit:DataField Label=”Status”>
    <ComboBox
     ItemsSource=”{Binding Data, Source={StaticResource shipmentStatusDomainDataSource}, Mode=OneWay}”
 DisplayMemberPath=”Status” SelectedValue=”{Binding StatusId,Mode=TwoWay}” SelectedValuePath=”Id” />
</toolkit:DataField>

StatusID is a field from the master grid to which the dataform is bound. Id and Status are values from the shipmentStatusDomainDataSource.

 

Dataform Autocommit = false

Problem:

I have a gridview and dataform master/detail setup. While editing the details of a record in the dataform, if the user clicks on a new parent record, I didn’t want the record to be committed. BUT setting autocommit=false on the dataform brought with it all kinds of problems. Most commonly the “cannot change currency when an item has validation errors or it is being edited” error! Arrrgh.

One elegant solution I found was as to handle the selectionchanged event of the gridview and ask the user if they want to save or cancel the changes. Regardless of what I did however, the “cannot change currency” error always reared its ugly head. Eventually I found a solution, when I discoverd that when Autocommit is set to True and the user selects a new record before commiting changes the DataForms IsItemChanged property is FALSE…aha! Which led me to the following (excuse the formatting I’ll setup wordpress properly later!)

Solution:

  <toolkit:DataForm Name=”DetailForm” Header=”Details” AutoGenerateFields=”False” AutoEdit=”False” AutoCommit=”True” CurrentItem=”{Binding SelectedItem, ElementName=dgShipmentBookingConfirmation}” EditEnded=”DetailForm_EditEnded” BeginningEdit=”DetailForm_EditStart” CommitButtonContent=”Save” CancelButtonContent=”Cancel” CommandButtonsVisibility=”Cancel,Edit,Commit” >

protected void DetailForm_EditEnded(object sender, DataFormEditEndedEventArgs e)
{
    m_editing = false;

    if (e.EditAction == DataFormEditAction.Commit)
    {
 if (DetailForm.IsItemChanged)
 {
     domainDataSource10.SubmitChanges();
 }
 else
 /* It seems counter intuitive but even though IsItemChanged is FALSE
 there are still changes to the datasource that can be comitted */
 {
     if(MessageBox.Show("Select OK to save your changes or Cancel to cancel them.", "Save changes?", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
  domainDataSource10.SubmitChanges();
     else
  domainDataSource10.RejectChanges();
 }
    }
}

The ‘m_editing’ variable I use to track if we are in edit mode or not. Why? If you are editing data in the dataform and call ‘domainDataSource.Load’ you’ll get an error. So you either need to check the ‘domainDataSource.CanLoad’  property, or handle it some other way as I did, but thats another matter.

Ok back to work…