I've spent too long today trying to make StringFormat work on a DataGrid column bound to a DataTable column which I thought was a double. It didn't seem to matter what I used as the StringFormat, the data would always display the same. I'd forgotten to specify the DataColumn DataType and so when I assigned values to the column, they were stored a string and didn't respond to StringFormats that expected double values.
Showing posts with label Binding. Show all posts
Showing posts with label Binding. Show all posts
Monday, January 17, 2011
WPF StringFormat Problems
If you're struggling to make StringFormat on a WPF binding work consider whether or not the data type you are binding to is matches the StringFormat you are using.
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.
XAML
Source code for FindChildren (by Philipp Sumi)
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)
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.
Window.Resources
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:
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}}"
Subscribe to:
Posts (Atom)