Scrollable textblock within a ListItem (or other container)?

I do love Silverlight, but it does seem that the simplest of tasks are often the hardest to do. Today I wanted to have a nice little grid structure as my List Item data template and for one of the grids to contain a text block. There might be lot of text in there so I wanted the text block to be scrollable, sounds easy. So I thought I would just do;

<TextBlock Text="bla…" ScrollViewer.VerticalScrollBarVisibility="Visible" TextWrapping="Wrap"></TextBlock>

 

Alas that doesn’t actually create a scrollbar – looks so promising. Anyway without boring you with all the various attempts I finally settled on this;

<Grid Height="149" Width="290">

        <Grid.ColumnDefinitions>

          <ColumnDefinition Width="60"/>

          <ColumnDefinition Width="200"/>

        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0" Text="Col0"></TextBlock>

        <StackPanel Grid.Column="1">

          <TextBlock Text="Header"></TextBlock>

          <ContentControl  Height="100" >

            <ScrollViewer VerticalScrollBarVisibility="Visible">

              <TextBlock  TextWrapping="Wrap"

                     Text="Vestibulum vestibulum adipiscing parturient vestibulum vestibulum adipiscing parturient vestibulum

                     vestibulum adipiscing parturient vestibulum vestibulum adipiscing parturient vestibulum vestibulum adipiscing

                     parturient vestibulum vestibulum adipiscing parturient vestibulum vestibulum adipiscing parturient vestibulum

                     vestibulum adipiscing parturient vestibulum vestibulum adipiscing parturient vestibulum vestibulum adipiscing

                     parturient vestibulum vestibulum adipiscing parturient vestibulum xxxxxxxxxx xxxxxxxxxxxxxxxxxx xxxxxxxxxxx xxxxxxxxxx

                     yyyyyyyyyyy yyyyyyyyyyyyyyyyy yyyyyyyyyyyyyyyy yyyyyyyyyyy">

              </TextBlock>

            </ScrollViewer>

          </ContentControl>

          <TextBlock Text="Footer"></TextBlock>

        </StackPanel>       

      </Grid>

Hope it helps someone else (apart from being a bookmark for when I forget how I did it).

Nice overview of keeping images outside of the XAP

 
I didn’t release that \images\image2.jpg would get translated to Mysite\ClientBin\images\image2.jpg, good to know.
 

Getting starting with MS Ajax & WCF Service

After a fair bit of reading about live binding et al, I decided to have a play with it myself. However, I found it wasn’t that obvious how to get it going so I thought I’d better record what I had to do.

1. Download the latest version of AJAX kit in order to get hold of System.Web.Ajax.dll

2. Create a ASP Web Application Project, if you want to use my sample then call the project WebAjaxSvcTest

3. Reference Ajax dll from (1)

4. Add a new item to the project –> Add Ajax-enabled WCF Service (I left it at Service1). This should create a default method called DoWork

5. In the properties of the project change the Web setting to use local IIS Server

6. From IIS try and browser the service you created (i.e. right click on the webservce.svc file and browse). If it’s ok then skip to 8

7. WCF may not be installed on your server,you’ll need to run the configuration utility, for me that is; D:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe –r

8. Change your default aspx page to look something like;

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebAjaxSvcTest._Default" %>

<%@ Register Assembly="System.Web.Ajax" Namespace="System.Web.UI" TagPrefix="asp" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
      <script type="text/javascript" src="http://ajax.microsoft.com/ajax/beta/0911/Start.js"></script>
<script type="text/javascript">

    Sys.require([Sys.components.dataView, Sys.scripts.WebServices], function() {
        //Scripts loaded
    });
    </script>
</head>
<body xmlns:sys="javascript:Sys">
    <form id="form1" runat="server">   
    <div>

<script type="text/javascript">
    Sys.require([Sys.components.dataView, Sys.scripts.WebServices], function() {
        Sys.create.dataView("#CustomerView",
    {
        dataProvider: "/WebAjaxSvcTest/Service1.svc",
        fetchOperation: "DoWork",
        autoFetch: true,
        itemRendered: CustomerRendered
    });
        function CustomerRendered(dataView, ctx) {
            Sys.bind(Sys.get("li", ctx), "innerHTML", ctx.dataItem, "ContactName");
        }
    });

</script>

<div id="CustomerView" class="sys-template">
    <ul>
        <li />
    </ul>
</div>

    </div>
    </form>
</body>
</html>

9. Take care to change the dataprovider to be the path to your service, in my example my project (and therefore site) it called WebAjaxSvcTest and I called my Service Service1 😉

10. Hopefully you should have a demo that now runs the DoWork method and does absolutely nothing. Hopefully we now have the basic plumbing to do something interesting.

Defending Fitnesse on at least one front

I admit it, yes I’m currently using Fitnesse. It seems you have to hang your head in shame these days for admitting that. Well ok for its original purpose of Acceptance Testing I do think it is pretty limited. However, I’ve found that it has been really good for Executable Documentation. It allows the development team, as a whole, to write the specs/test in what amounts to an abstracted language. "Why not just write a unit test", I hear you cry. Well, yes I (and the rest of the developers) could, but for the rest of team that’s just not viable. Fitnesse allows the team to write almost any test they want, with the occasional bit of dev support. This has two major advantages because; more authors means more available resources for creating tests, different views of a requirement produces better conversations earlier in the process.

So there you go, while waiting for StoryTeller and evaluating Cucumber, Courgette (bad joke), Concordia, etc, you may just want to give Fitnesse another look. It really isn’t that bad.