powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Работа с на c# wpf decimal
16 сообщений из 16, страница 1 из 1
Работа с на c# wpf decimal
    #39218775
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!

Подскажите пожалуйста как правильно работать с decimal. Задача стоит следующая. Мне нужно сделать чтобы пользователь мог вводит TextBox числа с плавающей точкой или запятой.
0.2121
0,213
43,
4121.
0
null

Я сделал так, но я думаю что это как-то не по фэншую.

Код: xml
1.
2.
<TextBox Grid.Column="1" Grid.Row="5" HorizontalAlignment="Left" VerticalAlignment="Top" Width="280" 
                         Text="{Binding EditItem.AreaConvert, UpdateSourceTrigger=PropertyChanged}" />


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
[Table("Land", Schema = "dbo")]
public class Land
{
     [DecimalPrecision(12, 7)]
     public decimal? Area { get; set; }

     [NotMapped]
     public string AreaConvert
     {
         get { return Area.ToString(); }
         set
         {
             try
             {
                  if (Regex.IsMatch(value, @"^\d+[\.,]?\d*$")) Area = Convert.ToDecimal(value.Replace(".", ","));
                  else if (value == string.Empty) Area = null;
             }
             catch
             {
                  Area = Convert.ToDecimal(value.Replace(",","."));
             }
         }
    }
}
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39218939
Фотография Axeleron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nechto, будь осторожен с конвертацией строки с числом с запятой или точкой в децимал - это зависит от региональных настроек компьютера.
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39218963
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AxeleronNechto, будь осторожен с конвертацией строки с числом с запятой или точкой в децимал - это зависит от региональных настроек компьютера.
Да это я учел, проверкой try catch.

Есть еще какие нибудь способы работы с decimal а то не хочется городить велосипед.
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39218964
Фотография Axeleron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NechtoДа это я учел, проверкой try catch.
Это нецелесообразно. Есть специально для этого конструкция decimal.TryParse.

NechtoЕсть еще какие нибудь способы работы с decimal а то не хочется городить велосипед.
А что конкретно интересует?
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39218984
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NechtoЗдравствуйте!

Подскажите пожалуйста как правильно работать с decimal. Задача стоит следующая. Мне нужно сделать чтобы пользователь мог вводит TextBox числа с плавающей точкой или запятой.
0.2121
0,213
43,
4121.
0
null

Я сделал так, но я думаю что это как-то не по фэншую.

Код: xml
1.
2.
<TextBox Grid.Column="1" Grid.Row="5" HorizontalAlignment="Left" VerticalAlignment="Top" Width="280" 
                         Text="{Binding EditItem.AreaConvert, UpdateSourceTrigger=PropertyChanged}" />


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
[Table("Land", Schema = "dbo")]
public class Land
{
     [DecimalPrecision(12, 7)]
     public decimal? Area { get; set; }

     [NotMapped]
     public string AreaConvert
     {
         get { return Area.ToString(); }
         set
         {
             try
             {
                  if (Regex.IsMatch(value, @"^\d+[\.,]?\d*$")) Area = Convert.ToDecimal(value.Replace(".", ","));
                  else if (value == string.Empty) Area = null;
             }
             catch
             {
                  Area = Convert.ToDecimal(value.Replace(",","."));
             }
         }
    }
}


