Saturday, 24 January 2009

How to center a listview column in Grid mode

This one I’ve really struggled with. I have a lot of listviews in the application, and basically I love listviews in WPF, but as I wrote earlier, the downside of having total control is that you must control everything…

I have some columns that I wanted to be centred. Actually, this is not very easy. I’ve used Goggle a bit, but mostly I’ve read the MSDN documentation and now after three hours of testing I’ve come up with a solution. I’m not really satisfied yet, but it will work for now.

First I thought that there would be some sort of HorizontalContentAlignment property I could set. But there isn’t any there for columns. So I started to style the column in the listview that I want to centre like this.

<Style x:Key="OnlineHeaderStyle" 
               TargetType="{x:Type GridViewColumnHeader}" 
               BasedOn="{StaticResource 
TournamentColumnHeaderStyle}"
> <Setter Property="HorizontalContentAlignment" Value="Center"/> </Style> <DataTemplate x:Key="OnlineCell"> <DockPanel> <TextBlock Foreground="DarkBlue" HorizontalAlignment="Center" TextAlignment="Center"> <TextBlock.Text> <Binding Path="Publish" Converter="{StaticResource
converterBooleanTextConverter}"
/> </TextBlock.Text> </TextBlock> </DockPanel> </DataTemplate>

This should do it I assumed, but it wasn’t enough. I also had to set a style for the ListView.ItemContainerStyle, like this:

<ListView Name="lv_Tournaments" 
   View="{StaticResource GridViewTournament}">
   <ListView.ItemContainerStyle>
     <Style TargetType="ListViewItem">
      <Setter Property="HorizontalContentAlignment" 
Value="Stretch" /> </Style> </ListView.ItemContainerStyle> </ListView>

This has to be done because the Dockpanel, or all containers for a column cell has some sort of auto size, so if the cell is 100px wide, but the text of that cell if only 20px wide, the text container will be only 20px, and the textontainer is some how aligned to the left, and even tough the content is centred, it appears as left aligned, but with the HorizontalContentAlignment of the ItemcontainerStyle set to stretch the textcontainer will have a width of 100px, and the text will appear as centred. As i wrote in the beginning, I’m not total happy with this solution, but it is good enough for now. I can get it better, and will write about it then, and I also think that Microsoft has some things to develop regarding the Listview.

Labels: ,

kick it on DotNetKicks.com

Returning an empty list and Null Continued

Ok, you live and learn. In my earlier post I wrote that I wanted to return null Lists when getting tournaments for an owner.
For example, the functions List<Tournament> GetTournamentsByOwner(Guid ownerGuid) should return NULL if no tournaments where found for that owner in the database. This is wrong, in this case.
First of all, I'm doing this project as a hobby project, and one of the reasons for doing this project is to challenge standard ways of doing things, and instead start with a new, and empty, mind set of how things should be done. I stand corrected, but I still think that in many cases it depends. It is not a given rule all the time. Obviously I have some learning to do about how, and when, I write about stuff in this blog, but I was also wrong about some things. After I read the comments, and answered to them, I continued to discuss this issue with a former colleague of mine.  And I also thought about this when I was out on the pub and have a few beers with my girlfriend and our friends.

So my conclusion is this, regarding the former post, and how I will handle it as standard way in the application, but there will be exceptions to that! When I discuss with my former colleague we usually don't settle with arguments as "it is the standard". We want to change the standard. I don't make any stakes that I change the standards, but I want to remind my self while doing this project why a standard is a standard, and how and if it can be evolved. When a function that returns a List<T>, like List<Tournament> GetTournamentsByOwner(Guid ownerGuid) and that functions doesn't have any items, it will return an empty List, not NULL! In this case I was wrong.
When a function returns an entity, like Tournament GetTournamentByGuid(Guid tournamentGuid) and that entity is not found, it will return NULL. My conclusion was that a function that returns a list, is a search function in a way. GetTournamentsBy.. actually searches for a set of tournaments, and if no tournaments are found, a search results is returned, with  zero elements. So you might see it like that function returns a search result, not a list of tournaments.

