Тэги

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, копируйте и изменяйте шаблоны по умолчаний, вставляйте их в свою тему – вот мой рецепт.

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

Silverlight: Общие типы / объекты между двумя WCF - сервисами побыстрому.



Задача: между двумя сервисами передавать общий объект одного класса (типа) на стороне клиента.
Т.е. Silverlight получает кастомный объект из одного сервиса, обрабатывает его и передает в другой сервис/ы.

Чтоб сделать так, вынесите общий тип в общий проект.
Этот проект должен быт Silverlight class library.
Мне даже не пришлось выкидывать конфликтующие с полным .NET Framework сборки при добавлении референса на общий Silverlight проект в проект Web-сайта.
Видимо, это будет работать пока не испольуются какие-либо сложные типы, например List<ЧтоТо>.

Оказалось в WCF задача решается, как и в обычных Web-сервисах ASP.NET – через внешнюю сборку, на которую ссылаются оба проекта - и клиент и сервис.

Но есть еще проблема с INotifyPropertyChanged.
Нельзя создать общий проект / сборку содержащую класс, наследованный от INotifyPropertyChanged, потому что этот интерфейс определен в сборке System для Silverlight, но не для полного .NET Framework.

Вот такая ошибка получается при этом:
The type 'System.ComponentModel.INotifyPropertyChanged' is defined in an assembly that is not referenced. You must add a reference to assembly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.



Для INotifyPropertyChanged я испоьзую класс-посредник, который размещен только в проекте клиента Silverlight:
public class myMediator : INotifyPropertyChanged{
private MySharedClass mySharedClass;

    public String Name{
        get{ return mySharedClass.Name; }

        set{
            mySharedClass.Name = value;
            RaisePropertyChanged(“Name”);
        }
    }

        . . . . .

}

В таком решении я получаю действительно общие типы, а не общий код, как при подходах расшаривания логиги между Silverlight и полным .NET Framework.
Хотя общий код тоже бывает полезен, но пока до этого руки не дошли.
Теперь можно часто перегенерировать сервисы без заморочек и без внешних утилит командной строки для сложных случаев.

Есть и более детальный подход на это решение, кому интересно посмотрите это Sharing Entities between WCF and Silverlight (EN).

Silverlight: В TreeView в XAML нельзя помещать вперемешку TreeViewItem и другие элементы.


Unhandled Error in Silverlight Application
Code: 1001
Category: ParserError
Message: AG_E_UNKNOWN_ERROR
File:
Line: 123
Position: 321

Если в TreeView или в TreeViewItem поместить в разметке вперемешку TreeViewItem и другие элементы, то при установке

item.IsExpanded = true;

получите выше приведенное исключение.

Обнаружено в Silverlight 3 Toolkit October 2009


четверг, 26 ноября 2009 г.

ASP.NET: Приложение сервера недоступно

Текст ошибки:

Приложение сервера недоступно

Web-приложение, к которому вы пытаетесь обратиться на этом веб-сервере, в данный момент недоступно.  Нажмите кнопку "Обновить" в своем веб-обозревателе для повтора запроса.
Замечание администратора: Сообщение об ошибке, подробно поясняющее причину сбоя данного конкретного запроса, находится в журнале событий приложений на веб-сервере. Ознакомьтесь с этой записью в журнале и выясните причину ошибки.
Одна из причин:
В папке в которой находяться файлы сайта нет прав для запуска ASP.NET.
Например для Widows XP для сайта разработки достаточно добавить на папку сайта учетку ASP.NET, но она есть только в Win XP, поэтому чтоб не запоминать, сделайте права на папку сайта такие же, как в папке сайтов IIS по умолчанию.
Это C:\Inetpub\wwwroot.
Даже если ваша папка сайта (приложения) лежит в C:\Inetpub\wwwroot, то всеравно проверте на ней права, тк они могут отстутствовать, например из-за выгрузки папки сайта целиком из SVN.
Характерная черта этой ошибки, что в логах сервера IIS (обычно C:\WINDOWS\system32\Logfiles\W3SVC1) вы получаете что-то типа
11:22:11 127.0.0.1 GET /WebSite1/Default.aspx 500
и при этом, при дебаггинге сайта в Visual Studio не попадаете на обработчик события Application_Error, который по умолчанию определен в файле Global.asax

среда, 25 ноября 2009 г.

Linq: Метод var res = (Linq Expression).ToDictionary(p => p.ID) неработает с анонимными типами полученными в select выражения Linq.

Вот это работать будет

var res = (from item in SomeList
    select new SomeClass()
        {
            ID = item.Id,
        }
).ToDictionary<SomeClass, Int64>(p => p.ID);
А вот это нет
var res = (from item in SomeList
    select new
        {
            ID = item.Id,
        }
).ToDictionary(p => p.ID);

Чтоб это обойти нужно просто исопльзовать ToDictionary, принимающий два делегата Func, а не однин.
Например:
var res = (from item in SomeList
    select new
        {
            ID = item.Id,
        }
).ToDictionary(p => p.ID, p=>p);

Первый делегат вернет ключь, второй значение для словаря.

Silverlight: Улучшенный TreeView с CheckBox. Добавил детальное представление и фильтрацию элементов для детального представления - TreeView Using CheckBoxes improvement



Есть в Silverlight Toolkit пример Using CheckBoxes in a TreeView – Использование чекбоксов в дереве. Я его срочно доработал :).

Посмотреть готовый припер вы можете сразу по этой ссылке Check Hierarhy Perfect

Скачать проект здесь.

В Silverlight есть TreeView в котором вставлены CheckBox. Изменение этих CheckBox связано как вверх по иерархии, так и вниз.
Как это работает в Toolkit можно посмотреть здесь (внимание, долго грузиться, тк сразу все примеры из Toolkit).
Я чуть-чуть доработал это приер и вот что мне удалось туда добавить

  • работа с детальным представление и чтоб в изменения в детальном представлении изменяли отображение самого TreeView

  • Избавиться от обработчика события клика по элементу дерева

  • Дабавил возможность разделения элементов между деревом и детальным представлением. Например у структуре организации у вас есть подразделения и сотрудники и вы хотите в дереве отобаржать только подразделения, а в детальном DataGrid или другом TreeView сотрудников. Ну по псякому может быть.

  • Я делал сразу, чтоб в отличии от Silverlight Toolkit у меня поддерживался Drag & Drop, но тестировать это нет никакого времени, извините

  • Также, в отличии от Toolkit, поддерживается динамическое изменение всех трех коллекций в коде.

  • Все три коллекции синхронизированы


от 27.09.2009

  • Убрал дурацкое промежуточное состояние Null на родительском чекбоксе при клике. Это когда в примере на Silverlight Toolkit кликаем по родительскому чекбоксу, а он вместо перехода с Checked на Unchecked переходит в промежуточное третье состояние, когда свойство (Boolean?) IsChecked = null. Это так раздражает :)

  • По просьбе коллег по умолчанию сделал все чекбоксы выделенными (IsChecked = true). Вы можете это сами переопределить для себя в классе установив
    private Boolean? _isCheckedFild_ = false; или private Boolean? _isCheckedFild_ = null; вместо private Boolean? _isCheckedFild_ = true;


