none
Не получается использовать конвертор в приложении MVVM. RRS feed

  • Вопрос

  • Добрый день. Хочу использовать конвертер в приложении построенном по шаблону MVVM. Определил класс конмертера в приложении:

    using System;
    
    namespace FuturesTradingTest
    {
        [System.Windows.Data.ValueConversion(typeof(Int32), typeof(String))]
        class Int32_Converter : System.Windows.Data.IValueConverter
        {
            public Object Convert(Object value, Type tergetType, Object parameter,
                                  System.Globalization.CultureInfo culture)
            {
                Int32 intValue = (Int32)value;
                return intValue.ToString();
            }
    
            public Object ConvertBack(object value, Type targetType, object parameter,
                                      System.Globalization.CultureInfo culture)
            {
                String strValue = value as String;
                Int32 resultInt;
                if (Int32.TryParse(strValue, out resultInt))
                {
                    return resultInt;
                }
                else if (strValue == String.Empty)
                {
                    return 0;
                }
                return System.Windows.DependencyProperty.UnsetValue;
            }
        }
    }

    В представлении (глвном окне приложения) пишу:

    <Window x:Class="FuturesTradingTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:FuturesTradingTest"
            Title="{Binding Path=MainWindowTitle}" Height="350" Width="525"
            WindowState="Maximized">

    Затем, там же в разметке окна пишу:

    <Window.Resources>
         <local:Int32_Converter x:Key="Int32_ValueConverter"/>
    </Window.Resources>

    Затем, в разметке , в описании TextBox, к значениям которого хочу применять конвертер пишу:

    <!--Лимит лотов-->
    <Label Grid.Row="0" Grid.Column="1" Content="Лимит" HorizontalAlignment="Center"
                       Target="{Binding ElementName=LotsLimit_Tbx}"/>
    <TextBox x:Name="LotsLimit_Tbx" Grid.Row="1" Grid.Column="1"
                         Margin="5,0,5,10" TextAlignment="Center"
                         Text="{Binding Path=LotsLimit, Mode=OneWayToSource, 
             Converter={StaticResource ResourceKey=Int32_ValueConverter},
                        UpdateSourceTrigger=PropertyChanged}"/>

    И в результате имею в окне необработанное исключение: System.NullReferenceException. И окно, следовательно, не загружается.

    Что я делаю неправильно?

    19 августа 2013 г. 11:33

Ответы

