O usuário seleciona algo no ComboBox, algo mais é enviado para a propriedade de dependência

StackOverflow https://stackoverflow.com/questions/2287190

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:

  1. O usuário seleciona "15 de janeiro" para que a propriedade de dependência esteja definida como "M".
  2. 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.

Foi útil?

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>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top