Три коллекции, это где все элементы, где помеченные элементы и где не помеченные элементы. Например в моем приммере, в верхней части все элементы а в нижней в дереве помеченные (группы), а в детальном представлении в DataGrid не помеченные (сотрудники). Ну тут возможны вариации.

Все это работает на одном абстрактном классе CheckHierarhy, который вы должны наследовать для добавления ваших полей.
Пока я не прекрутил это к данным с Web-сервера, так что могут быть изменения.

Все я погнал дальше работать, мне уже не до этого :).

вторник, 24 ноября 2009 г.

WPF: DataGrid в WPF не поддерживает полноценной работы с валидацией, в отличии от Silverlight DataGrid



На данный момент я не нашел способа программно в UI (!!! а не в бизнес объектах) определить, валидны ли строки или ячейки в DataGrid WPF.

Стандартные уловки с LogicalTreeHelper.GetChildren(...) и Validation.GetHasError(...) на теперешнем июльском 2009 DataGrid не работают.

А вот разработчики Silverlight Toolkit такого промоха не допустили.

Вот и пригодился мой подход с самопальными Validation Groups как у ASP.NET, который я притянул в WPF и о котором писал ранее.

Так что, не все так хорошо в датском королевстве :)

Но ждем лучшего, т.к. .NET Framework 4 не загорами.

вторник, 17 ноября 2009 г.

Microsoft Web Platform Installer 2.0 у меня как-то криво ставит Silverlight 3



Unable to start debugging. The Silverlight managed debugging package isn't installed

Попробуйте переустановить Microsoft® Silverlight™ 3 Tools for Visual Studio 2008 SP1, только не используйте для этого
Web Platform Installer 2.0.
И еще, хоть Microsoft® Silverlight™ 3 Tools for Visual Studio 2008 SP1 и не поддерживает Widows Server 2003, но всеравно там работает.

У этой проблемы есть и более стандартный ответ, но с ним вам поможет Google.com, который вам скажет, что у вас не установлен Silverlight Developer Runtime. Это одна из частей, как раз вхдящая в Silverlight™ 3 Tools for Visual Studio 2008 SP1.

Вообще  корень проблемы в том, что Microsoft Web Platform Installer 2.0 у меня ставит как-то криво, что даже Silverlight на работает.

пятница, 13 ноября 2009 г.

Silverlight: DataGrid – динамическое добавление колонок в DataGrid с динамическими инменами колонок, с поддержкой DataPager. Должно сработать и для WPF.



Silverlight: DataGrid – динамическое добавление колонок в DataGrid с динамическими инменами колонок, с поддержкой DataPager.
Должно сработать и для WPF (возможно при доработке), но для WPF, видимо, лучше использовать в качестве низлежащего объекта данных DataTabel.
В Silverlight класс DataTabel не существует.

Главное условие – сейчас поддерживается максимально до 20 колонок, но это количество не ограничено, просто фиксированно в коде. Правте код сами, кому надо.

Решение удобно использовать для отображения отчетов с неизвестными именами колонок и неизвестным количеством колонок и неизвестным типом данных. Т.к. это для отчетов, то изменения данных не подразумеваются.

Решению всеравно, что вы используете, List<> или ObservableCollection<>.

Типы данных которые не поддерживаются добавте сами, это просто сделать по аналогии с имеющимся в проекте коде.
Сейчас поддерживаются String, Int32, Decimal, Double, DateTime.

За целостность данных вы отвечаете сами. Я имел ввиду, что нет проверки как в DataTabel, что вы добавляете верный тип данных. Т.е. если вы начили в первую колонку добавлять число, то должны добавлять число в остальные колонки.
Правда можете добавлять null, только не забывайте даже null обарачивать в специальный объект.

Project DataGrid Dynamic Columns for Visual Studio 2008 Silverlight 3
Возможно вам потребуется установить Silverlight Toolkit для DataGrid и DataPager, чтоб проект собирался.

Если будут желающие я объясню, что там делается.

___

Доработки 26.11.2009
По просьбе трудящихся добавил свойство для детальной информации, которое отдельно можно отрисоваться в детальной части строки DataGrid. Свойство не типизировано.

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

Silverlight 3: задание Foreground на строке DataGrid не приводить к изменению цвета



Поэтому надо задавать в контенте, например на TextBox.

Как кастомизировать DataGrid через код есть в сети, но если что - напишу.

четверг, 5 ноября 2009 г.

Внимание! Добавление элементов в XAML Resource Dictionary из того же проекта, где расположен сам файл ресурсов



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

Обратите внимание, что автоматически подставляемая XML ссылка на namespace в вашем проекте получается без указания на сборку текущего проекта. Это обычное явление. Вот что вы получите при добавлении XML-референса в файл темы

xmlns:customControls="clr-namespace:MyProject.CustomControls"

А виноват в том, что рвется недоработанный ImplicitStyleManager. Он не переваривает XML-референсы без указания на сборку. Вот такой он :)
themingToolkit:ImplicitStyleManager.ResourceDictionaryUri="Themes/Generic.xaml"

Лечиться это легко, в вашем xmlns: добавте assembly=MyProjectAssemblyName
В результате вы получите:

xmlns:customControls="clr-namespace:MyProject.CustomControls; assembly=MyProjectAssemblyName"

Вуаля, работайте дальше.

Для поисковиков приведу возникающие при этом ошибки

Ошибка: Unhandled Error in Silverlight Application
Code: 2255
Category: RuntimeError
Message: AG_E_PARSER_BAD_TYPE
MethodName:

Unhandled Error in Silverlight Application AG_E_PARSER_BAD_TYPE [Line: 46 Position: 81]

Ну как-то так :)
Я про это как-то видел на форумах (EN), но тогда не обратил внимание на стонания бедного индуса :)

среда, 4 ноября 2009 г.

Типизированные DataSet - труд коту под хвост. С ADO.NET EntityFramework веселее, но она не поддерживает хранимые процедуры (сейчас)

Очередной раз сижу и злюсь на себя, что связался с типизированными DataSet!
С ними только на собеседованиях пыль в глаза пускать.
Только ADO.NET, чистый ADO.NET и ничего большего в серьезном проекте! Прям как в книгах заговорил :) .
У меня немного поменялась схема в базе данных и какие-то типизированные датасеты слетели полностью, какие-то вылетают в рунтайме из-за того, что поле ID не может быть NULL, и т.д. и т.п., и т.д. и т.п.
Как это достало! Вот, в одном проекте сделал все на ADO.NET и ADO.NET Entity Framework немного, так мило дело теперь маштабировать (изменять, дорабатывать, наращивать) при случае.
Теперь сижу и сверяю настройки датасетов из старой версии проекта который поднял из системы контроля версий.
ADO.NET Entity Framework конечно поприятнее, но по сути это работа над ошибками в DataSet’s, а еще эта сладость не поддерживает импорт хранимых процедур в код приложения. Разработчики говорят, что им не хватило времени на это. Можно только импортить как Select, Update, Insert замены обычным запросам.
Конечно можно изловчиться и заставить сымпортить хранимки, но жизнь у нас одна и не стоит ее тратить на незрелые продукты. Есть еще, правда, ADO.NET Entity Framework Extensions, но я всетаки дождусь релиза.
Вон как поносят эту недороботку Entity Framework:
Google: entity framework function import scalar (EN)
import a function that returns a scalar value (EN)
Entity Framework Problems: Mapping stored procedures to non-insert,update,delete (EN)
P.S. Таки настроил свои датасеты и уже забыл про все негативное, что про них написал здесь :)

