SL3 TabItem HeaderTemplate does not support DataBinding - PRISM work-around

An excerpt from this message thread on Silverlight.net follows:

TabControl and Databinding is a sore point for a while now. You can show your support in fixing it on this codeplex bug:
http://silverlight.codeplex.com/WorkItem/View.aspx?WorkItemId=3604 

We're planning on overhauling TabControl for the Silverlight vNext release.

Sincerely,

--
Justin Angel,
Blog @ http://silverlight.net/blogs/JustinAngel
Twitter @ http://twitter.com/JustinAngel

The problem reveals itself in the PRISM View Injection QuickStart: 

Since PRISM has a TabcontrolRegionAdapter for Silverlight we have a hook into the problem (for a work-around).  Excerpt from documentation on the BootStrapper follows:

Conditional compiling is used to register the TabControlRegionAdapter only for Silverlight. This is because when you add an item in a TabControl control in WPF, this item is wrapped inside a TabItem type. This is not applicable for Silverlight, where you must manually wrap the item into the TabItem; because of that, the TabControlRegionAdapter adapter was modified to both adapt a region to the TabControl control and to automatically add this wrapping.

PRISM users can update the TabControlRegionAdapter.cs, in the Composite.Presentation project, as follows:

private static TabItem PrepareContainerForItem(object item, DependencyObject parent)
{
TabItem container = item as
TabItem;
if (container == null
)
{
    container = new
TabItem();
    container.Content = item;
    container.DataContext = GetDataContext(item);
    container.Style = GetItemContainerStyle(parent);
    container.SetValue(IsGeneratedProperty, true
);

    // BillKrat.2009.08.06 - SL3 Template binding bug workaround

    if (container.Header != null
         && container.Header.ToString().Contains("Binding:"
))
    {
     PropertyInfo modelProperty = null
;

     // Strip "Binding:" from the header - leaving model property

     string modelPropName = container.Header.ToString().Replace("Binding:", ""
);

     // Get model properties and search for the property name provided

     PropertyInfo[] propInfo = container.DataContext.GetType().GetProperties();

    
if (propInfo != null
)
        modelProperty =
         propInfo.FirstOrDefault(p => p.Name.ToString() == modelPropName);

     // If found then update the header with the value

     if (modelProperty != null
)
        container.Header = modelProperty.GetValue(modelProperty, null
);
    }
}

return
container;
}

Instead of using Value="{Binding HeaderInfo}", which won't work under SL3, you can use "Binding:HeaderInfo" which will be processed by the above method.  (note: Header will be set/available when the container.Style property is set above).  An example follows:


<Regions:TabControlRegionAdapter.ItemContainerStyle>
    <Style TargetType="Controls:TabItem">
        <Setter Property="Header" Value="Binding:HeaderInfo"/>
    </Style>
</Regions:TabControlRegionAdapter.ItemContainerStyle>

Until the Silverlight Toolkit team resolves the issue this can serve as a work-around.   With some work it could be made more dynamic but this is a good starting point.

 

The model being used follows:

namespace UIComposition.Modules.Project
{
    public class
ProjectsListPresentationModel
    {
        public ObservableCollection<BusinessEntities.Project> Projects { get; set
; }

        public static string
HeaderInfo
        {
            get { return "Current Projects"
; }
        }
    }
}

EDITED - a better solution was provided on the following link.  Although I haven't tested it yet I was impressed that it resolves the problem with one line of code - my kind of fix!   I found the above to be a great learning exercise in the power of styles so I leave it intact as is.

PRISM User forum addressing the issue HERE


Tags: , , , ,
Categories: CompositeWPF


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Your Silverlight developer components are out of date

After getting Expression Blend 3 up and running I was ready to run the Zune sample and was greeted with the prompt to upgrade my Silverlight - I ran it and was then stopped by the message "Your Silverlight developer components are out of date".

This message had me banging my head for a while because I had just finished installing everything new on my x64, Windows 7, Visual Studio 2008 sp1 beta box.   Everything is the latest software in addition to Beta and CTP development apps!

The clue came from a situation I ran into with Visual Studio 2010 - it wouldn't convert Silverlight applications from Silverlight 2 to Silverlight 3, to be more specific it would act like it converted it successfully but the project never showed up.   VS2010 has a hardcoded reference to the 2.0 folder references; my work-around was to copy the 3.0 folder to 2.0 (I have a blog on this somewhere as well as an incident reported to Microsoft).

So my assumption was that Expression Blend 3, like Visual Studio 2010 has some hard references to Silverlight tools 2 so I installed it from the following link:

http://go.microsoft.com/?linkid=9394666

I was happy to see it install without complaints about Silverlight tools 3 being installed and I found I could now successfully run the Expression Blend 3 sample!!

The key to upgrading is to install old stuff!


Tags: ,
Categories:


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Where is Microsoft.Expression.Interactions?

That's the question I was asking after installing Microsoft Expression Blend 3.   It appears that two DLL references are missing - or at least misplaced.

They are located at C:\Program Files\Microsoft SDKs\Expression\Blend 3\Interactivity\Libraries. 