Все ответы

  • Я вижу как минимум два места, где у вас данные могут быть null:

    Int32 intValue = (Int32)value;

    и

    String strValue = value as String;

    Правильнее писать вот так:

    public Object Convert(Object value, Type tergetType, Object parameter,
                                  System.Globalization.CultureInfo culture)
    {
          object result = null;
          if (value != null)
          {
                Int32 intValue = (Int32)value;
                result = intValue.ToString();
          }
          return result;
    }
    

    19 августа 2013 г. 11:40
    Отвечающий
  • А то что у меня привязка OneWayToSource (от приёмника к источнику) это может играть роль?


    • Изменено TownSparrow 19 августа 2013 г. 12:27
    19 августа 2013 г. 12:27
  • Нет не получается. Тот же самый результат System.NullReferenceException. C Convert сделал так как вы посоветовали и с ConvertBack сделал вот так:

    public Object ConvertBack(object value, Type targetType, object parameter,
                                      System.Globalization.CultureInfo culture)
    {
            if(value !=null)
            {
                String strValue = value as String;
                Int32 resultInt;
                if (Int32.TryParse(strValue, out resultInt))
                {
                    return resultInt;
                }
                else if (strValue == String.Empty)
                {
                    return 0;
                }
            }
            return System.Windows.DependencyProperty.UnsetValue;
    }

    Всё равно идёт упомянутое выше исключение.

    • Изменено TownSparrow 19 августа 2013 г. 13:30 Corrected
    19 августа 2013 г. 12:38
  • Если удаляете Binding все работает, возвращаете, все падает?

    19 августа 2013 г. 15:01
    Отвечающий
  • Нет, Алексей, извините, я Binding не пробовал удалять. Мне в этом месте лучше всего подходит Mode.OneWayToSource, т.к. я ввожу в текстбокс значение, которое приложение затем берёт из источника привязки (к которому привязан этот текстбокс) и использует при своей работе. Я сейчас пробовал Mode.TwoWay, с ним нормально работает, а с Mode.OneWayToSource создаёт исключение System.NullReferenceException. Но мне хочется что бы было OneWayToSource, а не TwoWay. Вот как бы заставить конвертер работать с Mode.OneWayToSource?



    • Изменено TownSparrow 20 августа 2013 г. 9:42 corrected
    20 августа 2013 г. 9:40
  • Тогда, у меня есть предположение, что ваше свойство не принимает пустое значение. Сделайте вот так:

    public Object ConvertBack(object value, Type targetType, object parameter,
                                      System.Globalization.CultureInfo culture)
    {
            if(value !=null)
            {
                String strValue = value as String;
                Int32 resultInt;
                if (Int32.TryParse(strValue, out resultInt))
                {
                    return resultInt;
                }
                else if (strValue == String.Empty)
                {
                    return 0;
                }
            }
            return 0;
    }

    Т.е. пусть у вас ноль возвращается...
    20 августа 2013 г. 15:05
    Отвечающий
  • Попробовал. Увы, тот же результат - System.NullReferenceException. Создаётся такое впечатление, что конвертор вобще не может работать, если выбран тип привязки OneWayToSource. Может быть всё-таки есть решение этого вопроса. Ребята, кто-нибудь, помогите, а?

    • Изменено TownSparrow 22 августа 2013 г. 5:21
    21 августа 2013 г. 9:22
  • Поменяйте местами условия.


    if (string.IsNullOrEmpty(strValue)) { return 0; }

    if(Int32.TryParse(strValue, out resultInt))
    {
    return resultInt;
    }


    22 августа 2013 г. 13:10
    Отвечающий
  • Антон, в вашем случае, при запуске приложения, в окне разметки создаётся исключение: XamlParseException: Задание свойства "System.Windows.Data.Binding.Converter" вызвало исключение.
    23 августа 2013 г. 7:47
  • на одну ошибку меньше :) Попробуйте запуститься в отладке и посмотреть что там не так.
    23 августа 2013 г. 8:09
    Отвечающий
  • Извините, а разве можно в XAML-разметке поставить точку останова? Ведь это исключение вылезает пряио в XAML-разметке, непосредственно под следующей её секцией:

    <Window x:Class="FuturesTradingTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:FuturesTradingTest"
            Title="{Binding Path=MainWindowTitle}" Height="350" Width="525"
            WindowState="Maximized">

    При этом приведённое выше описание "шапки" окна ограничивается такой тоненькой-тоненькой рамочкой по своему периметру, а под этой рамкой - уже окошко с исключением. 

    А! Прояснило! Можно поставить точки останова в тексте функций-членов класса конвертера.


    • Изменено TownSparrow 23 августа 2013 г. 9:13
    23 августа 2013 г. 9:12
  • Нет, ничего не выходит. Место возникновения исключения XamlParseException: Задание свойства "System.Windows.Data.Binding.Converter" вызвало исключение не могу отловить.
    • Изменено TownSparrow 23 августа 2013 г. 9:48
    23 августа 2013 г. 9:19
  • Ошибка System.NullReferenceException. означает что в объекте нет данных то есть он null или объект не инициализирован.

    пример

    // Null Reference Exceptions are for design time use and should not be caught
    string s = null;

    // this line will throw a null reference exception
    s
    = s.ToLower();

    Скорей всего вы не инициализируете объект. пусть даже примитивно это звучит

    Иных вариантов нет

    23 августа 2013 г. 10:06
  • Вставьте конвертер, который вообще ничего не конвертит, а просто возращает какое-нибудь значение. Возможно проблема не в нём. Так же проверьте, что это исключение не вызывает само поле LotsLimit, которое может оказаться не интом, без сеттера или ещё какая фигня с ним. Попробуйте сделать его нуллбл (int?) и убедиться, что это не помогло.

    Отрицательный результат тоже результат.

    26 августа 2013 г. 9:06
    Отвечающий
  • Хорошо, попробую. А LotsLimit у меня определено вот так вот:

    public Int32 LotsLimit { get; set; }

    • Изменено TownSparrow 27 августа 2013 г. 6:37
    27 августа 2013 г. 6:29
  • C Int32? тот же самый результат: исключения XamlParseException: Задание свойства "System.Windows.Data.Binding.Converter" вызвало исключение
    27 августа 2013 г. 6:47
  • Ладно. Видно ответа не дождусь. Так что пока закрываю тему.

    • Помечено в качестве ответа TownSparrow 3 сентября 2013 г. 15:24
    3 сентября 2013 г. 15:24