воскресенье, 1 ноября 2009 г.

Версионность на уровне базы начиная с MS SQL 2008 в релизе Enterprise

Коллеги, в MS SQL 2008, в самом дорогом релизе Enterprise есть версионность на уровне базы данных.
Она поддерживает администрирование, авто-удаление и другие полезные фичи.
Т.к. версионность доступна только с редакции Enterprice, то можно сказать, что никакой версионности в MS SQL 2008 нет :), но все-таки.
Система отслеживания измененных данныхСистема отслеживания измененных данных регистрирует действия по вставке, обновлению и удалению, применяемые к таблицам SQL Server, сохраняя подробности операций изменения в легко обрабатываемом реляционном формате. Таблицы изменений, используемые системой отслеживания измененных данных, содержат столбцы, отражающие структуру столбцов отслеживаемой исходной таблицы, а также метаданные, необходимые для понимания того, какие изменения произошли.

Система отслеживания изменений в данных доступна только в следующих выпусках: Enterprise, Developer и Evaluation SQL Server.
Работает это все прозрачно и асинхронно не внося изменения в схему базы данных.
Легко настраивается, легко включается.
Напоминаю, что Enterprice стоит денег :). Не помню точно, но вроде что-то от 50 до 250 тысяч баксов, т.е. от полтора миллиона рублей до семи.
Почитать про такое же решение от Oracle можно здесь Managing History (EN)

суббота, 31 октября 2009 г.

Дополнение к предыдущему посту “Темы в Silverlight Toolkit October убивают валидацию в TextBox. Т.е. валидационный View. Видимо так было раньше и пока так будет, но это несложно поправить.”.



Предыдущий пост: Темы в Silverlight Toolkit October убивают валидацию в TextBox. Т.е. валидационный View. Видимо так было раньше и пока так будет, но это несложно поправить.

Продолжение предыдущего поста:

А вот безобразие, которое было до этого:
___________
<!--Textbox-->
<Style TargetType="TextBox">
    <Setter Property="BorderThickness"
        Value="1"/>
    <Setter Property="Background"
        Value="{StaticResource ShadeBrush}"/>
    <Setter Property="Foreground"
        Value="#FF000000"/>
    <Setter Property="Padding"
        Value="2"/>
    <Setter Property="BorderBrush"
        Value="{StaticResource NormalBorderBrush}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid >
                    <vsm:VisualStateManager.VisualStateGroups>
                        <vsm:VisualStateGroup x:Name="CommonStates">
                            <vsm:VisualStateGroup.Transitions>
                                <vsm:VisualTransition GeneratedDuration="00:00:00.1"
                                    To="MouseOver"/>
                                <vsm:VisualTransition GeneratedDuration="00:00:00.1"
                                    To="ReadOnly"/>
                                <vsm:VisualTransition GeneratedDuration="00:00:00.1"
                                    To="Disabled"/>
                                <vsm:VisualTransition From="Normal"
                                    GeneratedDuration="00:00:00.3000000"
                                    To="MouseOver"/>
                                <vsm:VisualTransition From="MouseOver"
                                    GeneratedDuration="00:00:00.5000000"
                                    To="Normal"/>
                            </vsm:VisualStateGroup.Transitions>
                            <vsm:VisualState x:Name="Normal"/>
                            <vsm:VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                               Duration="00:00:00.0010000"
                                               Storyboard.TargetName="HoverBorder"
                                               Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <SplineDoubleKeyFrame KeyTime="00:00:00"
                                        Value="1"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="Disabled">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="DisabledVisualElement"
                                               Storyboard.TargetProperty="Opacity">
                                        <SplineDoubleKeyFrame KeyTime="0"
                                        Value="0.6"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="ReadOnly">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ReadOnlyVisualElement"
                                               Storyboard.TargetProperty="Opacity">
                                        <SplineDoubleKeyFrame KeyTime="0"
                                        Value="1"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                        </vsm:VisualStateGroup>
                        <vsm:VisualStateGroup x:Name="FocusStates">
                            <vsm:VisualStateGroup.Transitions>
                                <vsm:VisualTransition From="Focused"
                                    GeneratedDuration="00:00:00.5000000"
                                    To="Unfocused"/>
                                <vsm:VisualTransition From="Unfocused"
                                    GeneratedDuration="00:00:00.3000000"
                                    To="Focused"/>
                            </vsm:VisualStateGroup.Transitions>
                            <vsm:VisualState x:Name="Focused">
                                <Storyboard>


                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                               Duration="00:00:00.0010000"
                                               Storyboard.TargetName="FocusVisualElement"
                                               Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <SplineDoubleKeyFrame KeyTime="00:00:00"
                                        Value="1"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="Unfocused">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                               Duration="00:00:00.0010000"
                                               Storyboard.TargetName="FocusVisualElement"
                                               Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <SplineDoubleKeyFrame KeyTime="00:00:00"
                                        Value="0"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                        </vsm:VisualStateGroup>
                    </vsm:VisualStateManager.VisualStateGroups>
                    <Border x:Name="Border"
                Opacity="1"
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                CornerRadius="2,2,2,2">
                        <Grid>
                            <Border x:Name="ReadOnlyVisualElement"
                    Opacity="0"
                    Background="#72F7F7F7"/>
                            <Border BorderThickness="1"
                    CornerRadius="1,1,1,1">
                                <Border.BorderBrush>
                                    <SolidColorBrush Color="Transparent"
                                 x:Name="MouseOverColor"/>
                                </Border.BorderBrush>
                                <ScrollViewer BorderThickness="0"
                            IsTabStop="False"
                            Padding="{TemplateBinding Padding}"
                            x:Name="ContentElement"/>
                            </Border>
                        </Grid>
                    </Border>
                    <Border x:Name="HoverBorder"
                Opacity="0"
                BorderBrush="{StaticResource NormalBrush}"
                BorderThickness="2,2,2,2"
                CornerRadius="2,2,2,2"/>
                    <Border x:Name="DisabledVisualElement"
                IsHitTestVisible="False"
                Opacity="0"
                Background="#FFFFFFFF"
                BorderBrush="#A5F7F7F7"
                BorderThickness="{TemplateBinding BorderThickness}"
                CornerRadius="2,2,2,2"/>
                    <Border Margin="1"
                x:Name="FocusVisualElement"
                IsHitTestVisible="False"
                Opacity="0"
                BorderBrush="{StaticResource NormalBrush}"
                BorderThickness="2.1,2.1,2.1,2.1"
                CornerRadius="0.2,0.2,0.2,0.2"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


Темы в Silverlight Toolkit October убивают валидацию в TextBox. Т.е. валидационный View. Видимо так было раньше и пока так будет, но это несложно поправить.



Если использовать темы из Silverlight Toolkit, то сразу бросается в глаза, что при их применениее сразу убивается View для валидации в TextBox.
Не знаю с чем связано такое безобразие, но вернуть это все несложно. Для этого нужно выполить следующее:

Рассмотрим стандартно применяемые стиль и шаблоны для TextBox на странице TextBox Styles and Templates (En)

Оттуда скопируем в наш файл, взятой из Silverlight Toolkit темы, “ControlTemplate for ValidationTooltip”.
<ControlTemplate x:Key="ValidationToolTipTemplate">

