C# WPF DataGrid绑定MySQL日期字段转换为波斯历(Shamsi)格式的实现方案问询
Hey,我来帮你搞定这个公历转波斯历显示的问题,这里有几个实用的方案,你可以根据自己的项目情况选择:
方法1:用WPF值转换器(IValueConverter)做绑定层转换
这种方法不用改你现有的数据查询逻辑,直接在XAML绑定的时候完成转换,适合想保持原有DataSet结构的场景。
首先创建一个转换器类,实现IValueConverter接口:
using System; using System.Globalization; using System.Windows.Data; namespace YourProjectNamespace // 替换成你的项目命名空间 { public class MiladiToShamsiConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // 检查传入的是否是有效的DateTime类型 if (value is DateTime miladiDate && miladiDate != DateTime.MinValue) { // 初始化波斯历文化信息 var persianCulture = new CultureInfo("fa-IR"); // 转换为dd/MM/yyyy格式的波斯历字符串 return miladiDate.ToString("dd/MM/yyyy", persianCulture); } return string.Empty; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { // 因为你的DataGrid是只读的,反向转换不需要实现,直接抛出异常即可 throw new NotImplementedException("反向转换未实现,当前DataGrid为只读状态"); } } }
接着在XAML的资源里声明这个转换器(记得先引入命名空间):
<Window xmlns:local="clr-namespace:YourProjectNamespace" ...> <Window.Resources> <local:MiladiToShamsiConverter x:Key="MiladiToShamsiConverter" /> </Window.Resources> <!-- 你的其他XAML代码 --> </Window>
最后修改register_date列的绑定,加上转换器:
<DataGridTextColumn Binding="{Binding register_date, Converter={StaticResource MiladiToShamsiConverter}}" Header="sell date " Width="200" IsReadOnly="True" />
这样运行起来,DataGrid里就会自动显示波斯历日期了。
方法2:在MySQL查询时直接转换为波斯历字符串
如果你想在获取数据的时候就直接拿到格式化好的波斯历字符串,可以修改SQL语句,利用MySQL 8.0+自带的TO_JALALI函数(专门处理公历转波斯历)。
另外强烈建议你把原来的字符串拼接SQL改成参数化查询,避免SQL注入风险!
修改后的后台代码:
// 使用参数化查询,安全且避免注入 MySqlCommand cmd3 = new MySqlCommand("SELECT id, percent, TO_JALALI(register_date, 'dd/MM/yyyy') AS register_date FROM owner_units WHERE unit_id = @UNITID", conn); cmd3.Parameters.AddWithValue("@UNITID", UNITID); // 传入参数 MySqlDataAdapter adp2 = new MySqlDataAdapter(cmd3); DataSet ds2 = new DataSet(); adp2.Fill(ds2, "LoadDataBinding2"); owner_unit.DataContext = ds2;
这样查询出来的register_date已经是波斯历格式的字符串了,XAML里的绑定不需要做任何修改,直接显示即可。
方法3:用实体类替代DataSet(推荐,更易维护)
如果你的项目后续有扩展需求,推荐用实体类封装数据,这种方式更符合MVVM思想,也能更灵活地处理数据转换。
首先创建实体类:
public class OwnerUnit { public int id { get; set; } public decimal percent { get; set; } // 存储原始的公历日期 private DateTime _registerDateMiladi; public DateTime RegisterDateMiladi { get => _registerDateMiladi; set => _registerDateMiladi = value; } // 计算属性,返回格式化后的波斯历日期 public string RegisterDateShamsi { get { var persianCulture = new CultureInfo("fa-IR"); return _registerDateMiladi.ToString("dd/MM/yyyy", persianCulture); } } }
然后后台查询数据并转换成实体类列表:
List<OwnerUnit> ownerUnitList = new List<OwnerUnit>(); using (MySqlCommand cmd3 = new MySqlCommand("SELECT id, percent, register_date FROM owner_units WHERE unit_id = @UNITID", conn)) { cmd3.Parameters.AddWithValue("@UNITID", UNITID); using (MySqlDataReader reader = cmd3.ExecuteReader()) { while (reader.Read()) { ownerUnitList.Add(new OwnerUnit { id = reader.GetInt32("id"), percent = reader.GetDecimal("percent"), RegisterDateMiladi = reader.GetDateTime("register_date") }); } } } // 直接把实体类列表绑定到DataGrid的ItemsSource owner_unit.ItemsSource = ownerUnitList;
最后修改XAML里的绑定目标为计算属性:
<DataGridTextColumn Binding="{Binding RegisterDateShamsi}" Header="sell date " Width="200" IsReadOnly="True" />
这种方式代码结构更清晰,后续修改或扩展功能也更方便。
内容的提问来源于stack exchange,提问作者Arsalan Ahmadi
相关产品推荐
相关产品推荐

