I have a combo box that I want to bind to a list of datetime objects, but I want to show the datetime objects in short time format. I'm pretty sure I need to use some form of data template for this, but I can't figure out how to bind to the datetime object's ToShortTime method within the data template.
Can someone point me in the right direction?
Assuming you're using .NET 3.0 or 3.5 with SP1, you can simply use the StringFormat to specify the format, for example:
<TextBlock Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat='{}{0:t}'}" />
Will show the current date time with short time format ('t' standard date time format modifier, exactly the same as calling DateTime.Now.ToString("t")).
Edit: If you're already in a data template having a DateTime as the DataContext, just use:
<TextBlock Text="{Binding StringFormat='{}{0:t}'}" />
You could set the Converter property on the binding. Implement IValueConverter to make the change to a string. The MSDN docs for IValueConverter actually use this as an example.
There is a property named:
Combobox.ItemStringFormat
here you can provide the Stringformat as usual. No need to Datatemplate the items for this purpose.
<ComboBox ItemsSource="{Binding MyDates}"
ItemStringFormat="yyyy-MM-dd" />
Related
I'm using WPF to display Products on my DataGrid, for database I am using MySql database,
decimals in mysql are stored as 100.30, 100.10, 90.40, as you can see mysql is using dot(".") as separator between decimals, and to show it on my screen as comma separated, I used next thing:
<DataGridTextColumn Binding="{Binding Price, StringFormat='{}{0:C}',ConverterCulture=EN}" Header="PRICE" FontSize="15" FontFamily="Verdana" Width="10*" />
I set culture info to my DataGridTextColum where I am displaying my price, but in case someone someday would like to change that culture info how could I acces this DataGridTextColumn and change culture info for that column "Price" .. ?
Thanks guys,
Cheers
If you give the column an x:Name (like "col1") in your XAML markup you should be able to access it and its properties programmatically like this:
Binding b = col1.Binding as Binding;
string format = b.StringFormat;
var c = b.ConverterCulture;
Note that you won't be able to change any property of the binding after it has been used though so if you need to change the culture or the StringFormat you must either do this in the constructor before the binding has been resolved or by simply editing the XAML markup. It can't be done programmatically after the binding has been resolved.
I can't get my custom DateTime string format to work in my binding. I want the format to be "mmmm, yyyy" (e.g. "June, 2012").
The following does not work. I get a short date format (m/d/yyyy).
<TextBlock Text="{Binding ElementName=ThisWindow,
Path=Date,
StringFormat={}{0:MMMM\, yyyy}"/>
I've considered using a converter, but I prefer a pure XAML approach.
Edit:
For clarity, I have a Window with a dependency property Date of type DateTime. In my XAML, I've named the window 'Thiswindow'.
Edit 2:
I looked back at my actual code, and I had a Label, not a TextBlock. I changed it to TextBlock and it works fine.
<Label Content="{Binding ElementName=ThisWindow,
Path=Date,
StringFormat={}{0:MMMM\, yyyy}"/>
Anyone know why it doesn't work with Label?
Thanks.
ContentControls have a ContentStringFormat property which overrides the original formatting.
(When i saw your question i expected this to be the problem actually but was surprised to find a TextBlock at first)
Your month needs to be in uppercase:
{Binding Source={x:Static sys:DateTime.Now}, StringFormat={}{0:MMMM\, yyyy}}
EDIT:
The Label problem is probably because Label has Content, not Text.
Change the Text="{Binding ...}" to Content="{Binding ...}"
A templated control I'm working on uses a ValueConverter like so:
<ListBox>
<ListBox.Resources>
<Controls:CodeDescriptionValueConverter x:Key="CodeDescriptionValueConverter"/>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource CodeDescriptionValueConverter}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This is the default look that I supply in generic.xaml. When I use this control I'll want to pass different format strings into the converter. Is there a way to make that happen without providing the full ControlTemplate?
My first thought was that I could use ConverterParameter with a TemplateBinding to a property on the control, but I discovered that ConverterParameters can't be bound to. Another option could be to get access to the control from the ConvertTo method, then pick off that property. I'm not sure how to do that. Any options that would eliminate the need to completely re-template the control each time I use it would be helpful (it's a lot of Xaml).
In these situations, I generally do one of two things:
1) Bind to an object that has access to both the property you want to bind to the format string. In the the converter you will then have access to both the property and the format string.
2) Add properties to your data object/viewmodel/etc for the format string and the formatted text. Then bind to the formatted text properties. Assuming that you are using INotifyPropertyChanged, keep in mind that you will need to fire the propertychanged event for the formatted text property whenever you change the text or format string properties
For example, I have a simple textbox bound to a property:
<TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
The property looks something like this:
[Display(Name="Last Name")]
public string LastName { ... }
So, given the textbox, I would like to get the Display Name property from the attribute. This will be used in a composite control that includes a fieldlabel and some other niceties.
Thanks in advance.
I am not able to attempt this at the moment so this may not be accurate or even possible. As soon as I get to a computer that I can try this I will...until then, this is just theory.
I'm guessing in your composite control you'll have something like this for each data bound field:
<TextBlock Text="{Binding FirstName, Mode=OneWay}" />
<TextBox Text="{Binding FirstName, Mode=TwoWay, ...}" />
What you'll probably need to do in order to create a converter that will look at the binding data for the Display attribute, and convert the value to the attribute value instead. This would cause the above block to look like this:
<TextBlock Text="{Binding FirstName, Mode=OneWay, Converter={StaticResource AttributeConverter}, ConverterParameter=Display}" />
<TextBox Text="{Binding FirstName, Mode=TwoWay, ...}" />
Here I passed in the Display as the parameter in case you wanted to access a different attribute.
Again this is just theory since I'm not able to currently test this and cannot recall if IValueConverter.Convert(object value, ...) passes the object in question or just the string value in this case. If it's just the string value, it probably isn't possible, though if it's the object instead, it will depend on how much access you have to the reflection namespace to evaluate the attributes.
As soon as I am able to, I'll throw the scenario together and try it out.
EDIT:
For some reason the sytax highlighter is giving me the finger when I try to paste code in this edit
Anyways, after trying this out in a little project, it don't think you can do this.
Based on my suggestion of making 2 data bound controls and using a converter for the one that consumes the attribute, I did the following:
Created the xaml for the databound control.
Create the Custom Attribute for testing
Created the Model with the decorated property for testing.
Created the converter to attempt to read the attribute from the property.
Here's where I got caught up. I wasn't able to obtain the data bound type from the IValueConverter.Convert(...) method. The value parameter came through as String as did the targetType parameter. While that was the primary hangup, the second was that I was unable to dynamically identify the property name that the control was data bound to. This could be remedied through a converter parameter possibly.
Now, I WAS able to read the attribute value if I supplied the type of my test Model with the decorated property so that much is possible but I wasn't able to dynamically identify the type on the fly.
The only other way I can think of is create some form of observer or converter prior to the data truly being bound to your custom control.
Good Luck
This works great:
<my:DatePicker IsTodayHighlighted="True" Width="200">
</my:DatePicker>
But I want to format the date, something like this:
<my:DatePicker IsTodayHighlighted="True" Width="200" Format="yyyy-mm-dd">
</my:DatePicker>
Anyone know the syntax for this?
Unfortunately the DatePicker control currently does not support free DateTime formats.
If this is something you're interested in seeing up support in future version of DatePicker, please create a codeplex feature request that suggests that.
http://silverlight.codeplex.com/WorkItem/Create.aspx
Just to point out that the new Silverlight Toolkit March 2009 TimePicker & TimeUpDown controls do support a full range of globalization options. One of those include free DateTime formats. So it is just a matter of public interest on whether or not we port that ability back to DatePicker.
Have a look at the format for TimePicker #
http://silverlight.codeplex.com/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201#TimePicker
In the meanwhile, The best workaround is to either change the local culture or the format on the local culture.
public App()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("nl-NL");
or change the format on the local culture.
public App()
{
Thread.CurrentThread.CurrentCulture = (CultureInfo) Thread.CurrentThread.CurrentCulture.Clone();
Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern = "D/m/yyyy";
You should define a custom control template and edit the textbox of the datepicker control to format the text.
The Silverlight DatePicker has a SelectedDateFormat Property on it, this may be what you are looking for.
You could just hide the controls textbox (with a smaller width), expose you're own (optionally set the IsEnabled to false) and use an Element binding and Converter. If you're using MVVM, then set the DataContext to your ViewModel. I suppose another option would be to overwrite the DataTemplate to not include the text box and do the same idea.
<StackPanel Orientation="Horizontal" Height="22">
<TextBox x:Name="textBox2" Width="106" Text="{Binding ElementName=datePicker2, Path=SelectedDate, Mode=TwoWay, Converter={StaticResource internationalDateTimeFormatConverter}}" />
<controls:DatePicker x:Name="datePicker2" IsTabStop="False" SelectedDate="{Binding TargetDatePicker, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" Width="23" HorizontalAlignment="Left" />
</StackPanel>
UPDATE:
The TwoWay binding from the text box to the the date picker works well, but it doesn't update the ViewModel Property. So I'm going to set the IsEnabled=False and call it good.
I notice this is an answered question.
But I would like to notify about this link to a Silverlight 5 control toolkit I have recently started creating. It contains (among other controls) a DateTimeBox control in which you can handle both date and time within the same control. At this point, it is still under development, but it should be usable for most scenarios.