</ControlTemplate>
Поскольку к этому шаблону из стиля TextBox идет обращение, как к статическому ресурсу по имени ValidationToolTipTemplate, то размещать его XAML надо до XAML стиля TextBox.

Далее нам осталось только дополнить недостающие части XAML стиля для TextBox
<Style TargetType="TextBox">

</Style>

Сравните аккуратно исходный стиль и стиль в вашей теме и вы легко определите место куда вставить недостающие VisualState’ы и <Border x:Name="ValidationErrorElement" … >

Для полноты картины я приведу то что должно получиться, а то что быо до этого приведу в следующем посту, тк получается слишком большой объем

Вот что должно получиться:
___________
    <!--TextBox-->
    <!-- i!t для TextBox пришлось добавлять (возвращать) разметку и VisualState's для валидации
   
http://iliya-tretyakov.spaces.live.com/blog/cns!6DDCA30C11FA5050!504.entry
    -->
    <ControlTemplate x:Key="ValidationToolTipTemplate">
        <Grid x:Name="Root" Margin="5,0" RenderTransformOrigin="0,0" Opacity="0">
            <Grid.RenderTransform>
                <TranslateTransform x:Name="xform" X="-25"/>
            </Grid.RenderTransform>
            <vsm:VisualStateManager.VisualStateGroups>
                <vsm:VisualStateGroup Name="OpenStates">
                    <vsm:VisualStateGroup.Transitions>
                        <vsm:VisualTransition GeneratedDuration="0"/>
                        <vsm:VisualTransition To="Open" GeneratedDuration="0:0:0.2">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="xform" Storyboard.TargetProperty="X" To="0" Duration="0:0:0.2">
                                    <DoubleAnimation.EasingFunction>
                                        <BackEase Amplitude=".3" EasingMode="EaseOut"/>
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                                <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.2"/>
                            </Storyboard>
                        </vsm:VisualTransition>
                    </vsm:VisualStateGroup.Transitions>
                    <vsm:VisualState x:Name="Closed">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="0" Duration="0"/>
                        </Storyboard>
                    </vsm:VisualState>
                    <vsm:VisualState x:Name="Open">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="xform" Storyboard.TargetProperty="X" To="0" Duration="0"/>
                            <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
                        </Storyboard>
                    </vsm:VisualState>
                </vsm:VisualStateGroup>
            </vsm:VisualStateManager.VisualStateGroups>


            <Border Margin="4,4,-4,-4" Background="#052A2E31" CornerRadius="5"/>
            <Border Margin="3,3,-3,-3" Background="#152A2E31" CornerRadius="4"/>
            <Border Margin="2,2,-2,-2" Background="#252A2E31" CornerRadius="3"/>
            <Border Margin="1,1,-1,-1" Background="#352A2E31" CornerRadius="2"/>


            <Border Background="#FFDC000C" CornerRadius="2"/>
            <Border CornerRadius="2">
                <TextBlock
                  UseLayoutRounding="false"
                  Foreground="White" Margin="8,4,8,4" MaxWidth="250" TextWrapping="Wrap" Text="{Binding (Validation.Errors)[0].ErrorContent}"/>
            </Border>
        </Grid>
    </ControlTemplate>
    <Style TargetType="TextBox">
        <Setter Property="BorderThickness"
            Value="1"/>
        <Setter Property="Background"
            Value="{StaticResource ShadeBrush}"/>
        <Setter Property="Foreground"
            Value="#FF000000"/>
        <Setter Property="Padding"
            Value="2"/>
        <Setter Property="BorderBrush"
            Value="{StaticResource NormalBorderBrush}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                    <Grid >
                        <vsm:VisualStateManager.VisualStateGroups>
                            <vsm:VisualStateGroup x:Name="CommonStates">
                                <vsm:VisualStateGroup.Transitions>
                                    <vsm:VisualTransition GeneratedDuration="00:00:00.1"
                                        To="MouseOver"/>
                                    <vsm:VisualTransition GeneratedDuration="00:00:00.1"
                                        To="ReadOnly"/>
                                    <vsm:VisualTransition GeneratedDuration="00:00:00.1"
                                        To="Disabled"/>
                                    <vsm:VisualTransition From="Normal"
                                        GeneratedDuration="00:00:00.3000000"
                                        To="MouseOver"/>
                                    <vsm:VisualTransition From="MouseOver"
                                        GeneratedDuration="00:00:00.5000000"
                                        To="Normal"/>
                                </vsm:VisualStateGroup.Transitions>
                                <vsm:VisualState x:Name="Normal"/>
                                <vsm:VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                   Duration="00:00:00.0010000"
                                                   Storyboard.TargetName="HoverBorder"
                                                   Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                            Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="DisabledVisualElement"
                                                   Storyboard.TargetProperty="Opacity">
                                            <SplineDoubleKeyFrame KeyTime="0"
                                            Value="0.6"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="ReadOnly">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ReadOnlyVisualElement"
                                                   Storyboard.TargetProperty="Opacity">
                                            <SplineDoubleKeyFrame KeyTime="0"
                                            Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                            </vsm:VisualStateGroup>
                            <vsm:VisualStateGroup x:Name="FocusStates">
                                <vsm:VisualStateGroup.Transitions>
                                    <vsm:VisualTransition From="Focused"
                                        GeneratedDuration="00:00:00.5000000"
                                        To="Unfocused"/>
                                    <vsm:VisualTransition From="Unfocused"
                                        GeneratedDuration="00:00:00.3000000"
                                        To="Focused"/>
                                </vsm:VisualStateGroup.Transitions>
                                <vsm:VisualState x:Name="Focused">
                                    <Storyboard>


                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                   Duration="00:00:00.0010000"
                                                   Storyboard.TargetName="FocusVisualElement"
                                                   Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                            Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>


                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="Unfocused">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                   Duration="00:00:00.0010000"
                                                   Storyboard.TargetName="FocusVisualElement"
                                                   Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                            Value="0"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                            </vsm:VisualStateGroup>


                            <vsm:VisualStateGroup x:Name="ValidationStates">
                                <vsm:VisualState x:Name="Valid"/>
                                <vsm:VisualState x:Name="InvalidUnfocused">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="InvalidFocused">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsOpen">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <sys:Boolean>True</sys:Boolean>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                            </vsm:VisualStateGroup>


                        </vsm:VisualStateManager.VisualStateGroups>
                        <Border x:Name="Border"
                    Opacity="1"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    CornerRadius="2,2,2,2">
                            <Grid>
                                <Border x:Name="ReadOnlyVisualElement"
                        Opacity="0"
                        Background="#72F7F7F7"/>
                                <Border BorderThickness="1"
                        CornerRadius="1,1,1,1">
                                    <Border.BorderBrush>
                                        <SolidColorBrush Color="Transparent"
                                     x:Name="MouseOverColor"/>
                                    </Border.BorderBrush>
                                    <ScrollViewer BorderThickness="0"
                                IsTabStop="False"
                                Padding="{TemplateBinding Padding}"
                                x:Name="ContentElement"/>
                                </Border>
                            </Grid>
                        </Border>
                        <Border x:Name="HoverBorder"
                    Opacity="0"
                    BorderBrush="{StaticResource NormalBrush}"
                    BorderThickness="2,2,2,2"
                    CornerRadius="2,2,2,2"/>
                        <Border x:Name="DisabledVisualElement"
                    IsHitTestVisible="False"
                    Opacity="0"
                    Background="#FFFFFFFF"
                    BorderBrush="#A5F7F7F7"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    CornerRadius="2,2,2,2"/>
                        <Border Margin="1"
                    x:Name="FocusVisualElement"
                    IsHitTestVisible="False"
                    Opacity="0"
                    BorderBrush="{StaticResource NormalBrush}"
                    BorderThickness="2.1,2.1,2.1,2.1"
                    CornerRadius="0.2,0.2,0.2,0.2"/>
                        <Border x:Name="ValidationErrorElement" BorderThickness="1" CornerRadius="1" BorderBrush="#FFDB000C" Visibility="Collapsed">
                            <ToolTipService.ToolTip>
                                <ToolTip x:Name="validationTooltip" Template="{StaticResource ValidationToolTipTemplate}" Placement="Right"
                         PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                         DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                                    <ToolTip.Triggers>
                                        <EventTrigger RoutedEvent="Canvas.Loaded">
                                            <EventTrigger.Actions>
                                                <BeginStoryboard>
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsHitTestVisible">
                                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                                <DiscreteObjectKeyFrame.Value>
                                                                    <sys:Boolean>true</sys:Boolean>
                                                                </DiscreteObjectKeyFrame.Value>
                                                            </DiscreteObjectKeyFrame>
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </BeginStoryboard>
                                            </EventTrigger.Actions>
                                        </EventTrigger>
                                    </ToolTip.Triggers>
                                </ToolTip>
                            </ToolTipService.ToolTip>
                            <Grid Width="12" Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Background="Transparent">
                                <Path Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C"/>
                                <Path Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff"/>
                            </Grid>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


