用户在组合框中选择某些内容,其他内容将发送到依赖属性

发布于 2024-08-22 04:27:57 字数 528 浏览 3 评论 0原文

在我的应用程序中,用户可以选择日期的显示方式。大多数标准日期时间格式字符串可以是已选择。我现在的问题是普通用户不理解“m”和“D”之间的区别。 我想要做的是更改此设置,以便像 Excel 那样,显示使用该格式的任意日期的外观,而不是显示格式字符串。

WPF 组合框 SelectedItem 绑定到日期格式选择器类中的依赖属性,包含此日期选择器的其他控件也绑定到该属性。

示例

  1. 用户选择“January, 15”,因此依赖属性设置为“m”。
  2. 通过后面的代码,依赖属性的值设置为“D”,组合框更新为显示“1970 年 1 月 15 日星期四”作为所选项目。

我尝试使用转换器,但 ConvertBack 是不可能的,因为我无法提取用于创建特定日期的格式字符串。

In my application the 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:

  1. The user selects "January, 15" so the dependency property is set to "m".
  2. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月竹挽风 2024-08-29 04:27:57

您可以创建一个 DateFormatChoice 类,其中包含格式代码(例如“m”或“D”)的属性以及以此方式格式化的当前日期的属性。

public class DateFormatChoice {
    public string FormatCode { get; private set; }
    public string CurrentDateExample {
        get { return DateTime.Now.ToString( FormatCode ) }
    }

    public DateFormatChoice( string standardcode ) {
        FormatCode = standardcode;
    }
}

您可以使用 DataTemplate 中的 CurrentDateExample 或作为 ComboBox 的 DisplayMemberPath 将 ComboBox 绑定到这些集合。您可以直接将这些对象与日期格式选择器类一起使用,并将 DatePicker 绑定到所选 DateFormatChoice 对象的 FormatCode 属性,或者您可以将原始 ComboBox 上的 ValueMemberPath 属性设置为 FormatCode 属性,并使用 ComboBox 上的 SelectedValue 来获取/设置所选内容。不使用 ValueMember 可能会更容易一些。


这是一个更完整的示例。它使用上面的 DateFormatChoice 类。

首先,数据收集。

public class DateFormatChoices : List<DateFormatChoice> {
    public DateFormatChoices() {
        this.Add( new DateFormatChoice( "m" ) );
        this.Add( new DateFormatChoice( "d" ) );
        this.Add( new DateFormatChoice( "D" ) );
    }
}

然后我为窗口制作了简单的 ViewModel:

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 ) );
    }
}

我没有接受标准字符串格式代码的日期选择器控件,因此我制作了一个相当愚蠢的 UserControl(有很多拐角)只是为了演示它接收格式代码。我给了它一个名为 DateFormatPropertystring 类型的依赖属性,并在 UIPropertyMetadata 中指定了一个值更改回调。

<Grid>
    <TextBlock Name="datedisplayer" />
</Grid>

回调:

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 );
    }
}

这就是我在窗口中将它们捆绑在一起的方式。

<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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文