Thursday, November 19, 2009

Calling a service from a silverlight application

I was working on a Silverlight application that I intended to use on my GoDaddy hosted site and having trouble with calls to my WCF service (hosted on the same GoDaddy site).

Eventually, I found the following to work:

Uri GetServiceUri(String serviceName)
{
String fullPath = HtmlPage.Document.DocumentUri.ToString();
int index = fullPath.LastIndexOf('/');
Uri uri = new Uri(fullPath.Substring(0, index + 1) +
serviceName);
return uri;
}


Service2Client CreateService2Client()
{
return new Service2Client(new BasicHttpBinding(),
new EndpointAddress(GetServiceUri("Service2.svc")));
}



Friday, October 30, 2009

WPF binding to a fast changing data source

I was using wpf data binding to display data in a real time monitoring application and found the rate at which the data source was changing resulted in a difficult to read control.

Josh Smith has a good article on ways to reduce the frequency of binding updates and the option of calling UpdateTarget on the controls binding expression was the most appropriate solution for my application. The WPF user controls that I was applying this to had a large number of controls and so I needed a way of finding the binding expressions for all the controls.

Philipp Sumi has a function (FindChildren) to find all child control of a specified type which I used to locate and subsequently update all relevant binding expressions for the control type I was using (TextBlock)

public partial class BindingSample : UserControl

    {
        List<BindingExpression> _bindingExpressions = new List<BindingExpression>();

        public BindingSample()
        {
            InitializeComponent();

            foreach (var tb in this.FindChildren<TextBlock>() )
            {
                BindingExpression be = tb.GetBindingExpression(TextBlock.TextProperty);
                if (be != null)
                    _bindingExpressions.Add(be);
            }
        }

        // Force binding update 
        // NB: Not using OneWay binding because updates are too frequent
        //     An alternative would be to use the converter UpdateThresholdConverter
        //     but this would not necessarily result in the last value being displayed when updates stop.
        public void UpdateTarget()
        {
            _bindingExpressions.ForEach(e => e.UpdateTarget());
        }
    }

XAML

            <StackPanel Style="{StaticResource DisplayLabelValue}">
                <Label Style="{StaticResource DisplayTitle}">Speed</Label>
                <TextBlock Style="{StaticResource DisplayValue}" Text="{Binding Path=Speed, Mode=OneTime, StringFormat=F1}"/>
            </StackPanel>

Source code for FindChildren (by Philipp Sumi)

Wednesday, July 22, 2009

Creating a LIB file for a DLL

I was trying to use a DLL that was supplied with a LIB file that Visual Studio 2008 refused to link to. To get around this I needed to create a new LIB file from the DLL.
Microsoft has instructions to do this (http://support.microsoft.com/kb/131313) but this wasn't working for me. In the end I found the following worked for me.

1. dumpbin /export Filename.dll (do this from a Visual Studio Command prompt)
2. Use the output of dumpbin to produce a file Filename.def (with the functions listed by dumpbin in the EXPORTS section). I found that I needed to edit to remove all leading underscores on the exported functions.
3. lib /def:filename.def
4. This will produce 2 files, filename.lib & filename.exp.
You should now be able to link to this file.

Tuesday, June 16, 2009

Entity Framework & SQL Server CE problem

The SQL Server Compact Edition throws a very unhelpful SqlCeException exception with the message:

"A parameter is missing. [ Parameter ordinal = 1 ]"

when using the entity framwork SaveChanges() method if you set a decimal property to a value with more decimal places than the database column has been configured to store.

For example, if you have a database table "header" with a Numeric 18/3 column "Height" and execute the following code, the "A parameter is missing" will be thrown.

  EntityFrameworkSQLCEEntities entities = new
EntityFrameworkSQLCEEntities();
            
  Header header = Header.CreateHeader(Guid.NewGuid(), "Test");
  header.Height = Convert.ToDecimal(3.4555);
  //header.Height = Decimal.Round(Convert.ToDecimal(3.4555), 3);
  entities.AddToHeader(header);

  entities.SaveChanges();

Rounding the decimal to the supported number of decimal places prior to setting the property "fixes" this problem but couldn't this be better handled by the Entity Framework and/or SQL Server Compact Edition?



App.Config DataDirectory macro

By default, the |DataDirectory| macro is substituted at run-time with the folder that contains the exe.  You can override this default by changing the setting the "DataDirectory" property on the app domain as follows:

   AppDomain.CurrentDomain.SetData("DataDirectory", thePath );

Friday, June 12, 2009

Installing & using SQL Server Compact Edition data files

I've been writing a program that uses the SQL Server Compact Edition for data storage.

I configure the program (via the application config file in the set-up project) to access the SQL data file (SDF file) from the programs installation folder.  This all worked without problem on my XP & Vista PCs.

However, when installed on another Vista Laptop, my application was denied access to the SDF file and was unable to run.  This turned out to be because the laptop had UAC turned on.

This page  on stackoverflow has some solutions to this problem.  The simplest of which is to change the application to a "Full Trust" application.  You can do this in Visual Studio 2008 from the application security property page. Just check the "Enable ClickOnce Security Settings" and then select "This is a full trust application".

BTW, I've tested this on Windows 7 with UAC set on its default ("Notify me when programs try to make changes to my computer").


Thursday, June 11, 2009

Formatted TimeSpan WPF Binding

The .Net TimeSpan object is displayed in a fixed format when bound to a WPF control. If you need to display a TimeSpan with a custom format you need to do this via a converter class that derives from IValueConverter.

class TimeSpanConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
TimeSpan timeSpan = (TimeSpan) value;
String result = String.Empty;
if ( timeSpan != null )
{
result = String.Format(
"{0:D2}:{1:D2}:{2:D2}:{3:D2}.{4:D1}",
timeSpan.Days, timeSpan.Hours,
timeSpan.Minutes, timeSpan.Seconds,
(int) Math.Round( timeSpan.Milliseconds/100.0));
}
return result;
}

public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}

You can create an instance of the Converter class in the Windows resources as follows:
Window.Resources
srm:TimeSpanConverter x:Key="TimeSpanConverter" /srm:TimeSpanConverter
Window.Resources

and use this converter in the binding with the following XAML

GridViewColumn Header="Duration" DisplayMemberBinding=
"{Binding Path=Duration, Converter={StaticResource TimeSpanConverter}}"


Update

I now use the following which has support for an option ConvertParameter:

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
String result = String.Empty;
if ( value is TimeSpan )
{
TimeSpan timeSpan = (TimeSpan) value;
if (timeSpan != TimeSpan.Zero)
{
if (parameter == null || !(parameter is string))
result = String.Format("{0:D2}:{1:D2}:{2:D2}:{3:D2}.{4:D1}",
timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds, (int)Math.Round(timeSpan.Milliseconds / 100.0));
else
{
DateTime time = DateTime.Today;
time = time.Add(timeSpan);
result = time.ToString((string)parameter);
}
}
}
return result;
}
XAML:
Binding="{Binding Path=Duration, ConverterParameter=H:mm:ss.f, Converter={StaticResource TimeSpanConverter}}"