Тэги

Silverlight (36) WPF (10) IIS (7) Visual Studio (7) SharePoint (6) .Net Framework (5) ODP.NET (5) ASP.NET (4) C# (4) common (4) Network Settings (3) JavaScript (2) MS Office (2) Resharper (2) WCF (2) WEB (2) XPath (2) XSLT (2) ADO.NET (1) APEX (1) CMD (1) CSS (1) EF (1) HTML (1) Hardware bugs (1) Java (1) MS SQL (1) Oracle (1) PDF (1) Version Control (1) XAML (1)

понедельник, 14 декабря 2009 г.

Silverlight 3: UpdateSourceTrigger PropertyChanged – реализация отсутствующего функционала



В Silverlight 3 для UpdateSourceTrigger есть только занчения Default и Explicit.
Часто необходимо получить WPF поведение – UpdateSourceTrigger . PropertyChanged

Как это решается:
В лоб:
Вешаем на TextBox обраотчик TextChanged в котором передергиваем фокус на элементе. Стандартная фишка и работает без потери позиции курсора в Silverlight.

private void MyTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    // чтоб работало вточности как при WPF UpdateSourceTrigger.PropertyChanged реагируем только если элемент под фокусом
    // Т.е. этим запретим установку фокуса при отркрытии
    if (FocusManager.GetFocusedElement() != sender)
    {
        return;
    }

    // здесь ставьте фокус на какой-то невидимый элемент или на RootVisual
    UiUtilsCommon.TrySetFocusOnRootVisual();

    var tb = sender as TextBox;

    // возвращаем фокус
    tb.Focus();
}

Как это решается по уму:
Создавайте в коде свой контрол, который наследует TextBox и подкллючите приведенный выше обработчик в конструкторе.

Для PasswordBox:
Для PasswordBox это проще решается в лоб через переопределение PasswordChanged, т.к. класс PasswordBox помечен как sealed. Можно, конечно, заморочиться на композитный контрол, но это лишнее.

private void MyPasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
    if (FocusManager.GetFocusedElement() != sender)
    {
        return;
    }    UiUtilsCommon.TrySetFocusOnRootVisual();    var thisPasswordBox = sender as PasswordBox;    thisPasswordBox.Focus();
}Проблема. Когда возникает:
У вас есть список (дерево, грид и т.д.) элементов, а также детальная область, заполняемая биндингом по выбранному элементу и позволяющая редактировать выделенный элемент.
Производим изменение только в одном поле (TextBox) и, не убирая с него фокус, сразу выбираем другой элемент в списочном элементе.
В этом случае вы потеряете изменение, а также не сможете отреагировать и выполнить какую-то вашу важную логику.
При выборе другого элемента у вас уже отображаются другие данные.
При наступлении события выбора другого элемента биндинг по TextBox еще не отработал и новое значение поля в низлежащем объекте не будет задано.

Источник:
Textbox - how to update source object without losing focus?
Там есть и другие идеи.

вторник, 8 декабря 2009 г.

AutoCompleteBox has problem with items with same name

Русский заглоловок:Проблема выбора в AutoCompleteBox объектов с одинаковым свойством.

Поблема:
при отображении в AutoCompleteBox объектов, которые имеют одинаковые поля, AutoCompleteBox всегда будет выбирать только первый найденный (всегда один и тот же) объект из всех объектов с одинанковым полем. И это не смотря на то, что в выпадающем списке (выпадающей области) мы может отобразить любые нужные поля объекта сразу или даже DataGrid и увидеть отличия объектов.

Вот сразу простое и быстрое решение:
private void someInit()
{
    completeBox.SelectionChanged += AbonentsAutoCompleteBox_SelectionChanged;
    completeBox.Populated += new PopulatedEventHandler(completeBox_Populated);
}

