User selects something in combobox, something else is sent to dependency property
In my application th开发者_如何学JAVAe user can select how a date is displayed. Most of the standard datetime format strings can be selected. My problem now is that the average user doesnt understand the difference between "m" and "D". What I want to do is change this so that, as excel does, rather than showing the format string, I show how an arbitrary date would look like using that format.
The WPF combobox SelectedItem is bound to a dependency property in the date format picker clas, which the other control containing this date picker also binds to.
Example:
- The user selects "January, 15" so the dependency property is set to "m".
- Through code behind, the value of the dependency property is set to "D", the combobox is updated to display "Thursday, 15 January 1970" as the selected item.
I tried using converters but ConvertBack was impossible since I cant extract a format string used to create a certain date.
You could create a class DateFormatChoice
that contains a property for the format code (e.g., "m" or "D") and a property for the current date formatted in that way.
public class DateFormatChoice {
public string FormatCode { get; private set; }
public string CurrentDateExample {
get { return DateTime.Now.ToString( FormatCode ) }
}
public DateFormatChoice( string standardcode ) {
FormatCode = standardcode;
}
}
You bind your ComboBox to a collection of these using CurrentDateExample
in either your DataTemplate
or as the ComboBox's DisplayMemberPath
. You can either use these objects directly with your date format picker class and the DatePicker
binds to the FormatCode
property of the chosen DateFormatChoice
object, or you can set the ValueMemberPath
property on the original ComboBox to the FormatCode
property and use SelectedValue
on the ComboBox for getting/setting what is chosen. Not using ValueMember
might be a little easier.
Here's a more full example. It uses the DateFormatChoice
class above.
First, a data collection.
public class DateFormatChoices : List<DateFormatChoice> {
public DateFormatChoices() {
this.Add( new DateFormatChoice( "m" ) );
this.Add( new DateFormatChoice( "d" ) );
this.Add( new DateFormatChoice( "D" ) );
}
}
Then I made simple ViewModel for the Window:
public class ViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged = ( s, e ) => {
}; // the lambda ensures PropertyChanged is never null
public DateFormatChoices Choices {
get;
private set;
}
DateFormatChoice _chosen;
public DateFormatChoice Chosen {
get {
return _chosen;
}
set {
_chosen = value;
Notify( PropertyChanged, () => Chosen );
}
}
public DateTime CurrentDateTime {
get {
return DateTime.Now;
}
}
public ViewModel() {
Choices = new DateFormatChoices();
}
// expression used to avoid string literals
private void Notify<T>( PropertyChangedEventHandler handler, Expression<Func<T>> expression ) {
var memberexpression = expression.Body as MemberExpression;
handler( this, new PropertyChangedEventArgs( memberexpression.Member.Name ) );
}
}
I didn't have a date picker control that accepted the standard string format codes, so I made a quite dumb UserControl (with many corners cut) just to demonstrate its receipt of the format code. I gave it a dependency property called DateFormatProperty
of type string
and specified a value changed callback in the UIPropertyMetadata
.
<Grid>
<TextBlock Name="datedisplayer" />
</Grid>
The callback:
private static void DateFormatChanged( DependencyObject obj, DependencyPropertyChangedEventArgs e ) {
var uc = obj as UserControl1;
string code;
if ( null != ( code = e.NewValue as string ) ) {
uc.datedisplayer.Text = DateTime.Now.ToString( code );
}
}
And this is how I tied it all together in the Window.
<StackPanel>
<StackPanel.DataContext>
<local:ViewModel />
</StackPanel.DataContext>
<ComboBox
ItemsSource="{Binding Choices}" DisplayMemberPath="CurrentDateExample"
SelectedItem="{Binding Chosen, Mode=TwoWay}"/>
<local:UserControl1
DateFormatProperty="{Binding Chosen.FormatCode}" />
</StackPanel>
精彩评论