если пользователь введет не число, но значение не будет равно "NULL", следовательно Area не изменится, что будет не очень логичным, ведь пользователь видит изменение на экране, я бы задал значению Area сразу NULL, после этого, чтоб быть явно уверенным в том, что пользователь ввёл фигню.
Во вторых ты переводишь текст в decimal не указывая культуру, если ты преобразуешь в запятые, то нужно использовать Invariant'ную культуру.
А вообще для такого существуют Конвертеры, в нём и делается подмена . на , и обратно. как угодно
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39219044
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
IValueConverter ?
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39219045
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman MejtesВо вторых
В-третьих, отсутсвует нотификация пользователя о неверно введенном значении. Здесь не нужно изобретать велосипед - есть стандартные механизмы валидации.
В-четвертых (хотя к теме топика и не относится) - налицо модель и вьюмодель в одном флаконе, что с т.з. каноничного MVVM не есть хорошо.
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39219073
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры ПавловныRoman MejtesВо вторых
В-третьих, отсутсвует нотификация пользователя о неверно введенном значении. Здесь не нужно изобретать велосипед - есть стандартные механизмы валидации.
В-четвертых (хотя к теме топика и не относится) - налицо модель и вьюмодель в одном флаконе, что с т.з. каноничного MVVM не есть хорошо.
Что то вы меня запутали. Где правильно использовать конвертор? Я так понимаю не в сущности.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
    [Table("Land", Schema = "dbo")]
    public class Land : DataErrorInfo, IValidated
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public decimal? Area { get; set; }

        [NotMapped]
        public string AreaConvert
        {
            get { return Area.ToString(); }
            set
            {
                try
                {
                    if (Regex.IsMatch(value, @"^\d+[\.,]?\d*$")) Area = Convert.ToDecimal(value.Replace(".", ","));
                    else if (value == string.Empty) Area = null;
                }
                catch
                {
                    Area = Convert.ToDecimal(value.Replace(",","."));
                }
            }
        }

        [NotMapped]
        public bool IsValidated
        {
            get { return DictDeloType != null; }
        }

        public string Error
        {
            get { return null; }
        }

        public string this[string columnName]
        {
            get 
            {
                if ((columnName == GetPropertyName(() => DictDeloType) && DictDeloType == null))
                {
                    return "Поле должно быть заполненым!!!";
                }
                return null;
            }
        }
    }
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39219150
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
реализуешь IValueConverter и используешь в Binding'е
{Binding Property1, Converter={StaticResource KeyMyConverter}}
Твой вариант вполне имеет место быть, только нужно отделить мух от котлет,

View (представление) нужно связывать не с модель данных, а с моделью представления.
То есть, модель представления получает в качестве источника какие то данные и преобразует их в нужный формат и обратно, который будет наиболее удобен для отображения и редактирования, как в твоём случаи это преобразование из Decimal в String и обратно.
Это может быть, нечто другое, данные к примеру приходят в формате Byte[] и ты их в модели представления преобразуешь в какую то пикчу или что то более сложно.
В твоём конкретном случае это же самое можно сделать через IValueConverter не во ViewModel, а во View через конверторы связывания, либо через какой то Control типа MaskEditor' который ты сам напишешь :)
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39219251
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Суть работы интерфейса IValueConverter понял работает по концепции (get set).

Осталось одно не ясно, как мне связать этот конвертер, с сущностью IDataErrorInfo.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
[NotMapped]
        public bool IsValidated
        {
            get { return DictDeloType != null; }
        }

        public string Error
        {
            get { return null; }
        }

        public string this[string columnName]
        {
            get 
            {
                if ((columnName == GetPropertyName(() => DictDeloType) && DictDeloType == null))
                {
                    return "Поле должно быть заполненым!!!";
                }
                return null;
            }
        }
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39219723
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
    [ValueConversion(typeof(decimal?), typeof(string))]
    public class DecimalConvertor : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var numberString = value as string;
            if (string.IsNullOrWhiteSpace(numberString))
            {
                return null;
            }

            decimal numeric;
            numberString = numberString.Replace(",", ".");
            var result = Decimal.TryParse(numberString, NumberStyles.Number, CultureInfo.InvariantCulture, out numeric);
            if (result)
            {
                return numeric;
            }

            return null;
        }
    }


Код: xml
1.
2.
3.
4.
5.
6.
7.
<Page.Resources>
   <convertors:DecimalConvertor x:Key="DecimalConvertor" />
</Page.Resources>

...

<TextBox Text="{Binding EditItem.Area, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DecimalConvertor}}" />



Сделал так, работает. Осталось только один косяк. К примеру, если пользователь вводит число и ставит разделитель [ 31, ], то разделитель пропадает и остается только число [ 31 ]. Разделитель можно поставить только в внутри числа [ 1561186.8 ], а это не правильно.