In my case (64bit) it was C:\Program Files(x86)\... as shown in the image that follows.

Add the references and all will be happy. 

Below you can see that after adding references our view will display.   Note Expression Blend 3 offers 140 controls! 


Tags: , , ,
Categories: WPF


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

VS2010, Silverlight 3 and Windows 7 - can't convert SL3 project

My adventures started when I was notified that my Windows 7 beta was going to expire in 2 days.  While I continued to work on it I created a "production" development box; I've learned my lesson - don't install Beta on a production box...

With my production box functional I now had to create a Beta box which has all the cool stuff like VS2010, Silverlight 3, C# 4.0, etc.

The problem was with a fresh install you cannot convert Silverlight projects - I needed my PRISM projects (which I won't code without) and was dismayed to find out that everything "appeared" to work but the project never showed up.   The following is the fix! 

The following folder

C:\Program Files (x86)\MSBuild\Microsoft\Silverlight

Only has a v3.0 folder. I copy/pasted this folder and renamed the copy to v2.0 and the project would successfully appear after conversion.

 

 


Tags: ,
Categories:


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Running Crystal Reports from Silverlight

I provide a short WebCast supplementing this blog - HERENote: It appears I was having some audio difficulty in the early part of the webcast showing how to navigate to the HTML BROWSER INTEGRATION webcast - since I provide the link below I published the webcast as is.

The following www.Silverlight.net webcast HTML BROWSER INTEGRATION provides the key to running Crystal Reports from Silverlight.  Once you complete the webcast you'll find it takes only a few steps to get your Crystal Reports up and running.

I downloaded the C# Source code from the above referenced link, added the following class (MyClass) to the HtmlInteraction_CS project's Page.xaml.cs file and updated the Button1_Click() to support it:

/// <summary>

/// Added Inner class for proof of concept

/// </summary>

public class MyClass

{

    public string ReportName { get; set; }

    public int ID { get; set; }

 

    /// <summary>

    /// Override ToString so we can easily return our

    /// URL Parameters

    /// </summary>

    /// <returns></returns>

    public override string ToString()

    {

        return string.Format("?ID={0}&Name={1}", ID, ReportName);

    }

}

 

/// <summary>

///

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void Button1_Click(object sender, RoutedEventArgs e)

{

    // Instantiate class setting ReportName to textbox value

    MyClass para = new MyClass

    {

        ID = 10,

        ReportName = TextBox1.Text

    };

    // Invoke the sayGoodbye javascript method

    HtmlPage.Window.Invoke("sayGoodbye",

        new string[] {para.ToString()});

}

 

With my Silverlight code completed I only needed to prepare the Website code.  I renamed the testpage to CrystalReportPrototype.aspx and added the window.open("Report.aspx"+fname, "_blank") to the sayGoodbye(fname) javascript method as shown below:

 

So all that remained was to create my Report.aspx and reports.  I dropped a CrystalReportViewer object on the page and named it Demo1.  I then parse out the "Name" and run the applicable report, i.e., DemoReport (default), DemoReport1 and DemoReport2.

After I saw all was well I used Expression Blend to spiffy up the Silverlight screen (took all of five minutes):

 

SL-HtmlInteraction.zip (1.68 mb)  <= SOURCE CODE


Tags: , ,
Categories:


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Javascript debugging doesn't work in Visual Studio 2008 - or does it?

We need to have Crystal Reports support in Silverlight - an adventure I begin this evening...   I started with the HTML BROWSER INTEGRATION tutorial and plan to have a Silverlight event execute a javascript method to open a new window (providing the necessary parameters) for launching our Crystal Report.

The head-banging session started rather early in the game for less than obvious reasons - I couldn't get a breakpoint to work in my Javascript code - they were being ignored :O

Googling "Visual Studio 2008 Javascript" revealed some pretty cool blogs and webcast suggesting it is a plug'n play so obviously it was something on my machine???  No, so there seems to be a bug...

In all my configuration changes (Debug options as well as project) I didn't think to turn off Silverlight (arrow below) because I need to debug my Silverlight application into the Javascript call HOWEVER!  When I turned this off (unchecked it) I was now successfully debugging my Javascript code as advertised.

 

Seems like an XOR situation; I can either have Silverlight or Javascript debugging but not both....   

I submitted a bug report to Microsoft on the issue so if they are consistent I should have a response within a relatively short period of time letting me know if this is a BUG or FEATURE ;)

 


Tags: , ,
Categories: Silverlight


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

WCF / Silverlight - An error occurred ... attempting to access a service in a cross domain way

When creating a WCF Service Application for your Silverlight application you will encounter a "cross domain" error with default configurations.  

Below I show the default Service application code (only class name changed) and made the necessary Silverlight WCF configuration change for basicHttpBinding as shown by the arrow. 

I then created a Web Service reference for both my Silverlight application and Test application.  Note that Silverlight uses Async calls while the Test project uses Sync call to obtain data.

When I run the Silverlight application I get the following error:

I added the following clientaccesspolicy.xml file per THIS LINK (you can copy code from it) to my WCF Service and both my Silverlight and Unit test run without issue.

 

WCFService.zip (709.94 kb)  <= SOURCE CODE