But if I call the function GetTournamentByGuid(Guid tournamentGuid) , I expect a specific tournament, and if this tournament does not exists, NULL will be returned. Some people would argue that I should return a Tournament object with empty values, but I think that is a bad idea. Because I would rather check for NULL than check for the state of the object if it is a real entity or a "placeholder". So in that perspective I rather "break" the standard of never returning NULL.

Labels: ,

kick it on DotNetKicks.com

Friday, 23 January 2009

Returning an empty list or null?

In my data access classes, which is using Linq2Sql I have functions like GetAllTournamentsByGuid().
A Tournament is a set of competitions in golf, see www.invitationaltour.com if you want to know what this project is all about.

Well, at first I wrote the test for this function, from a TDD perspective, like this;

The test is pretty straight forward, it saves two tournaments to the database with a specific owner, created earlier, then it calls the data layer and tries to get these two tournaments from the database.

[Test]
 
public void CanGetAllTournamentsByOwner()
{
  //Save two tournaments to db
  User owner = tournament.Owner;
  dataManager.SaveTournament(tournament);
  dataManager.SaveTournament(tournament2);
  
  //The actual test
  System.Collections.Generic.List<Tournament> tournaments = 
   dataManager.GetTournamentsByOwnerGuid(owner.Guid);
 
  Assert.That(tournaments.Count,Is.EqualTo(2));
  
  //Clean up is performed in the teardown routine
}

This test works well and passes when run, but what if there are no tournaments in the database, what if I want to get tournaments for a owner that does not have any tournaments? Should the function return an empty List<Tournament> or null? Or should the function return a Boolean value telling the caller if the call to the database was successful and the returning List as an output parameter or as a ref List?

I have struggled with this question for a long time during the development of various systems, and I have two ground rules, which are them self fights with each other.

1) Never throw exceptions if not needed.
Exceptions are resource intensive, compare to regular code. If you know that something can go wrong you should be able to create code that prevents that error, with validation etc. I’ve started to reconsider this rule. If the system I’m building is not that performance intensive. But I still apply this rule through out my systems.

2) Don’t return null.
Actually, I’ve adopted this rule while reading the book Clean Code by Robert C. Martin (Uncle Bob) where he writes that functions should never return NULL. Well, I’m starting to disagree.
The book states very clearly that the book is not the law, it is a book about clean code and suggestions, and there is nothing wrong with making other rules than stated in the book, so this is not a flame about the book, I love that book!

I’m rambling again….. Back to the problem

What if the function doesn’t return any tournaments? Should i return an empty List<Tournament> with a count of 0? I think I’ve decided that the return value should be NULL. The main reason for that is if this function is called via a service, a NULL value is less to serialize than an empty List of Tournaments.

What if an exception occurs? Well, I will re throw it in the function, but wrap the exception in an own exception class, which is better for serializing. This will make up the signature for the core function of gettournaments. It will be the callers responsibility to handle any exceptions.

What about returning a Boolean value indicating if the operation was successful. No problem! If I need a function that never throws an exception back to the caller I will create a wrapper function, but I will only make that function if I need it. One of the pillars in agile development is not to code functions until you need it, and it is also the third rule of TDD; only create code to pass the unit test. It also apply to the rule, from Clean Code, that a function should be responsible for one, and only one, thing!

So, to summarize:

- The functions that get entities from the repository will return null if no result aren’t found.

- The functions that get entities will throw exception if any thing goes wrong, it is the callers responsibility to handle exceptions.

- If a function is needed that doesn’t throw any exceptions, instead it should return a Boolean telling if the operation succeeded a wrapper will be created around the core getter function with an out parameter for the entity or the list of entities.

Labels: , , ,

kick it on DotNetKicks.com