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

Подскажите пожалуйста как правильно работать с 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
19.04.2016, 12:03
    #39218939
Axeleron
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
Nechto, будь осторожен с конвертацией строки с числом с запятой или точкой в децимал - это зависит от региональных настроек компьютера.
...
Рейтинг: 0 / 0
19.04.2016, 12:14
    #39218963
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
AxeleronNechto, будь осторожен с конвертацией строки с числом с запятой или точкой в децимал - это зависит от региональных настроек компьютера.
Да это я учел, проверкой try catch.

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

NechtoЕсть еще какие нибудь способы работы с decimal а то не хочется городить велосипед.
А что конкретно интересует?
...
Рейтинг: 0 / 0
19.04.2016, 12:29
    #39218984
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
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
19.04.2016, 13:14
    #39219044
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
IValueConverter ?
...
Рейтинг: 0 / 0
19.04.2016, 13:15
    #39219045
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
Roman MejtesВо вторых
В-третьих, отсутсвует нотификация пользователя о неверно введенном значении. Здесь не нужно изобретать велосипед - есть стандартные механизмы валидации.
В-четвертых (хотя к теме топика и не относится) - налицо модель и вьюмодель в одном флаконе, что с т.з. каноничного MVVM не есть хорошо.
...
Рейтинг: 0 / 0
19.04.2016, 13:27
    #39219073
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
Сон Веры Павловны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
19.04.2016, 14:08
    #39219150
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
реализуешь IValueConverter и используешь в Binding'е
{Binding Property1, Converter={StaticResource KeyMyConverter}}
Твой вариант вполне имеет место быть, только нужно отделить мух от котлет,

View (представление) нужно связывать не с модель данных, а с моделью представления.
То есть, модель представления получает в качестве источника какие то данные и преобразует их в нужный формат и обратно, который будет наиболее удобен для отображения и редактирования, как в твоём случаи это преобразование из Decimal в String и обратно.
Это может быть, нечто другое, данные к примеру приходят в формате Byte[] и ты их в модели представления преобразуешь в какую то пикчу или что то более сложно.
В твоём конкретном случае это же самое можно сделать через IValueConverter не во ViewModel, а во View через конверторы связывания, либо через какой то Control типа MaskEditor' который ты сам напишешь :)
...
Рейтинг: 0 / 0
19.04.2016, 14:57
    #39219251
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
Суть работы интерфейса 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
20.04.2016, 07:01
    #39219723
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
Код: 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
20.04.2016, 08:28
    #39219762
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
Решил проблему, теперь и с 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
21.04.2016, 19:07
    #39221714
gpu
gpu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
Есть у меня большие сомнения что ето работает для всех языков.
Кстати а культуру в конвертере мс починил?
Она туда совсем не та приходит, как ожидается.
...
Рейтинг: 0 / 0
21.04.2016, 19:15
    #39221723
gpu
gpu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
На 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
23.04.2016, 09:12
    #39222991
Nechto
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
gpuЕсть у меня большие сомнения что ето работает для всех языков.
Кстати а культуру в конвертере мс починил?
Она туда совсем не та приходит, как ожидается.
Все работает, без проблем.
...
Рейтинг: 0 / 0
29.04.2016, 18:53
    #39227764
gpu
gpu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с на c# wpf decimal
NechtogpuЕсть у меня большие сомнения что ето работает для всех языков.
Кстати а культуру в конвертере мс починил?
Она туда совсем не та приходит, как ожидается.
Все работает, без проблем.
Меняем региональные настройки на Германию и удивляемся.
...
Рейтинг: 0 / 0
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Работа с на c# wpf decimal / 16 сообщений из 16, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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