One way to ease writing PropertyChanged events

Here’s a quick tip for those who want to write propertychanged events but dislike frameworks;

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
  if (PropertyChanged != null)
  {
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  }
}

Example;

Guid currentProfileId;
public Guid CurrentProfileId
{
  get
  {
    return this.currentProfileId;
  }
  set
  {
    if (this.currentProfileId != value)
    {
      this.currentProfileId = value;
      NotifyPropertyChanged();
    }
  }
}

Discovering what Data Item the control in your template is bound to

One issue that raises its head every now and again is how to add controls to a List’s Data Template in such a way that you can understand what data item the control is associated with when the control raises an event. E.g. I want to know what data item I should remove from a list when the user de-selects a checkbox;

<DataTemplate x:Key="MyDataClassItemTemplate">
    <StackPanel>
        <CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" 
                    Content="{Binding DisplayName}" 
                    Unchecked="CheckBox_Unchecked"
                    />
    </StackPanel>
</DataTemplate>

As you can see the checkbox has an Unchecked event but when that fires you will only be told what specific instance of the checkbox raised the event, not what the associated data item is. Previously I have worked-around this issue using the Visual Tree but I’ve always hated that solution. So I’m now using the following code that relies on the fact that my control has some form of data binding;

private MyDataClass MyDataClassFromCheckBox(object sender)
{
    FrameworkElement fe = sender as FrameworkElement;
    BindingExpression be = fe.GetBindingExpression(CheckBox.IsCheckedProperty);
    MyDataClass selectedMyDataClass = be.DataItem as MyDataClass;
    return selectedMyDataClass;
}

There, a much nicer solution. Note the ‘IsCheckedProperty’, this would need to be changed depending upon the property you are using in the binding – it is easy to pass that in as a dependancy property argument. Another quick point, previously I’ve had a similar problem using a Button in a template. However, the button only had a fixed caption so there was no binding expression to use. One simple trick here is to create a fixed property in your view model and bind to that, e.g. myViewModel.ButtonCaption { get {return “My Button Caption” }}. Yes it’s a slight overhead but you may prefer that to using the visual tree, I do.

How I think Silverlight can work on desktop & phone

I recently started to consider a new User Interface for a web application. Oh yes I want to use Silverlight but it just has zero presence on mobile devices, can I justify the speed in development/maintenance vs the lack of delivery channels. Hmm, I can try. But why should I? Windows Phone 7 (Wp7) runs Silverlight, that should certainly help me shouldn’t? But no, browse to my App on a browser on Wp7 and nothing, “no plugins here”. But why? The official line is about technical details, but I doubt that. Ok it’s not the same Silverlight but come on, it’s close enough to allow a desktop target of “restrict to Wp7 set”. So if not that then what else? Let’s imagine a world where Microsoft may pay some attention to Apple’s model. What if Microsoft can make money by only allowing apps on wp7 via a market place. Sounds like biz sense. But wait a second, if I browse to a site that has the same Silverlight app on it then why buy from the market place? Solution, stop Silverlight rendering on the browser. As I started this post, this frustrates me and stops me writing Silverlight apps for the web. But there is a way around this, “Wp7 enabled Silverlight app”. Imagine this;
1. In your Out Of Browser options you specify ‘Has Windows Phone 7 version’, and you enter the market place ID of your Wp7 application
2. You compile and deploy your Silverlight app
3. User browsers to your site via a desktop browser. They get the full experience
4. User browsers to your site from Wp7, the patched version of IE spots that the Silverlight host application has the market place id of a wp7 app. So it asks the shell’s catalogue if it has this ID, no – then prompt the user to purchase it, yes – launch the app and the user gets a specific phone experience. So there you have my idea of how we could get a shared experience, sure you’re still writing 2 apps, but now;
a) the site can have a functioning presence in a mobile browser
b) the wp7 has another selling channel, everyone’s a winner

Silverlight to resize to 100% with IE8

Had a frustrating time getting a Silverlight control to take up 100% height of the browser page. First off, this is nothing really to do with Silverlight and all about the div it’s contained in. In IE7 having the div at 100% worked fine, but in IE8 it was tiny. The problem is that in IE7 a div at 100% means, ‘please take up 100% of the available height’. Whereas in IE8 it’s, ‘please take up 100% of your parent’. So a structure like

html->body->div->div[100%]->Silverlight Control
means that in IE8 its height is basically nothing. So I added 100% to the parents up to body and still no joy. Then Hannah at Clear Breeze Design pointed out that I needed to apply it to the html tag too. That did the trick. So if you have a very simple layout you could do something like;

 html * {height 100%}

Even in my code that’s too simple but the basic take-away is that you need to follow the ancestors from the Silverlight control up until you hit a height, that’s the one it will take. If you want it to be 100% then must ensure that everyone on that chain is 100% too, including body and html.

Silverlight with ASP.NET http context gotcha

Encountered an old problem at work today. A Silverlight application which talks to an svc on the same web host wasn’t correctly sharing the same session. You could see this as the httpContext was different between the web site calling the Silverlight control and the site receiveing a request from Silverlight. It’s a simple problem; when you add a refrence to a service Visual Studio will create an endpoint in the config file, something like yourmachine.yourdomain.com. However, when you test you might just use localhost. If there is a mismatch then the session will NOT be shared. I tend to pass the endpoint address from the web site in the Silverlight initParams, I find this easier than trying to post the .host by your milage may vary. NB. This is also important when hosting on a system that uses some form of https proxy as this causes the host to look like http but you need to pass https from the client, e.g. your Silverlight control.

ASP Session Context State missing in WCF call from Silverlight

I added a new Silverlight app and corresponding WCF service to my site yesterday and I couldn’t understand why the WCF service could not see any of the details in the ASP Session Context property bag. After a bit of poking around I realised it was very simple;
The web site was using IIS at localhost/mysite but the add service reference in my Silverlight app had created a ServiceReferences.ClientConfig using an endpoint with my full machine name; machine.domain.com/mysite. The net effect is that these are treated as different web sites and therefore there is no shared cookie and thus session context. Changing the ClientConfig to localhost solved it.

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).