Выполнение произвольной промежуточной операции над данными внутривыражения LINQ

Первый абзац это теория и вступление, переходите к следующему, кто в теме
При написании LINQ постоянно появляется желание выполнить промежуточную операцию над данными. По науке это не правильно, т.к. пока производительность не страдает каждый цикл по данным должен служить отдельной роли. Ведь LINQ это и есть цикл, определенные на языке запросов. Но, тоже по науке :), код должен быть очевиден и однотипные или связанные операции сгруппированы.
Сразу ответ на тему поста:
Я использую выражение LINQ “let” для написание промежуточной операции, но с некоторым простым ухищрением. Вот пример:
var orgUnits = (
    from el in orgUnitsDict.Values
    // в промежуточной операции отсортируем элементы в дочернем объекте
    let dummy = el.Phones = el.Phones.OrderBy(p => p.PhoneStr).ToList()    orderby el.ParentId,
    el.IsGroup descending,
    el.Name
    select el
).ToList();
Описание:
В этом выражении из словаря объектов я получаю отсортированный список этих же объектов, но попутно, у меня стоит задача в каждом объекте отсортировать дочернюю коллекцию в свойстве Phones.
Директива let позволяет это сделать. А поскольку в директиве let обязательно должна создаваться промежуточная переменная, то я использую как затычку бесполезную переменную dummy, которая больше нигде не используется в запросе.
Также эту строчку
let dummy = el.Phones = el.Phones.OrderBy(p => p.PhoneStr).ToList()
вы можете заменить следующей
let dummy = el.Phones = MyMethod(el.Phones)
или даже так
let dummy = MyMethod(el)
т.е. можете применять свой произвольный метод для выолнения промежуточной операции,
главное, чтоб он хоть чего-нибудь возвращал.
Очень полезное образовательное надругательство над LINQ.
Веселых вам извратов, господа, если что, обращайтесь :).
Пожалуйста, если вы знаете другие подходы, то дайте знать. Там ссылочку киньте или напишите в комментариях.

четверг, 29 октября 2009 г.

ORA-06502: PL/SQL: numeric or value error: character string buffer toosmall

Ошибка на Oracle
ORA-06502: PL/SQL: numeric or value error: character string buffer too smallВ моем случае это связано с тем, что функция или процедура Oracle имеет возвращаемый парампетр Varchar2
и я использую ODP.NET и следующий код устанавливающий параметр на стороне ADO.NET (т.е. на стороне .NET Framework приложения):
oCom.Parameters.Add("o_name", OracleDbType.Varchar2, ParameterDirection.Output);
Неправильно, сказала Oracle всем :), надо использовать следующее извращение, сказала Оракля:
oCom.Parameters.Add("o_name", OracleDbType.Varchar2, 300, null, ParameterDirection.Output);
Здесь 300 – это размерность. Любая, но не меньше, чем вы ожидаете.
null – ну типа как изначальное значени.
Уже стотый раз спотыкаюсь на этом, но постоянно забываю об этой несуразности.
С облегчением :) !

воскресенье, 25 октября 2009 г.

Silverlight Drag And Drop. У Сильверлайта появился свой нормальный драг дроп с выходом Toolkit от октября 2009 года.



Очень хорошо!
Но оказалось, что это заметно тормозит при количестве элементов в списке от 500. Например, если в ListBox 3 000 элементов, то какая-либо реакция проявляется только через 5 секунд.
Пока проджекта не уговорю сделать пейджинг и фильтрацию, придется, для некоторых задач, продолжить пользоваться своим аналогичным фреймворком, который работает ваабще без задержек.
Но все равно стоит использовать решение из Toolkit, т.к., например, мое решение не умеет разворачивать ноды в TreeView. Недолго сделать, но прикручивать все такие мелочи – жизни не хватит :) .

Ниже источники и описание.

Блог Tim Heuer "Silverlight Toolkit adds DragDrop" EN – здесь ознакомительное описание, позволяющее начать работать с примером.
Silverlight Toolkit EN – а здесь исходник с примером.
Если вы хотите глубоко кастомизировать ваши решения, то нужно смотреть
New with the Silverlight Toolkit: Drag and Drop Support for all your Favorite Controls! (Part 1) и
Silverlight Toolkit Drag Drop (Part 2): Customizing Drag and Drop Behavior
Пример можно посмотреть в ToolKit (выберите в меню слева внизу) и у Tim Heuer.

