O usuário seleciona algo no ComboBox, algo mais é enviado para a propriedade de dependência
-
21-09-2019 - |
Pergunta
No meu aplicativo, o usuário pode selecionar como uma data é exibida. A maioria dos Strings de formato padrão de datetime pode ser selecionado. Meu problema agora é que o usuário médio não entende a diferença entre "M" e "D". O que eu quero fazer é Altere isso para que, como o Excel, em vez de mostrar a sequência do formato, mostro como uma data arbitrária seria usar esse formato.
O WPF ComboBox SelectedItem está vinculado a uma propriedade de dependência no CLAS do seletor de formato de data, ao qual o outro controle que contém este seletor de data também se liga.
Exemplo:
- O usuário seleciona "15 de janeiro" para que a propriedade de dependência esteja definida como "M".
- Através do código por trás, o valor da propriedade de dependência está definido como "D", o ComboBox é atualizado para exibir "Quinta -feira, 15 de janeiro de 1970" como o item selecionado.
Tentei usar conversores, mas o Convertback era impossível, pois não consigo extrair uma sequência de formato usada para criar uma determinada data.
Solução
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>