void completeBox_Populated(object sender, PopulatedEventArgs e)
{
    var completeBox = sender as AutoCompleteBox;
    completeBox.Tag = null;
}
private void AbonentsAutoCompleteBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    fukcAutoAutoCompleteBoxDevelopersStupidPrinciplesInSelectionChanged(sender);
}
private static void fukcAutoAutoCompleteBoxDevelopersStupidPrinciplesInSelectionChanged(object sender)
{
    var completeBox = sender as AutoCompleteBox;
    if (completeBox.Tag == null)
    {
        completeBox.Tag = completeBox.SelectedItem;
        // this is correct state.
        // you can do some work there.

    }
    else
    {
        if (completeBox.SelectedItem != completeBox.Tag)
        {
            completeBox.SelectedItem = completeBox.Tag;
        }
        else
        {
            // this is correct state.
            // you can do some work there.

        }
    }
}
Как это работает:Мы выбираем второй, или третий и т.д. элемент и он становиться выбранным, как нам и надо и попадает в SelectedItem.
Зажигается событие SelectionChanged с нашим обработчиком.
После этого, не прекращая поток выполнения, код реализации AutoCompleteBox берет строковое значение поля выбранного нами объекта и производит по нему повторый поиск. В результатах поиска он берет первый элемент и проверят, отличается ли он от текущего SelectedItem. Ну ясен перец отличается, т.к. у них только поля похожие, поэтму он заменяет выбранный пользователем SelectedItem на только что найденый элемент. Каков мерзавец! :)
Из-за этого опять зажигается событие SelectionChanged в котором мы опять задаем через SelectedItem наш прежний закэшированный в .Tag выбранный пользователем объект.
После этого событие SelectionChanged опять сработает, уже по нашей вине.
В итоге мы получаем правильный выбранный элемент.
Почему так происходит:
В исходном коде AutoCompleteBox зашили такую подлянку, а легко бы могли подправить, чтоб такого не происходило.
Я, правда, тоже, бывает, так делаю :) , но легче соглашаюсь исправить что-либо.

Приамбула:
Разработчики AutocompleteBox начхали на разарботчиков-потребителей, заявив, что надо использовать объекты, которые не предоставляют одинаковых полей. Хорошая позиция.

Исходник проблемы:
AutoCompleteBox has problem with items with same name

P.S. Натравить бы на разработчиков AutoCompleteBox парочку тестеров, чтоб они объяснили им что к чему в этой жизни.

пятница, 4 декабря 2009 г.

Silverlight: Drag & Drop или “Тупой и еще Тупее” из Silverlight Toolkit October 2009.



Ой извинииите, конечно я хотел сказать “Медленный и еще Медлееннее”.

Похоже разарботчик Drag & Drop из Silverlight Toolkit October 2009 настолько увлекся следованию стандартной схеме Drag & Drop в Windows (это хорошо), что совсем забыл про конечного пользователя.
Или может он думал, в этот момент, о скоростном удобном индийском поезде :).

Поскольку я написал свой Дарг эн Дроп, то я знаю о чем говорю.

Очень медленно, неоправданно медленно.
Даже на почти пустом элементе этот Drag & Drop появлятеся около секунды.
При этом он часто наровить появиться не там, где мышь – это просто трагедия какая-то.
На то, что он, при старте, показывает несуразное View можно закрыт глаза.

Рецепт: Используйте таки Drag & Drop из Silverlight Toolkit и ждите следующей версии.
Если ваши ресурсы позволяют, сделайт свой Drag Drop. Будет летать как молния, невзирая на количество элементов в Source и Target. К тому же легко под себя настроить любое Drag View (видим то, что перетаскиваем).
Мне это показалось совсем не сложно.

Подозреваю, что сейчас на третьем Silverlight можно ставить крест, т.к. все сообщество дышит только четвертым.
Вот, видимо, там мы и увидим приемлемое решение.

Silverlight: Сколько строк за раз отоброзит Silverlight и не повиснет или Максимальное количество элементов в списочном элемнте управления, которое не приводит к подвисанию View



Такое получилось правило:
Все что при появлении отображает от ста элементов списке должно работать с пейджером.

Ну триста строк максимум.

Нет, я делал и 3 000 и десять тысяч элеметов. Мне то нормально, но вот менеджеры проектов и заказчики очень расстраивались увиденным :)

Вы скажите “Есть виртуализация”. Да, до какой-то степени есть виртуализация :).

Главное запомните, что, наприммер в трехзвенке, самомы медленным (слабым) звеном окажется UI.
Это не только Silverlight свойственно.

Нужно учитывать какой элемент рисуется. DataGrid с большим количеством колонок будет самым медленным обычно.

А вот TreeView у которого в иерархии миллион элементов, но при открытии отображается только 300 элементов первых уровней, будет летать. Не гарантирую конечно :)

