Sonntag, 19. August 2012

Namespace Problems in C#

Hallo, just stumbled over two problems with namespaces in C#

First things first:

The type name 'IO' does not exist in the type 'Microsoft.Office.Interop.Word.System' when you have the following usings defined:
    using System.IO;
    using Microsoft.Office.Interop.Word;
The problem is that there exists a namespace Microsoft.Office.Interop.Word.System and Visual Studio or MSBuild somehow apply the System.*-namespaces (even they're defined before) to Micorosft.Office.Interop.Word and make it Microsoft.Office.Interop.Word.System.*

There is also a StackOverflow question about it, but unfortunately without any answer. My solution to this was more of a workaround, I named the namespace Microsoft.Office.Interop.Word.
    using System.IO;
    using word = Microsoft.Office.Interop.Word;
The downside of this workaround is that you need to use "word" in front of every type from the namespace. But at least the code compiles.

The second problem...

was a bit my fault but also not very clear in the beginning.
I have 2 Projects:
  • Common (for common functions, ExtensionMethods, ... which I may use also in the future)
  • Editor - the actual project
in Editor I had another folder "Common" which lead to the namespace Editor.Common

Now, the 1 Million $ question - how do you use in a class which has the namespace Editor.Common a class from the project and namespace Common? - The answer is simple: you can't.

And the moral of this story - don't mix your namespaces and give them names which are as unique as possible.


Happy Coding!
Peter

Sonntag, 12. August 2012

Simple Zoom for WPF Controls

Hallo again,
recently, I had to implement a zoom – in / out – functionality into a WPF application. After some research I found out that there is a RenderTransform on the Grid-Control. Here you can define a ScaleTransform which is able to scale everything in the grid by a value of type double (so 0.5 makes everything half the size, 2 makes everything double the size). One more great but probably not often needed feature is, that you can define different values for the horizontal and the vertical scale.To get an easy and quick return, just use the following XAML-Code:
<Grid x:Name="LayoutRoot">
  <Grid.RenderTransform>
    <ScaleTransform>
      <ScaleTransform.ScaleX>
        <Binding Path="ScaleFactor" ElementName="Window"/>
      </ScaleTransform.ScaleX>
      <ScaleTransform.ScaleY>
        <Binding Path="ScaleFactor" ElementName="Window"/>
      </ScaleTransform.ScaleY>
    </ScaleTransform>
  </Grid.RenderTransform>

  <Grid.RowDefinitions>
    <RowDefinition Height="66"/>
    <RowDefinition Height="*"/>
    <RowDefinition Height="30"/>
  </Grid.RowDefinitions>

  <!-- enter your controls here -->
</Grid>

As you see there is a binding to ScaleFactor, which is Dependency-Property on the Window element. Now you only have to set the ScaleFactor to change the zoom-factor, this was easy.
When you want to implement this on your main-window, which doesn’t have any scroll-bars you won’t be very. You get the zoom-functionality but when you zoom-in, you won’t see everything anymore, and when you zoom-out, there will be unused space.
I can’t help you with the unused space, because this can only be filled, when you actually have scroll bars, because your control ist too large for it’s container. So the best thing is, just ignore the zoom-out and set the minimum zoom value to 1 (100%)
But for the zoom-in, there is a very simple trick, just add 2 more RowDefinitions. Why 2? Because the RowDefinitions with static values (pixel, auto) change by a slightly other factor then the dynamic ones (star). So now, our definition should look something like this:
<Grid x:Name="LayoutRoot">
  <Grid.RenderTransform>
    <ScaleTransform>
      <ScaleTransform.ScaleX>
        <Binding Path="ScaleFactor" ElementName="Window"/>
      </ScaleTransform.ScaleX>
      <ScaleTransform.ScaleY>
        <Binding Path="ScaleFactor" ElementName="Window"/>
      </ScaleTransform.ScaleY>
    </ScaleTransform>
  </Grid.RenderTransform>

  <Grid.RowDefinitions>
    <RowDefinition Height="66"/>
    <RowDefinition Height="*"/>
    <RowDefinition Height="30"/>
    <!– zooming row definitions –>
    <RowDefinition Height="0"/>
    <RowDefinition Height="0"/>
  </Grid.RowDefinitions>
  
  <!-- enter your controls here -->
</Grid>
As you can see, I added 2 more RowDefinitions with Height=”0″ but this will change, in the code, this is the definition of the ScaleFactor and what happens, when it changes:
public double ScaleFactor
{
  get { return (double)GetValue(ScaleFactorProperty); }
  set { SetValue(ScaleFactorProperty, value); }
}

// Using a DependencyProperty as the backing store for ScaleFactor. 
// This enables animation, styling, binding, etc…
public static readonly DependencyProperty ScaleFactorProperty =
  DependencyProperty.Register("ScaleFactor", typeof(double), 
    typeof(MainWindow), new FrameworkPropertyMetadata(1.0,
      FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
      ScaleFactorPropertyChangedCallback));

private static void ScaleFactorPropertyChangedCallback(
  DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  MainWindow me = d as MainWindow;

  if (me != null)
  {
    double starSize = 0, staticSize = 0;

    for (int i = 0; i < me.LayoutRoot.RowDefinitions.Count – 2; i++)
    {
      if (me.LayoutRoot.RowDefinitions[i].Height.IsStar)
        starSize += me.LayoutRoot.RowDefinitions[i].Height.Value;
      else if (me.LayoutRoot.RowDefinitions[i].Height.IsAuto)
        staticSize += me.LayoutRoot.RowDefinitions[i].MinHeight;
      else
        staticSize += me.LayoutRoot.RowDefinitions[i].Height.Value;
    }

    me.LayoutRoot.RowDefinitions
      [me.LayoutRoot.RowDefinitions.Count - 2].Height = 
        new GridLength(staticSize * (me.ScaleFactor – 1), GridUnitType.Pixel);
    me.LayoutRoot.RowDefinitions
      [me.LayoutRoot.RowDefinitions.Count - 1].Height = 
        new GridLength(starSize * (me.ScaleFactor – 1), GridUnitType.Star);
  }
}
Now, you can see, that I dynamically sum up the dynamic and static heights of all rows.
In the end, I set the height of the row before last to “Sum(height of all RowDefinitions with a static size) * (ScaleFactor – 1)” and I do the same with the last row, just for all dynamic RowDefinitions.
But why ScaleFactor – 1 ?
The answer is easy, so I can assure, that everything else my other rows are still fully visible, how?
Because the ScaleFactor changed, everything got bigger, so for example it changed to 1,5 so now everything is 150% of the normal size. But in the window only fits 100% so I can only see 2/3 of my grid. By resizing the 2 rows to the half of the grid (1,5 – 1 = 0,5) the rest still fits into the 100% and the 2 dummy rows are hidden in an unknown space.

Happy Coding!

Spring DAO Exceptions List


Hi all,
I’m coding a global exception wrapping class, which should be automatically create a user-friendly message for every DataAccessException thrown by spring. Although I wasn’t able to find a list of all possible exceptions, so I checked out the spring-tx-<version>.jar and found following exceptions with derived exceptions and because I’m using Spring-JDBC for DatabaseConnection, I also added the Spring-JDBC-Exceptions in red.
  • DataAccessExcpeption
    • NonTransientDataAccessException
      • CleanupFailureDataAccessException
      • DataAccessResourceFailureException
        • CannotGetJdbcConnectionException
      • DataIntegrityViolationException
        • DuplicateKeyException
      • DataRetrievalFailureException
        • IncorrectResultSizeDataAccessException
          • EmptyResultDataAccessException
        • IncorrectResultSetColumnCountException
        • LobRetrievalFailureException
      • InvalidDataAccessResourceUsageException
        • IncorrectUpdateSemanticsDataAccessException
          • JdbcUpdateAffectedIncorrectNumberOfRowsException
        • TypeMismatchDataAccessException
        • BadSqlGrammarException
        • InvalidResultSetAccessException
      • InvalidDataAccessApiUsageException
      • NonTransientDataAccessResourceException
      • PermissionDeniedDataAccessException
      • UncategorizedDataAccessException
        • SQLWarningException
        • UncategorizedSQLException
    • RecoverableDataAccessException
    • TransientDataAccessException
      • ConcurrencyFailureException
        • OptimisticLockingFailureException
        • PessimisticLockingFailureException
          • CannotAcquireLockException
          • CannotSerializeTransactionException
          • DeadlockLoserDataAccessException
      • TransientDataAccessResourceException
Additionally to the DAO and JDBC Exceptions, here are the Transaction-Exceptions:


  • TransactionException
    • CannotCreateTransactionException
      • NestedTransactionNotSupportedException
      • TransactionSuspensionNotSupportedException
    • HeuristicCompletionException
    • TransactionSystemException
    • TransactionTimeOutException
    • TransactionUsageException
      • IlegalTransactionStateException
      • InvalidIsolationLevelException
      • InvalidTimeoutException
      • NoTransactionException
    • UnexpectedRollbackException

Happy Coding

How To Stop a Storyboard


I have an application with a storyboard, which turns a icon that indicates that the application is currently busy. Because I don’t have any chance to know, how long the application will be busy, the RepeatBehavior on the application is set to Forever and I have to stop it manually.
OK, seams to be easy, the storyboard has everything needed to stop it, a Pause-, Stop- and Remove-method, but somehow, nothing works. After some time I detected one line in the Output-Window of Visual Studio:
System.Windows.Media.Animation Warning: 6 :
Unable to perform action because the specified Storyboard was never applied to
this object for interactive control.; Action='Remove'; ...
After some research the answer was very easy and very Microsoft-like, when you start the storyboard with the Begin-method, there is a second parameter of type Boolean, isControllableThis has to be set to true, afterwards all the methods mentioned above will work.
Happy Coding!