【问题标题】:WPF Display age from datepicker using data bindingWPF 使用数据绑定从日期选择器显示年龄
【发布时间】:2016-11-05 10:08:56
【问题描述】:

我有一个小window 和一个datepicker 和一个label。目标是显示选择出生日期的人的年龄。我为此使用了 MVVM 灯,我需要使用ViewModel.cs。我可以只使用XAML 吗?如果没有,如何解决?

我的视图模型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GalaSoft.MvvmLight;
using System.Windows.Controls;

namespace zh1_beteges
{
    public class PatientVM : ViewModelBase
    {
        Patient b = null;

        int age;
        DatePicker DP;
        public int Age
        {
            get { return age; }
            set { Set(ref age, value); }
        }
        public Patient B
        {
            get
            {
                return b;
            }
            set { Set(ref b, value); }
        }
        public PatientVM(DatePicker DP)
        {
            this.DP = DP;
        }
        public PatientVM(Patient b, DatePicker DP)
        {
            this.B = b;
            this.DP = DP;
            age = DateTime.Today.Year - b.DateOfBirth.Year;
        }


    }
}

还有我的 XAML:

<Window x:Class="zh1_beteges.BetegAdatai"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:zh1_beteges"
    mc:Ignorable="d"
    Title="BetegAdatai" Height="314.894" Width="512.766"
    WindowStartupLocation="CenterScreen"
    >
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="0.7*"/>
        <ColumnDefinition Width="0.7*"/>
    </Grid.ColumnDefinitions>
    <Label Content="Patient name:" HorizontalAlignment="Left" VerticalAlignment="Center"
           FontSize="14" Margin="10,0,10,0" Grid.Row="0" Grid.Column="0">
    </Label>
    <Label Content="PlaceOfBirth: " HorizontalAlignment="Left" VerticalAlignment="Center"
           FontSize="14" Margin="10,0,10,0" Grid.Row="1" Grid.Column="0">
    </Label>
    <Label Content="date of birth:" HorizontalAlignment="Left" VerticalAlignment="Center"
           FontSize="14" Margin="10,0,10,0" Grid.Row="2" Grid.Column="0">
    </Label>
    <Label Content="TAJ:" HorizontalAlignment="Left" VerticalAlignment="Center"
           FontSize="14" Margin="10,0,10,0" Grid.Row="3" Grid.Column="0">
    </Label>
    <Label Content="Age:" HorizontalAlignment="Left" VerticalAlignment="Center"
           FontSize="14" Margin="10,0,10,0" Grid.Row="2" Grid.Column="2">
    </Label>
    <Label Content="{Binding Path=Age}" HorizontalAlignment="Left" VerticalAlignment="Center"
           FontSize="14" Margin="10,0,10,0" Grid.Row="2" Grid.Column="3">
    </Label>
    <Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
            Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="4" Margin="170,5,170,5"
            Content="OK" FontSize="14">
    </Button>
    <DatePicker x:Name="DP" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Center"
                VerticalAlignment="Center" DisplayDateStart="2016/01/01"
                SelectedDate="{Binding Path=B.SzuletesiDatum}">
    </DatePicker>
    <TextBox Margin="10,5,10,5" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3"
             Text="{Binding Path=B.Name}" VerticalContentAlignment="Center" >
    </TextBox>
    <TextBox Margin="10,5,10,5" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3"
             Text="{Binding Path=B.PlaceOfBirth}" VerticalContentAlignment="Center" >
    </TextBox>
    <TextBox Margin="10,5,10,5" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3"
             Text="{Binding Path=B.TAJ}"  VerticalContentAlignment="Center">
    </TextBox>
</Grid>

还有我的 Xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace zh1_beteges
{
    /// <summary>
    /// Interaction logic for PatientData.xaml
    /// </summary>
    public partial class PatientData : Window
    {
        public PatientVM bvm;
        public PatientData()
        {
            InitializeComponent();
            bvm = new PatientVM(DP);
            this.DataContext = bvm;
        }
        public PatientData(Patient b)
        {
            InitializeComponent();
            bvm = new PatientVM(b,DP);
            this.DataContext = bvm;
        }
    }
}

【问题讨论】:

    标签: c# wpf xaml mvvm datepicker


    【解决方案1】:

    是的,您可以使用自定义转换器执行此操作。自定义转换器允许您将数据绑定到另一个转换为该数据或从该数据转换的值。在您的情况下,您需要一个转换器,将所选日期转换为经过该日期的时间。

    你应该像这样创建一个类:

    public class DatetimeToPassedDateConverter : IValueConverter,MarkupExtension
    {
        public object Convert(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            if(value is DateTime)
                return DateTime.Now-(DateTime)value;
            else
                return null;
        }
    
        public object ConvertBack(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            // Convert back which is not required in your case
        }
    
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }
    }
    

    然后像这样在你的 XAML 中使用它:

    <Label Content="{Binding ElementName=DP,Path=SelectedDate,Converter={namespace:DatetimeToPassedDateConverter}}" HorizontalAlignment="Left" VerticalAlignment="Center"
           FontSize="14" Margin="10,0,10,0" Grid.Row="2" Grid.Column="3">
    </Label>
    

    有关自定义转换器的更多信息,请参阅this article

    【讨论】:

    • 感谢您的提示。我创建了一个类并添加了这个标签,但是我得到了一些namespace was not found。如何将其添加到XAML 代码中?
    • 查看您的 xaml 页面的顶部。在初始部分中,您会看到一些“xmlns:xxx=yyy”。遵循相同的语法并在其中为您的类添加命名空间
    • 现在根据您链接的教程尝试。转换后的类位于我所有其他东西所在的命名空间内,并且是公共的,目前还没有运气。顺便说一句,我正在这样做:` `
    • 我们继承了 MarkupExtension 来避免这种情况。只需在 Converter={namespace:DatetimeToPassedDateConverter} 中将“命名空间”更改为“本地”
    • 而且它有效!感谢所有帮助:D
    【解决方案2】:

    您可以在PatientVM 中创建名为SelectedDate 的属性:

    private DateTime? selectedDate;
    public DateTime? SelectedDate
    {
        get
        {
            return selectedDate;
        }
        set
        {
            selectedDate = value;
            RaisePropertyChanged("SelectedDate");
            DateSelectionChangedExecute();
        }
    }
    

    然后在DateSelectionChangedExecute中计算Age(这个方法应该改进一下,比如防止负年龄):

    private void DateSelectionChangedExecute()
    {
         if (SelectedDate != null && SelectedDate.Value != null)
             Age = DateTime.Now.Year - SelectedDate.Value.Year;
    }
    

    并在 xaml 中将 SelectedDate 绑定到您的 DatePicker

    <DatePicker x:Name="DP" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Center" 
                    VerticalAlignment="Center" DisplayDateStart="2016/01/01"
                    SelectedDate="{Binding SelectedDate}">
    </DatePicker>
    

    因此,每次更改 SelectedDate 时都会计算 Age

    【讨论】:

    • 感谢您的帮助,但在@Emad 的帮助下,我可以使他的解决方案发挥作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 2022-11-27
    相关资源
    最近更新 更多