Tags: ,
Categories: Silverlight


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Silverlight / CompositeWPF / Prism regions

Suggested reading: Martin Fowler on the PresentationModel 

Source Code available  http://www.CodePlex.com/SDMS  

CompositeWPF/Prism regions permit you to easily design a system that clearly has a Separation of Concerns.  In the figure below you see the XAML code that defines the regions for the Main Employee Manager screen:

This is particularly useful for tabs because you don't have to kludge up your TabControl with alot of controls - above you see all the XAML code required for the Information, In Work and Assigned tabs.

Below you'll see where the Module's Initialize method will register the types, resolve each presenter (instantiate it) and then apply the presenter's view to the applicable regions:


Click HERE for Video Clip Demo (Windows 7 users may have to right click then Save Target As)


The code for the Status Bar's Presenter, View and Interface is below.  Note: all of the Employee Module views share a single presentation model.  

Below is the source code for the EmployeeModule\Views\frmStatus\frmStatusPresenter.cs

using EmployeeModule.PresentationModels;

using Microsoft.Practices.Unity;

using Microsoft.Practices.Composite.Events;

using EmployeeModule.Events;

using System.Windows.Controls;

using System;

 

namespace EmployeeModule.Views.frmStatus

{

    public class frmStatusPresenter

    {

        [Dependency]

        public IEventAggregator aggregator { get; set; }

 

        /// <summary>

        /// View reference

        /// </summary>

        public IfrmStatusView View { get; set; }

 

        /// <summary>

        /// Constructor : setup class

        /// </summary>

        /// <param name="container"></param>

        /// <param name="view"></param>

        public frmStatusPresenter(IUnityContainer container,

            IfrmStatusView view, IEventAggregator aggregator)

        {

            this.View = view;

            this.aggregator = aggregator;

 

            // Provide the presentation model to the view so that

            // it can set it's DataContext to it

            view.Model =
                 container.Resolve<EmployeePresentationModel>();

 

            // Subscribe to the StatusBar event

            aggregator.GetEvent<StatusBarEvent>()

                 .Subscribe(StatusBarEventHandler, true);

 

        }

 

        public void StatusBarEventHandler(StatusBarData panel)

        {

            switch (panel.Panel)

            {

                case StatusPanel.Left:

                    View.FindControl<TextBlock>("stsLeft").Text =
                             panel.Message;

                    View.FindControl<TextBlock>("stsRight").Text =
                             string.Format("ID:{2} -- {0} {1}",

                        View.Model.SelectedEmployee.FirstName,

                        View.Model.SelectedEmployee.LastName,

                        View.Model.SelectedEmployee.EmployeeID);

                    break;

 

                case StatusPanel.Right:

                    View.FindControl<TextBlock>("stsRight").Text =
                            panel.Message;

                    break;

 

            }

        }

    }

}

 


Tags: , ,
Categories: CompositeWPF | Silverlight


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Silverlight in Expression Blend - how to get calendar control

In watching the Silverlight training video INTRODUCING BLEND TO SILVERLIGHT DEVELOPERS the big question (unanswered up to this point) is "How do you find the Calendar control?". 

Unlike the Visual Studio 2008 toolbox the following is what you'll see by default in Expression Blend:

If you click Show All you'll see the following:

The key to resolving this was to add a calendar control from Visual Studio 2008 and see how it configured it.  Upon doing this I saw the following:

<UserControl xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" 

    x:Class="SDMS.Silverlight.Page"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Height="500" Width="500" >

    <Grid x:Name="LayoutRoot" Background="White">

      <basics:Calendar></basics:Calendar>

    </Grid>

</UserControl>


I added a reference to System.Windows.Controls and was actually forced to exit Expression Blend and reenter before the reference was updated.  Up to this point I was accustomed to being prompted by VS or Blend when the other system made an updated. Updated: I found that if you add references from Visual Studio and then rebuild the solution that when you switch back to Expression Blend it will prompt you to update your project.

 

Once I re-entered expression blend and loaded my project I was greeted with the following:

The calendar and many other controls (available in the Visual Studio 2008 toolbox) now appear in Expression Blend.


Tags: ,
Categories: Silverlight


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

AG_E_PARSER_BAD_TYPE Adding Silverlight Toolkit control to module

All was going smoothly creating the infrastructure for our next solution using the CompositeWPF/Prism package until I added a Silverlight Toolkit Treeview control (all of the standard controls worked just fine).  After adding the Treeview control to the ReportView.xaml file I got the following runtime error:

It was the following link that gave light to the problem (FYI, the designer was happy):
http://silverlight.net/forums/p/12448/48559.aspx#48559 

Which suggested there are issues with inherited controls - troubleshooting this concept I added the Treeview control to my Shell.xaml (ZLCAdmin.Silverlight project) and surprisingly my problem went away; I removed my control from the shell and the solution continued to work!

In the case of the CompositeWPF/Prism infrastructure the fix was easy - simply add a reference to the Microsoft.Windows.Controls.dll in the Main project; in the case above the ZLCAdmin.Silverlight project.   

 


Tags: , , ,
Categories: CompositeWPF


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know