Как это реализовать?
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39219762
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Решил проблему, теперь и с UpdateSourceTrigger=PropertyChanged работает!

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
[ValueConversion(typeof(decimal?), typeof(string))]
    public class DecimalConvertor : IValueConverter
    {
        private static string _changeValue;  

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return DependencyProperty.UnsetValue;
            }
            if (_changeValue != null)
            {
                return Regex.IsMatch(_changeValue, @"^\d+[\.,]$") ? _changeValue : value;
            }
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var numberString = value as string;
            _changeValue = numberString;
            if (string.IsNullOrWhiteSpace(numberString))
            {
                return null;
            }

            decimal numeric;
            numberString = numberString.Replace(",", ".");
            var result = Decimal.TryParse(numberString, NumberStyles.Number, CultureInfo.InvariantCulture, out numeric);
            if (result)
            {
                return numeric;
            }
            return DependencyProperty.UnsetValue;
        }
    }
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39221714
gpu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть у меня большие сомнения что ето работает для всех языков.
Кстати а культуру в конвертере мс починил?
Она туда совсем не та приходит, как ожидается.
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39221723
gpu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На vb.net но думаю понять можно,
плюс додумать что еще надо сделать с binding (если его еще в 4.5 не починили)
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
    Public Class DecimalConverterBase
        Implements IValueConverter
#Region "Private Methods"
        Private Function ToDecimal(value As String, culture As CultureInfo) As Object
            Dim tryParseResult As Boolean = False
            Dim result As Object = Nothing
            Dim style As NumberStyles = NumberStyles.Number Or NumberStyles.AllowThousands
            Dim lret As Decimal
            tryParseResult = Decimal.TryParse(value, style, culture, lret)
            If tryParseResult Then
                result = lret
            Else
                System.Diagnostics.Debug.WriteLine(String.Format("Cannot convert,value:{0}", value))
                result = DependencyProperty.UnsetValue
            End If
            Return result
        End Function

        Private Function ToNullableDecimal(value As String, culture As CultureInfo) As Object
            Dim tryParseResult As Boolean = False
            Dim ret As Object = Nothing

            Dim style As NumberStyles = NumberStyles.Number Or NumberStyles.AllowThousands
            If String.IsNullOrEmpty(value) = False Then
                Dim lret As Decimal
                tryParseResult = Decimal.TryParse(value, style, culture, lret)
                If tryParseResult Then
                    ret = lret
                Else
                    System.Diagnostics.Debug.WriteLine(String.Format("Cannot convert,value:{0}", value))
                    ret = DependencyProperty.UnsetValue
                End If
            End If
            Return ret
        End Function
#End Region

        Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
            Dim ret As String = String.Empty
            Dim dv As Decimal = CDec((value))
            Dim frmtString As String = "N"
            If parameter IsNot Nothing Then
                If TryCast(parameter, String) IsNot Nothing Then
                    frmtString = CStr(parameter)
                End If
            End If

            ret = dv.ToString(frmtString, culture)
            Return ret
        End Function

        Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
            Dim ret As Object = Nothing
            Dim stringValue As String = CStr(value)
            If targetType.IsGenericType = False Then
                ret = ToDecimal(stringValue, culture)
            ElseIf targetType.UnderlyingSystemType.Name.StartsWith("Nullable") Then
                ret = ToNullableDecimal(stringValue, culture)
            End If
            Return ret
        End Function
    End Class
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39222991
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
gpuЕсть у меня большие сомнения что ето работает для всех языков.
Кстати а культуру в конвертере мс починил?
Она туда совсем не та приходит, как ожидается.
Все работает, без проблем.
...
Рейтинг: 0 / 0
Работа с на c# wpf decimal
    #39227764
gpu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NechtogpuЕсть у меня большие сомнения что ето работает для всех языков.
Кстати а культуру в конвертере мс починил?
Она туда совсем не та приходит, как ожидается.
Все работает, без проблем.
Меняем региональные настройки на Германию и удивляемся.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Работа с на c# wpf decimal
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]