Этот DragDrop строится на подходе WPF (слава богу) с такими же событиями. Даже можно писать переносимый код, соблюдая некоторые условия.
Идея этого Drag Drop в следуюещем, теперь можно для ListBox, TreeView, DataGrid и графиков (Charts) исполльзовать Драгэнддроп, если вложить их в соответствующий элемент:
  • ListBoxDragDropTarget

  • TreeViewDragDropTarget

  • DataGridDragDropTarget

  • DataPointSeriesDragDropTargetНо также можно применять подход на основе событий и регестрировать через свойства элементы учавствующие в Драг Анд Дроп.

    Важно, что решение можно глубоко кастомизировать и настраивать.
    Заявляется, что можно делать Drag Drop внутри одного контрола, но только в случае ListBox для этого нужно отключать виртуализационную панель. В приведенных выше ссылках об этом рассказано подробно.
    Также доступно перемещение за раз нескольких элементов при множественном выделении айтемов.

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

  • Яндекс устал

    Никогда не задумывался, почему Яндекс непопулярен у активных и продвинутых пользователи интернета. Почему же предпочитают Google.
    Просто Яндекс медленный. Не хватает ресурсов, что бы оперативно проиндексировать весь интернет и поспевать за его изменениями и новостями.
    Там, видимо, посчитали, что если они будут активно переиндексировать популярный контент, то этого достаточно.
    Я люблю оба поисковика, но если мне нужна информация посвежее, я пользуюсь Google.
    Хотя Яндекс, бывает, что приятно удивляет :)

    Задание прикрепленного свойства в XALM. Set Attached Properties in XALM.

    Сразу несколько примеров, чтоб все стало ясно
    Вот эту запись:
    <Button Grid.Row=”1”>
        <TextBlock>1234567890</TextBlock>
    </Button>

    Можно записать так:
    <Button>
        <Grid.Row>
            1
        </Grid.Row>
        <TextBlock>1234567890</TextBlock>
    </Button>
    Пример из жизни:
    <Border>
        <vsm:VisualStateManager.VisualStateGroups>
            <vsm:VisualStateGroup x:Name="CommonStates">
                <vsm:VisualState x:Name="Normal" />
            </vsm:VisualStateGroup>
        </vsm:VisualStateManager.VisualStateGroups>
    </Border>
    Т.е. помимо задания прекрепленных свойств через атрибуты, их можно задавать в нодах XALM.
    Это очень хорошо пригодиться при кастомизации

    Сохраняем в SVN WCF Service References проекта на Silverlight



    Чтобы избежать путаницы с файлами Service References WCF клиента в проекте Silverlight 3 и позволить проекту компилироваться, стоит в SVN сохранять только файлы, содержащие в названии слово Reference. Это всего два файла: Reference.svcmap и Reference.cs. Все остальное добавте в Ignore list SVN, лучше по расширению, т.к. при генерации клиента в названии файлов могут добавлятьс числа.
    Мало того, вы можете физически удалить все что есть в папке Service References, кроме перечисленных выше двух файлов. При этом проект будет компилится и сервисы будут работать.
    При первом же вызове, из контекстного меню в Solition Explorer, Update Service Reference все удаленное восстановиться.

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

    SVN – система контроля версий
    WCF Service References – ссылки которые вы добавляете в клиентский проект, чтобы ему были доступны сервисы WCF, расположенные на хостовом проекте.

    суббота, 24 октября 2009 г.

    Silverlight: Утечки памяти. Memory leak



    Список приемов, которые создают утечки памяти (ресурсов) в Silverlight

    • Биндинг. Привязываем через <my:MyUI SourceUI="{Binding ElementName=MyElementName}"/>. Динамически удаляем или заменяем MyElementName. В свойстве зависимостей SourceUI останется ссылка на удаленный превый экземпляр MyElementName.
      Решение: не использовать привязку для динамически удаляемых элементов.

    • :) другого пока ничего не нашел, но есть сильные подозрения, что найду.


    вторник, 20 октября 2009 г.

    Silverlight 3 Binding ConverterParameter



    Можно передать в ConverterParameter не только значение созданное литералом в выражении привязки, но и объект. Для этого объетк нужно объявить на странице, как статический ресурс и использовать, например, следующее выражение привязки.

    ItemsSource="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource CompensationForPhone}, ConverterParameter={usercontrols:SubscriptionLayoutUiAccessor}}"

    Но прежде чем так делать, подумайте, не лучше ли сделать привязанный к определенному UI IValueConverter и доставать в нем нужные элементы UI из статических свойств.

    воскресенье, 18 октября 2009 г.

    Silverlight: Корректное манипулирование фокусом при его потере



    Вам нужно при нажатии на кнопку анимировать ее и на время анимации заблокировать ее от пользователя. Если блокировать кнопку через IsEnebled=false, (подскажите мне дроугой способ) то фокус переходит на следующий в дереве элемент управления принимающий фокус.
    Например в моем случае я блокирую кнопку Save и получаю фокус на кнопке Delete, что ужасно :)
    Дружественно решить это поможет задание фокуса на корневом элементе Application.Current.RootVisual перед или сразу после установки myButton.IsEnebled=false.
    Единственное ограничение, которое легко обойти, не выставляйте, при старте приложения Silverlight, в RootVisual элемент не наследуемый от Conrol.
    Если вы оставите все как есть, то в RootVisual будет UserConrol, что нам и нужно. Если вас не ломает и не выворачивает жестоко, то вы так и сделаете :)

    А вот желанный кусочек кода
    public static class UiUtilsCommon
    {

        // …

        /// <summary>
        /// Снятие фокуса с текущего элемента и постановка его на RootVisual.
        /// Используется когда на элементе принимающем фокус нужно задать IsEnebled=false, например в анимации, при этом фокус автоматически переходит на следующий в дереве
        /// элемент управления, что часто не желательно, поэтому можно демократично установить фокус на RootVisual
        /// </summary>
        public static void TrySetFocusOnRootVisual()
        {
            // т.к. в RootVisual при запуске приложения можно задать любой UI, то этот функционал не будет работать если RootVisual не неаследуется от Control, защитимся от этого
            try
            {
                ((Control)Application.Current.RootVisual).Focus();
            }
            catch { }
        }

        // …

    }

    четверг, 8 октября 2009 г.

    Ошибка - Компонент "75a0fea7-12fe-4cad-a1b2-525fa776c07e" не установленв данной ферме и не может быть добавлен в эту область

    Ого, сказал я себе, когда ничего не нашел подобного в поисковиках!
    Компонент "75a0fea7-12fe-4cad-a1b2-525fa776c07e" не установлен в данной ферме и не может быть добавлен в эту область.
    У меня это связано со следующим:
    Решил накатить один из шаблонов приложений Windows SharePoint Services 3.0, который для администраторов сервера, т.е. ставиться на уровне сервера из командной строки.
    Но забыл про то, что нужно сначала выполнить установку обязательного шаблона Application Template Core.
    Т.е. я об этом помнил, но у меня уже столько накопилось разработческих сред, что я и не помню где установлен Template Core :).
    Для проверки зайдите в Центр администрирования (Старт – Пуск / Administrative Tools / Центр администрирования SharePoint 3.0). Когда откроется браузер, в нем зайдите в Центр администрирования > Операции > Управление решениями и проверте, что у вас установлено решение “applicationtemplatecore.wsp
    Установить Application Template Core из командной строки можно следующими строками:
    %PROGRAMFILES%\common files\microsoft shared\web server extensions\12\bin\stsadm" -o addsolution -filename "C:\WssTemplates\!ServerAdminTemplates\ApplicationTemplateCore.wsp"
    %PROGRAMFILES%\common files\microsoft shared\web server extensions\12\bin\stsadm" -o deploysolution -name ApplicationTemplateCore.wsp -allowgacdeployment –immediate
    %PROGRAMFILES%\common files\microsoft shared\web server extensions\12\bin\stsadm" -o copyappbincontent
    Только замените файловый путь на ваш (красные символы).
    Скачивается это вместе со всеми “Шаблоны приложений Windows SharePoint Services 3.0”, ну может и отдельно можно скачать :). Там же в архиве есть redme.txt файлик, расказывающий, как надо устанавливать.
    Еще раз, называется это - решение Application Template Core – ApplicationTemplateCore.wsp

    stsadm Нет доступа

    Столкнулся с проблемой при установке шаблона SharePoint на уровне сервера.
    Такие шаблоны устанавливаются только из командной строки через Windows SharePoint Services administration tool STSADM.EXE
    Эта штука лежит в %PROGRAMFILES%\common files\microsoft shared\web server extensions\12\bin\
    Дак во, при любом вызова stsadm я получал сообщение “Нет доступа”.
    Гугл сказал, что Нужны были права админа в базе данных, но мне некогда было разбираться с правами, я вспомнил, что устанавливал SharePoint (в моем разработческом случае это WSS) под учеткой Administrator, зашел под ней и все установил.
    Причем пришлось поменять пароль администраторской встроенной учетке, тк забыл :)
    Кстати, вот сразу полезные строчки для установления шаблонов на уровне сервера через командную строку
    Установка шаблона
    =
    "%PROGRAMFILES%\common files\microsoft shared\web server extensions\12\bin\stsadm" -o addsolution -filename "C:\WssTemplates\KnowledgeBase.wsp"
    "%PROGRAMFILES%\common files\microsoft shared\web server extensions\12\bin\stsadm" -o deploysolution -name KnowledgeBase.wsp -allowgacdeployment -immediate
    Удаление
    =
    "%PROGRAMFILES%\common files\microsoft shared\web server extensions\12\bin\stsadm" -o retractsolution -name <template_name>.wsp
    "%PROGRAMFILES%\common files\microsoft shared\web server extensions\12\bin\stsadm" -o deletesolution -name <template_name>.wsp
    замените пути до ваших шабллонов WSP в “Установке” и имя шаблона в “Удалении”

    четверг, 1 октября 2009 г.

    ”Введение в Microsoft Silverlight 3” от Лоуренса Морони – книга агвно.



    Книга действительно агвно, разве что на русском. Даже Microsoft WPF-Silverlight Comparison Whitepaper  http://wpfslguidance.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=28278 содержит больше информации!Это даже не введение, это рекламный проспект какой-то! Потивно читать, что не возмешь посмотреть по работе, одни белые пятна.
    Я считаю эту книгу вредной для разработчика.Мой совет, используйте хорошую книгу по WPF (помимо блогов и MSDN, и прочего конечно), там материала больше на порядки.Надеюсь скоро выпустят что-то приличное для Silverlight 3.”Введение в Microsoft Silverlight 3” от Лоуренса Морони
    Microsoft WPF-Silverlight Comparison Whitepaper

    понедельник, 28 сентября 2009 г.

    Создание изображения из экранного вывода WPF и Silverlight. Попросту Snapshot из Silverlight и WPF.



    Мне не терпиться поделиться новостью, что несколькими строчками кода можно создать изображение из любого элемента Silverlight или WPF. Для этого не нужно использовать Windows API (хотя тоже можно, как вариант).

    Применяются для получения изображений классы из пространства имен .NET Framework System.Windows.Media.Imaging и System.Windows.Media.
    Можно получить снэпшет как с любого элемента, так и со всего окна сразу. Полученное изображение в Silverlight можно передать по WCF на сервер или даже предложить пользователю сохранить на диск.

    Я создал примеры для WPF и Silverlight. Мне требуется их осмыслить, немного причесать перед выкладыванием, но срочный проект на работе забрал все мои ресурсы, в т.ч. свободного времени. Я заимусь этим позже, тк всеравно это будет использоватся по работе. Но я считаю, что мы все грамотные разработчики, поэтому для нас действует принцип: “Осведомлен, значит вооружен”.
    Итак, я вас вооружил :) Погуглите, поищите в MSDN-форумах, походите по блогам. В том числе вы наткнетесь и на мои сырые примеры в комментариях.

    И всетаки вот куски кода, скорее всего они будут вам очень полезны, если я не доберусь до этого поста.

    Для Silverlight
    _______________________________
    using System.Windows.Controls;
    using System.Windows;
    using System.Windows.Media.Imaging;
    using System.Windows.Media;

    namespace SilverlightApplication2
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
            }        private void Button_Click(object sender, RoutedEventArgs e)
            {
                WriteableBitmap bit = new WriteableBitmap(this, null);
                bit.Render(this, new MatrixTransform());
                Image img = new Image();
                img.Source = bit;
                StackPanel1.Children.Clear();            Border border = new Border();
                var brush = new SolidColorBrush(SystemColors.ActiveBorderColor);
                border.BorderBrush = brush;
                border.BorderThickness = new Thickness(20);
                border.Child = img;            StackPanel1.Children.Add(border);
            }
        }
    }
    +===============================+
    <UserControl x:Class="SilverlightApplication2.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
        <Grid x:Name="LayoutRoot">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <StackPanel Grid.Column="0">
                <TextBox Width="100"></TextBox>
                <TextBox Width="100"></TextBox>
                <Button Width="100" Content="Update" Click="Button_Click"></Button>
            </StackPanel>
            <StackPanel x:Name="StackPanel1" Grid.Column="1" VerticalAlignment="Center">
            </StackPanel>
        </Grid>
    </UserControl>
    ______________________________________________Для WPF
    _______________________________
    <Window x:Class="CaptureBitmapImage.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300"
            Background="Red"
            >
        <Grid>
            <Border>
                <Button Background="Yellow" Height="23" Name="button1" Width="75" Click="button1_Click">Button</Button>
            </Border>
        </Grid>
    </Window>
    +================================+
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.IO;namespace CaptureBitmapImage
    {
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
            }        private void button1_Click(object sender, RoutedEventArgs e)
            {
                SaveWindowSnapshot(this, "!!!__!!!__MyWindowSnapshot.jpg");            // add Button name "button1" before
                SaveWindowSnapshot(button1, "!!!__!!!__MyButtonSnapshot.jpg");
            }        private void SaveWindowSnapshot(Visual targetVisual, string fileName)
            {
                Matrix m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
                double myDeviceDpiX = m.M11 * 96.0;
                double myDeviceDpiY = m.M22 * 96.0;            BitmapSource bitmapSource = captureVisualBitmap(
                    targetVisual,
                    myDeviceDpiX,
                    myDeviceDpiY
                    );            var imgStream = GrabSnapshotStream(bitmapSource, myDeviceDpiX, myDeviceDpiY, ImageFormats.JPG);
                using (imgStream)
                {
                    imgStream.Position = 0;                var fileStream = new FileStream(@"c:/" + fileName, FileMode.OpenOrCreate);
                    using (fileStream)
                    {
                        for (int i = 0; i < imgStream.Length; i++)
                        {
                            fileStream.WriteByte((byte)imgStream.ReadByte());
                        }
                    }
                }
            }        private static BitmapSource captureVisualBitmap(Visual targetVisual, double dpiX, double dpiY)
            {
                Rect bounds = VisualTreeHelper.GetDescendantBounds(targetVisual);            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(
                    (int)(bounds.Width * dpiX / 96.0),
                    (int)(bounds.Height * dpiY / 96.0),
                    dpiX,
                    dpiY,                //PixelFormats.Default
                    PixelFormats.Pbgra32
                    );            DrawingVisual drawingVisual = new DrawingVisual();
                using (DrawingContext drawingContext = drawingVisual.RenderOpen())
                {
                    VisualBrush visualBrush = new VisualBrush(targetVisual);
                    drawingContext.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));
                }
                renderTargetBitmap.Render(drawingVisual);            return renderTargetBitmap;
            }        public static MemoryStream GrabSnapshotStream(BitmapSource bitmapSource, double dpiX, double dpiY, ImageFormats imageFormats)
            {
                BitmapEncoder bitmapEncoder;            switch (imageFormats)
                {
                    case ImageFormats.PNG:
                        {
                            bitmapEncoder = new PngBitmapEncoder();
                            break;
                        }
                    case ImageFormats.BMP:
                        {
                            bitmapEncoder = new BmpBitmapEncoder();
                            break;
                        }
                    case ImageFormats.JPG:
                        {
                            bitmapEncoder = new JpegBitmapEncoder();
                            break;
                        }
                    default:
                        throw new NotSupportedException("The Incorrect Logic");
                }            bitmapEncoder.Frames.Add(BitmapFrame.Create(bitmapSource));            // Create a MemoryStream with the image.
                // Returning this as a MemoryStream makes it easier to save the image to a file or simply display it anywhere.
                var memoryStream = new MemoryStream();
                bitmapEncoder.Save(memoryStream);            return memoryStream;
            }        public enum ImageFormats
            {
                PNG,
                BMP,
                JPG
            }
        }
    }Источники:
    Коллеги, погуглите, при случае привиду ссылки. Я сам гуглил.

    четверг, 24 сентября 2009 г.

    Silverlight не поддерживает RoutedEvent в EventTrigger, кроме Loaded



    Если вы получили похожую ошибку:
    Unhandled Error in Silverlight Application Attribute UIElement.MouseEnter value is out of range.
    то давайте ее полечим.

    Исходный код: Source for VS 2008

    Книга "Введение в Silverlight 3" на странице 112 говорит “... обратите внимание, что RoutedEvent поддерживает только событие Loaded (Загружен).” Т.е. как в WPF, декларативно через XALM, это не работает.
    Т.е. Silverlight 3 (и предшественники) для атрибута RoutedEvent в элементе EventTrigger в XALM разметке поддерживает только значение Loaded.

    Но уже давно есть решение, например RoutedEvent on EventTrigger is giving error that Rectangle.MouseEnter value is out of range
    Опишу его более подробно. Сначала посмотрим на разметку:

    <UserControl x:Class="SilverlightAnimation.MainPage"
    xmlns="
    http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <Grid Name="LayoutRoot" Margin="2" MouseEnter="LayoutRoot_MouseEnter" Background="Red">
    <Grid.Resources>
    <!--<Storyboard x:Name="LayoutRootStoryboard">-->
    <Storyboard x:Key="LayoutRootStoryboard">
    <DoubleAnimation
    Storyboard.TargetName="LayoutRoot"
    Storyboard.TargetProperty="Opacity"
    From="1" To="0"
    />
    </Storyboard>
    </Grid.Resources>
    <TextBlock Text="Как всикда, превед митвет!" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
    </Grid>
    </UserControl>


    и посмотрим на код обработчиика LayoutRoot_MouseEnter

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media.Animation;


    namespace SilverlightAnimation
    {
    public partial class MainPage : UserControl
    {
    public MainPage()
    {
    InitializeComponent();
    }


    private void LayoutRoot_MouseEnter(object sender, MouseEventArgs e)
    {
    var element = (FrameworkElement)sender;
    // если вы задали ключ x:Key или имя x:Name
    var storyboard = (Storyboard)element.Resources["LayoutRootStoryboard"];
    // строчка ниже будет работа только если вы задали имя x:Name
    //var storyboard = (Storyboard)element.FindName("LayoutRootStoryboard");


    storyboard.Begin();
    }
    }
    }


    Смысл этого в следующем:

    • Кидаем Storyboard в ресурсы любого элемента.

    • Если в коде мы легко получаем доступ к элементу, в ресурсах которого лежит Storyboard, то можем использовать обращение по ключю < Storyboard x:Key=”” >.
      Вот так мы будем доставать Storyboard :
      (Storyboard)element.Resources["LayoutRootStoryboard"];

    • Иначе можем идентифировать Storyboard по имени x:Name, но тогда оно должно быть уникальным в разметке XALM.
      Вот так получаем:
      (Storyboard)element.FindName("LayoutRootStoryboard");
      здесь element может быть любым элементом на странице

    • Запускаем анимацию методом .Begin()


    вторник, 22 сентября 2009 г.

    WPF-серия. Группы валидации в WPF



    Пока разбирался с валидацией в WPF успел создать функционал групп валидации, наподобии ASP.NET. Сделал свои ананлог, но теперь, честно говоря, досканально поняв и поработав с валидацией в WPF и Silverlight, я бы сделал группы валидации по другому, а может и не стал бы делать вообще. Слишком большое поле для кастомизации, что-бы еще притаскивать на это “поле” группы валидации.

     

    Выделение любого текста в GUI Silverlight и WPF



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

    В WPF для этого используется немного настроенный TextBox со свойством IsReadOnly=”true”
    Используется следующий стиль
    <Style x:Key="Texted" TargetType="TextBox">
    <Setter Property="IsReadOnly" Value="True" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="IsTabStop" Value="False" />
    </Style>


    В Silverlight 3 этот фокус теперь не пройдет, тк появилось закрашивание серым цветом если IsReadOnly=”true”
    Решается это следующим кастомным стилем (например разместите его в App.xaml в ResourceDictionary)
    <Style x:Key="OnlySelectedTextBox" TargetType="TextBox">
    <Setter Property="IsReadOnly" Value="True"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="#FF000000"/>
    <Setter Property="Padding" Value="2"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="TextBox">
    <Grid x:Name="RootElement">
    <Border x:Name="Border" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1">
    <ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>
    </Border>
    </Grid>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>


    Далее можете на любой странице применять следующее
    <TextBox Text="LaLa:" Style="{StaticResource OnlySelectedTextBox}"/>

    Замечание!
    Я немного сильно доработал шаблон контрола в этом стиле. Если вам нужно что-то более нежное с сохранением всего функционала TextBox, то используйте вот это preventing greyed-out effect when TextBox.IsReadOnly = true
    Там говориться, что надо подправить полностью содрать через Expression Blend 3 стиль TextBox, задать ему имя, и поменять одну строчку в стиле, отвечающую за закрашивание
    <Border x:Name="ReadOnlyVisualElement" Opacity="0" Background="#5EC9C9C9"/>
    на
    <Border x:Name="ReadOnlyVisualElement" Opacity="0"/>
    Далее можно использовать как у меня <TextBox Text="LaLa:" Style="{StaticResource MyTextBoxStyle}"/>

    среда, 22 июля 2009 г.

    Размещение строки создания (наполнения) нового элемента первой строкой в DataGrid WPF Toolkit.

    По умолчанию строка для добавления/наполнения нового элемента расположена внизу DataGrid WPF.
    Для её размещения сверху нужно обратиться к представлению по умолчанию для коллекции, которая будет привязана к DataGrid, привести его к IEditableCollectionView (представлению для редактирования) и задать соответствующий параметр NewItemPlaceholderPosition. Вот как это выглядит в коде:

    var view = (IEditableCollectionView)CollectionViewSource.GetDefaultView(productGroups);
    view.NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtBeginning;

    Добавьте этот код после создания привязываемой коллекции, можно, даже, до ее наполнения.

    Вот как-то так :)

    Взято из WPF DataGrid – New Item Template Sample.