如何同时输入 , 和 .然后将其格式化为 .用于所有文化中的 DataGridColumn?

Posted

技术标签:

【中文标题】如何同时输入 , 和 .然后将其格式化为 .用于所有文化中的 DataGridColumn?【英文标题】:How to enable typing both , and . then formatting it to . for DataGridColumn in all cultures? 【发布时间】:2017-05-18 00:44:11 【问题描述】:

无论文化如何,我都需要在可编辑的 DataGridColumn 中同时接受 ,.。输入值时,它的格式设置为使用. 作为小数分隔符。

目前我只使用:

<DataGridTextColumn Header="StaticResource XpStrSize" Binding="Binding Size" IsReadOnly="False"/> 

ViewModel 中绑定的属性 Size 是 double 类型。

所以如果用户输入 100,3 它应该在绑定属性中更新为 100.3。他也可以输入2.0,应该是2.0。此外,当用户输入 100,3 时,当焦点离开该字段时,它在列中更新为 100.3。

【问题讨论】:

您是否也接受',' 作为数字分隔符? 没有。仅适用于十进制。好点子。在我的文化中,那些不被使用 那就用string formatted = raw.Replace(',', '.'); 在哪里?我使用 MVVM,绑定属性是 double 类型。我想用 XAML 或比将绑定属性的类型更改为字符串更优雅的方式来解决这个问题。 我不确定仅在 XAML 中是否有办法做到这一点,所以如果有比我更了解该主题的人出现,也许他们可以说。否则,您可能需要编写一个自定义的BindingConverter 来进行转换。 【参考方案1】:

当您将 double(或 int)绑定到 TextBox(由 DataGridTextColumn 在编辑模式下创建)时,您会遇到限制:您对字符串的前向和后向转换的影响有限.获得更多控制权的一种解决方案是引入一个字符串类型的新属性,并将您的 double 表示为您想要的格式的字符串。您在 XAML 中绑定这个新属性并在视图模型中执行其余的魔法(前向、后向转换)。两个属性在更改时会相互更新。换句话说:XAML 的字符串、模型的双精度和视图模型连接两者:

XAML:

<DataGridTextColumn Header="StaticResource XpStrSize" Binding="Binding SizeAsString" IsReadOnly

视图模型:

private double size;

public double Size

    get
    
        return size;
    
    set
    
        size = value;
        NotifyPropertyChanged ();

        sizeAsString = FormatTheDoubleAccordingYourRequirements (size);
        NotifyPropertyChanged ("SizeAsString");
    


private string sizeAsString;

public string SizeAsString

    get
    
        return sizeAsString;
    
    set
    
        sizeAsString = value;
        Size = ParseTheStringAccordingYourRequirements (sizeAsString);
        NotifyPropertyChanged ();
    

【讨论】:

这不允许在列的文本框中写入任何内容吗? 我不确定你的问题是什么意思。使用这种方法,DataGridTextColumn“看到”了一个只能被编辑的字符串。但是你的主人是一个替身,你来回转换它。字符串为您提供所需的所有灵活性。顺便说一句,在编辑期间进行复杂的数据验证时,这样做是某种标准。 我的意思是,如果我只是绑定到双精度,我会在文本框周围出现红色边框,如果它不是合法的双精度。这不也是一个无限循环吗?无限期地从一个集合到另一个集合? 我很抱歉你是绝对正确的,这是一个无限循环。我修改了我的答案。但通常我试图展示的想法需要适应每个具体情况。是的,绑定到字符串时会丢失数据验证。不幸的是,你正处于一个全取或全取的情况。 谢谢!是的,通过简单的解决方案,我失去了数据验证。但是,这是可以肯定的。我目前正在尝试使用 double 属性和 Converter 来实现这个东西,绑定中会引发异常,我正在检查是否为该列设置 ValidatesOnExceptions=True 是否值得研究。【参考方案2】:

这应该适用于所有文化。远非完美,但满足最低要求。

所以我的“验证”只是将不正确的值(如 3.0h 或 ere)更改为 1.0

xaml:

<DataGrid.Resources>
    <cnv:DoubleToTextConverter x:Key="DoubleToTextConverter" />
    <sys:Double x:Key="DoubleOne">1.0</sys:Double>
</DataGrid.Resources>
<!-- ... -->
    <DataGridTextColumn Header="StaticResource XpStrSize" Binding="Binding Size, Converter=StaticResource DoubleToTextConverter, ConverterParameter=StaticResource DoubleOne, UpdateSourceTrigger=LostFocus" IsReadOnly="False"/>

转换器:

public class DoubleToTextConverter : IValueConverter

    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    
        return ((double) value).ToString("0.0", System.Globalization.CultureInfo.InvariantCulture);
    

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    
        double doubleValue;
        if (double.TryParse(value.ToString().Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture,
            out doubleValue))
        
            return doubleValue;
        
        if (parameter != null && parameter is double)
            return (double)parameter;

        return 0.0;
    

ViewModel 中的属性仍然是双倍的。不需要额外的字符串属性。

【讨论】:

为什么要投反对票?诚实的问题。我不知道这有什么问题。【参考方案3】:

请使用下面的代码,就可以了:

public partial class MainWindow:Window

    public MainWindow()
    
        InitializeComponent ();

        List<MyClass> myClasses=new List<MyClass> ();
        dataGrid.ItemsSource=myClasses;
    


public class MyClass

    public double Size  get; set; 


public class SizeConverter:IValueConverter

    public object Convert(object value,Type targetType,object parameter,System.Globalization.CultureInfo culture)
    
        return System.Convert.ToString (value);
    

    public object ConvertBack(object value,Type targetType,object parameter,System.Globalization.CultureInfo culture)
    
        try
        
            string size=System.Convert.ToString (value);
            string[] s=size.Split (',');
            if (s.Count ()==2)
                return System.Convert.ToDouble (s[0]+'.'+s[1]);
            else
                return System.Convert.ToDouble (value);
        
        catch (Exception e)
        
            MessageBox.Show (e.Message);
        
        return 0;
    

xaml:

<Window.Resources>
    <sc:SizeConverter x:Key="sizeConverter" />
</Window.Resources>
<Grid>
    <DataGrid Name="dataGrid" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Size" Binding="Binding Path=Size,Converter=StaticResource sizeConverter"  />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

【讨论】:

以上是关于如何同时输入 , 和 .然后将其格式化为 .用于所有文化中的 DataGridColumn?的主要内容,如果未能解决你的问题,请参考以下文章

Awk多模式匹配,并将输入文件的输出格式化为列。

如何从数据框中提取值以用于条件格式,同时一次将其应用于某些选择类别或数据条目?

将查询正确格式化为Google表格/天气公式

如何使用 yaml 格式文件在 serverless.yml 中编写嵌套 IF,同时将其用于云形成?

如何将 Double 格式化为货币 - Swift 3

如何通过 NSDate 输入对表格视图进行排序(格式化为 MMM yyyy)