Pull to refresh

Comments 16

И вам спасибо! Но на самом деле Markup Extension — это лишь то, что лежит на поверхности.
Если глубже изучить примеры кода, то можно обнаружить ещё несколько ценных вещей…
Классная статья, только, пожалуйста, не вздумайте публиковать приложение в таком «дизайне».

На самом деле, пример тоже стоит поправить, а то есть много людей которые выложат это без изменений.
Спасибо! Над дизайном, что называется, я сильно не заморачивался, поэтому тот, кто захочет, думаю, доработает его.
Однако если есть замечания и предложения именно по коду приложения, то я готов их выслушать и внести определённые правки, где нужно.
Недавно наткнулся на один очень странный и очень гадкий баг, в приложении некоторые WeakRefference становились не валидными при вполне живом объекте, который гарантированно был доступен из рута. Пришлось отказаться от слабых ссылок и жестко контролировать все подписки руками, что добавило головной боли на порядок. К сожалению я не смог понять почему это случается.
Хотелось бы взглянуть на пример кода. Возможно, в корневом объекте так или иначе была слабая ссылка на ваш объект, поэтому он был доступен лишь до поры до времени. Также, вполне может быть, корневой объект ссылался на точную копию вашего оригинального объекта, поэтому вы приняли их за один и тот же экземпляр, а сборщик мусора удалил оригинал, оставив лишь копию. Думаю, что второй вариант наиболее вероятный.
Это самые очевидные идеи, но увы они обе были проверены и не состоятельны. Код к сожалению уже затерян во времени.
Спасибо за интересную статью, мы в своих проектах тоже сделали такие же решения, но пришлось отказаться от многих вкусностей из за больших проблем производительности при использовании в списках.

Так, к примеру, более шустрый вариант на котором остановились это упрощенная этого же решения, т.е. в BaseViewModel
private static readonly Localization.UI LocaleUI=new Localization.UI();
public Localization.UI Locale
{
get
{
return LocaleUI;
}
}

и в UI чуть более лаконичная запись:
Text="{Binding Locale.PhonePage_Title}"

Впрочем, значительно больше проблем с производительностью дало использовании лямбда выражений для нотификаций UI. С классическим подходом скроллинг списка был ощутимо плавнее.

В целом статья очень интересная, еще раз спасибо!
Спасибо! Ваш вариант локализации тоже довольно интересный.
Плюс его в экономии ресурсов, но минус в том, что не всегда удобно им пользоваться, например, в DataTemplate

            <ListBox ItemsSource="{Binding Points}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{f:Localizing Key=СoordinateX, StringFormat={}'{0}: '}"/>
                            <TextBlock Text="{Binding X}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

То есть, чтобы ваш вариант сработал в такой ситуации нужно, чтобы данные были обязательно унаследованы от базовой вью-модели. Но это не всегда выполнимо, плюс ведёт к разрастанию класса Point.

Использование лямбда-выражений для нотификации UI во многих случаях оправдано, хоть и работает немного медленнее.
Бояться этого не стоит, прото нужно аккуратно ими пользоваться.
Понятно, что если свойство изменяется с большой частотой, то конкретно для него лучше нотификацию реализовать другим образом.

С другой стороны, такие ситуации в приложениях встречаются не столь часто.

Да и намного красивее писать что-то вроде

this[() => Name].PropertyChanged += (o, e) => { ... };

чем глобально подписываться на событие PropertyChanged и использовать if со строковой константой

PropertyChanged += (o, e) => { if (e.PropertyName == "Name") { ... } };

Подписка, как правило, выполняется только один раз, поэтому влияние лямбда-выражения на скорость здесь минимальное.
Согласен что ваш вариант намного проще сопровождать и рефакторить. Но в наших проектах этот подход давал существенные проблемы с производительностью в списках, особенно на таком железе как HTC Mozart и Lumia 610. (тесты проводились пока еще не было WP8). Надо будет проверить как сейчас все эти вкусности будут работать на самом популярном WP8 устройстве на текущий момент — Lumia 520
У вас есть девайс? Вы пальцами по кнопкам попадаете?
К сожалению, пока девайса нету, поэтому всё делаю на эмуляторе. Да, я запускал приложение у друзей и заметил, что мелковато получилось… Возможно, подправлю этот недостаток позже. По этой же причине пока что нету мультача в приложении.

Спасибо за обратную связь, если есть и другие пожелания к программе, то смело их высказывайте, постараюсь по возможности учесть.

Вообще хотелось бы в обозримом будущем добавить:
— мультитач для рисования, масштабирования и вращения
— больше кистей
— звуки при касаниях
— темы для интерфейса
— эффекты для изображений

P.S. Буду признателен за объективные отзывы в Store, поскольку, как я понял, они сильно влияют на рейтинг приложения и число загрузок :)
Теперь и на WinPhone можно писать
<TextBlock Text="{f:Localizing Key=ApplicationTitle}"/>

<...>, также обязательно указывать имя свойства Key, <...>

Не совсем так. Запись можно сократить до "{f:Localizing ApplicationTitle}", если у Localizing сделать конструктор с именем ключа:
  public Localize(string key): this()
  {
      Key = key;
  }

Это подсказывает хинт в XAML-редакторе ;)
Да уж. Не работает. Я недостаточно хорошо проверил после убирания «Key=». На самом деле студия просто не обновила XAML на девайсе.
А вот после ребилдола всё сломалось. Обидно :(
Впрочем, вы правы, что даже в таком виде это намного удобнее, чем монстр, который советуется в MSDN.
В своё время я тоже столкнуляся с этой же проблемой) Вариант с конструктором прекрасно работае в WPF и даже в дизайнере вижуал студии тоже всё проходит, но на реальном устройстве или эмуляторе — увы. Вероятно, связано с какими-то оптимизациями xaml-парсера для WP.

Но зато такой вариант локализации позволяет полностью абстрагироваться от реализации. Можно как угодно получать локализованные строки. Более того, есть возможность навесить ряд усвершенствований, например, управлять регистром вывода букв:

    public enum Cases
    {
        Default,
        Lower, 
        Upper
    }

        public string Key { get; set; }
        public Cases Case { get; set; }

        public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var key = Key;
            var resourceManager = value as ResourceManager;
            if (resourceManager == null || string.IsNullOrEmpty(key)) return ":" + key + ":";
            var localizedValue = resourceManager.GetString(key) ?? ":" + key + ":";
            switch (Case)
            {
                 case  Cases.Lower:return localizedValue.ToLower();
                 case  Cases.Upper:return localizedValue.ToUpper();
                 default:return localizedValue;
            }
        }

 Title="{m:Localizing Key=Hello, Case=Upper}" 

В общем, полезных применений расширениям разметки можно найти очень много, стоит лишь применить немного фантазии…
Sign up to leave a comment.

Articles