Отдельная песня про Drag & Drop из Silverlight Toolkit. Этот вообще тяжело переносит большие списки.

Резюме: пейджер всегда поможет.

Silverlight: Динамическое изменени цвета шрифта вместе с фоном в перекрестных состояниях – только два подхода



Ребята, не читайте, пожалуйтста, дальше, если вы не втеме.
Будет надо, Гугл вас сам сюда приведет.

Поехали:
То что в CSS и HTML стоит 2 копейки может превратиться в Silverlight в головную боль.

Задача: при наведении мыши изменить бэграунд и цвет шрифта.
Обычное состояние: Светлый фон и темный шрифт
Состояние при наведенной мыши или выделенного элемента: меняем на темный фон и светлый шрифт.
Теперь загвоздка – при уходе мыши, если элемент выбран, нужно сохранить состояние выделенности (Темный фон, свелый шрифт).

Конечно в HTML через CSS мы это сделаем без анимации, но просто и быстро. Мы меняем или добавляем втророй класс CSS, например, и все фиксируется и при уводе мыши состояние выделенности не меняется. Ну еще много вариантов, но не в этом соль.

Сильверлайт это всетаки не WPF, поэтму возникают сложности, т.к. в Silverllight это работает на визуальрных состояниях и переходах (транзишеннах - вроде называется).
Поскольку состояния наведения и увода мыши, а также выделения элемента находиться в разных визуальных группах, то эти состояния могут появлятся одновременно и перекрываться, что приводит к тому, что у выделенного элемнта, при уводе мыши проподает его View выделенности, т.е. возвращается светлый фон и темный шрифт, как в обычном состоянии.

Стыдно признать, что нет для такого простого и частого дизайнерского приема стандартного решения в Silverlight.
Вернее оно есть и называется “перепрограммировать чужой непродуманный элемент”. Фу.

Если вам попалась эта задачка, то вот какие решения мы нарыли с заграничными индусскими и не только товарищами:

  • В лоб – в шаблоне контрола разместить два текстовых элемента, один над другим. Один управлять из визуальных состояний мыши, другим из стостояний Selected.
    Это работае :) Производительность не страдает. Это вам не DataGrid с 1000 стороками рисоват, поэтому все хорошо, конечно если вы не стилизируете таки DataGrid с 1000 строками кода.

  • Программерское решение – управление состояниями выделенности мы оставляем неизменными, на совести XAML разметки.
    А управление сстояниями наведением мыши переносим в код. Я для этого применяю своей кастомизированный ContentControl. В нем я анализирую IsSelected и реагирую на наведение и уход мыши.


Silverlight: не используйте темы из Toolkit. Никогда.



Сначала тезисы, потом раскрою.

Темы из Silverlight Toolkit это ваш враг.
Они подойдут для обучения, подойдут как куски стилей, цветов, кистей, но не вздумайте их применять целиком.
Вы можете встретить фразу “Professional themes for your applications”
- это ложь.

Общее заключение по готовым темам Silverligt:

  • Пустой рекламный ход

  • Недоделка

  • Халтура

  • Тяп ляп

и самое главное

  • ПОДСТАВА чистой воды вас и коллег и воровство вашего времени

Почему:

  • Непреемлемые вещи, которые сделаны в этих темах не афишируются. Никто не носиться по интеренету и не кричит (кроме Гугла конечно) чего в них не так и чего они вас лишают.

  • Выкинут функционал валидации. Просто выкинули куски шаблонов в стиле вообще всех элементов :)

  • Выкинут функционал группирования в DataGrid. Тоже самое. Да да, вы настроили группы в DataGrid, а они не появятся.

  • Неизвестно чего еще не будет работать и чего выкинули

  • Я не дизайнер, но темы просто кричат своей непродуманностью и топорностью в некоторых моментах.

  • Несуразные артефакты. Вылезают неожиданные эфекты в сложных составных элемнтах, например в TreeView или в DataGrid. Хотя эти сюрпризы иногда попадаются и с шаблонах элементов по умолчанию.

  • и это не все…

Теперь вы вооружены и Silverlight опять для вас море возможностей и радости.

Кто сказал, что стили и шаблоны это сложно – это не так. Это не сложнее CSS, просто возможностей на порядок больше :)
Вооружайтесь Blend, копируйте и изменяйте шаблоны по умолчаний, вставляйте их в свою тему – вот мой рецепт.