Все записи с меткой 'c#'


XamlCombine


Для Fluent-а и ряда других проектов я написал небольшую утилиту для объединения нескольких xaml-овых Resource Dictionary в один большой xaml.
Данная утилита:
  1. считывает список словарей, которые надо объединить из файла;
  2. загружает ресурсы из этих словарей;
  3. собирает список используемых namespace-ов и удаляет повторяющиеся;
  4. сортирует загруженные ресурсы в порядке их использования (т.е. первыми окажутся те ресурсы, которые будут использоваться последующими);
  5. заменяет DynamicResource на StaticResource;
  6. сохраняет полученный словарь ресурсов в файл.

Командная строка, для работы с утилитой:
XamlCombine.exe list-of-xamls.txt result-xaml.xaml
Где:
  • list-of-xamls.txt - текстовый файл содержащий список xaml-овых словарей, которые необходимо объеденить,
  • result-xaml.xaml - имя результирующего xaml файла.

Я предпочёл использовать один большой xaml, а не набор смерженых (merged), потому что:
  1. при использовании одного xaml-а увеличивается скорость загрузки приложения и уменьшается кол-во занимаемой памяти;
  2. в едином xaml-е можно использовать StaticResource заместо DynamicResource, что также даёт прирост производительности;
  3. нет проблем с Generic.xaml для библиотек с lookless контролами.

В ближайшее время планируется:
  • ввести возможность отключения замены DynamicResource на StaticResource;
  • ввести возможность отключения сортировки ресурсов;
  • ввести поддержку включения merged словарей (в данной версии они удаляются).

Страница проекта на CodePlex-е.

Доступ к ViewModel списка из контекстного меню элемента списка


Недавно возник следующий вопрос. Есть ListBox, элементы которого берутся из коллекции ViewModel. Их вид задаётся через ItemsTemplate. В ItemsTemplate задано контекстное меню. Необходимо добавить в это контекстное меню MenuItem, заголовок которого брался бы из ViewModel.
Доступ к ViewModel списка из контекстного меню элемента списка

Читать далее...

Дерево с несколькими колонками


Стандартный TreeView в WPF, казалось бы, не позволяет сделать многоколоночное дерево. Но, как оказалось на практике, немного пошаманив с DataTemplate и Binding, нужного результата достигнуть не сложно.
Дерево с несколькими колонками

Читать далее...

Сплэшскрин в WPF


В .NET Framework 3.5 SP1 появилась возможность использовать в качестве сплэшскрина картинку из ресурсов. Для этого необходимо было поставить у картинки Build Action в SplashScreen, либо в коде использовать класс SplashScreen. Но данный сплэшскрин был очень ограничен в своих возможностях. На него даже невозможно было вывести текст. И если при старте программы была необходимость выводить сплэшскрины с разным текстом, то приходилось создавать множество вариантов картинок, со всеми возможными надписями. Как вариант можно было сделать отдельно фоновую картинку и отдельно картинки с надписями и показывать два сплэшскрина один поверх другого (такой метод мы использовали в ТЕХНОкоорд 5.0), но в данном случае был возможен вариант, когда пользователь ткнёт мышкой в фоновый сплэшскрин и он перекроет сплэшскрин с текстом. Также как вариант можно сначала показывать простой сплэшскрин из картинки, а потом когда загрузятся нужные сборки показывать WPF-ное окно, как сплэшскрин, так например поступает Expression Blend. Но такой вариант имеет смысл, если у вас ещё после инициализации WPF-а происходит загрузка большого количества данных, или использовать как сплэшскрин только WPF-ное окно - это вообще не вариант (мы пробовали это в 4-ом ТЕХНОкоорд-е), поскольку к тому времени, как такой сплэшскрин появится на экране, уже загрузится главное окно приложения.
Сплэшскрин в WPF
А потом появилась бета-версия Microsoft Office 2010, с очень красивым анимированным сплэшскрином, и мне захотелось использовать похожие сплэшскрины в моих приложениях на WPF-е. Поэтому был создан класс ExtendedSplashScreen, который позволяет создавать гораздо более богатые сплэшскрины, чем стандартный WPF-ный SplashScreen. Модифицированная версия этого класса применяется в тестовых сборках ТЕХНОкоорд-а 6.0.

Читать далее...

Множественное выделение в дереве используя M-V-VM


Стандартный WPF-ный TreeView не поддерживает возможность множественного выделения. Поэтому в том случае, когда это необходимо приходится либо пользоваться сторонними коммерческими контролами (которые, как правило, весьма невысокого качества), либо реализовывать свой вариант дерева, что является достаточно нетривиальной задачей. Но если вы в своём проекте используете шаблон проектирования Model - View - ViewModel (M-V-VM), то реализовать множественное выделение можно значительно более простым путём.
Множественное выделение в дереве используя M-V-VM

Читать далее...

Кнопки как в супербаре Windows 7


Ещё начиная с момента выхода Windows 7, мне хотелось сделать на WPF-е стиль для кнопок, такой же как в супербаре. И наконец-то у меня дошли до этого руки.
Кнопки как в супербаре Windows 7

Читать далее...

Баг с роутингом в ASP.NET MVC под 4-ый .NET Framework


Полгода назад я нашёл странный баг в ASP.NET MVC 2 под .NET Framework 4. Сегодня у меня наконец дошли руки разобраться в чём там дело и как это обойти.

Читать далее...

Рендер под Windows CE


Экспериментальным путём установил, что рендеринг Bitmap-а под Windows CE занимает минимальное время, если формат изображения соответствует формату системы, в большинстве случаев это - 16 бит на цвет по 5-6-5 на компонент. Пришлось допилить библиотечку для работы именно в таком формате, а не в RGB32, как было (впрочем поддержку RGB32 я оставил на всякий случай).
Также написал библиотеку для работы с DirectShow, чтоб проигрывать музыку и, в будущем, видео. Также написал поддержку извлечения тэгов и mp3 и wma файлов, поскольку использовать для этого DirectShow, неудобно и ресурсоёмко.

Windows CE


После покупки в машину проигрывателя основанного на Windows CE, меня самым естественным образом потянуло написать более пристойную оболочку, чем жуткое разноцветное творение китайцев. Поэтому я активно принялся экспериментировать с различными графическими библиотеками под Windows CE. Результат оказался печальным: во-первых 90% библиотек были заточены под Windows Mobile и на CE просто не запускались, а во-вторых у меня на устройстве оказалась настолько урезанная версия Windows CE, что в неё отсутствовал DirectDraw и даже не работали функции WinApi для альфа-блендинга.
Windows CE
Поэтому пришлось написать свою маленькую библиотечку по работе с графикой. Низкий уровень библиотеки написан на C++ (думаю в будущем переписать на ассемблер, но лень пока побеждает), высокий на C#. Идеологически библиотека пытается реализовывать что-то напоминающее M-V-VM, только с огромными ограничениями. По причине неработоспособного DirectDraw, для вывода на экран, используется GDI-шный DrawBitmap, он не очень быстр (подозреваю, что тут дело в неверной битности изображения), но учитывая ориентацию на рендеринг пользовательского интерфейса, производительности должно хватить.
Впрочем хотелось бы добавить каких либо эффектов, но на устройстве очень туго с floating-point операциями, так что похоже придётся обойтись без них, разве что придумаю эффекты работающие в целых числах.

Microsoft WPF Ribbon


Итак, свершилось то, чего мы ждали многие годы (ну, если честно, то лично мы-то забросили ждать ещё в ноябре прошлого года, начав Fluent) - микрософты выпустили Ribbon for WPF.
Microsoft WPF Ribbon

Читать далее...

Странный баг в ASP.NET MVC 2


Есть у меня проект на ASP.NET MVC 2, и есть там такой Route:
routes.MapRoute(
                "Archive", // Route name
                "archive/{year}/{month}/{day}", // URL with parameters
                new { controller = "Archive", action = "Overview", year = string.Empty, month = string.Empty, day = string.Empty }, // Parameter defaults
                new { year = @"(\d\d\d\d)?", month = @"\d?\d?", day = @"\d?\d?" }
            );
и соответственно я потом строю Url таким методом:
Url.RouteUrl("Archive", new {action="Overview", year = string.Empty, month = string.Empty, day = string.Empty});

Так вот если компилировать данное приложение под .NET 3.5, то все работает, возвращается правильный url, а вот если под 4-ый то возвращается null. Соответственно возникают вопросы: 1-ый может я где-то в корне не прав, 2-ой какого дьявола никто кроме меня на такое не нарывался (по крайне мере гугл и бинг молчат об этом) и 3-е если я сконвертирую проект под ASP.NET MVC 3 Preview исправится ли данный баг или нет?

Немного про шаблоны ContentControl-ов


Почему-то большинство людей, которым доводилось делать ControlTemplate-ы для ContentControl-ов никогда не используют возможность ограничить тип этого самого контента. Например если у нас есть кнопка, про которую мы точно знаем, что там будет только картинка, то почему не задать её шаблон следующим образом:
<ControlTemplate  TargetType="Button">
    <Border>
        <Image Source="{TemplateBinding Content}"/>
    </Border>
<ControlTemplate>
И тогда в xaml-е можно ее будет задавать следующим образом:
<Button>Images/Image1.png</Button>
Вместо традиционного:
<Button><Image Source="Images/Image1.png"/></Button>
Получается короче и удобнее в использовании. Естественно, использование данной возможности накладывает ограничение на использование таких шаблонов в незапланированных целях, поэтому допустим применять такую возможность в библиотеках компонентов будет не лучшей идей, но для использования внутри конкретного законченного проекта будет вполне удачно для упрощения и уменьшения написанного xaml-а.

IsAsync в биндинге


Заметил, что если поставить у биндинга свойство IsAsync в true, то он не будет тормозить при загрузке, если в во ViewModel-и коллекция создана как-то так:
private ObservableCollection<string> stringCollection;
public ObservableCollection<string> stringCollection
{
    get
    {
        if(stringCollection==null)  stringCollection = FillStringCollection();
        return stringCollection;
    }
}
Т.е. он загрузит коллекцию асинхронно, соответственно если ещё поставить триггер на null, то можно рисовать красивую анимацию загрузки, что весьма удобно при больших объёмах данных.

Размер Thumb-а у ScrollBar-а


В общем и целом WPF мне нравится. Вещь замечательная, удобная и не имеющая аналогов. Из более менее близких можно назвать пожалуй Qt, благо после покупки Нокией он стал развиваться гораздо активней и в целом движется в относительно верном направлении. Ещё конечно можно назвать Htmlayout, но он все таки слегка из другой оперы, хоть на данный момент и является единственной возможностью создавать красивые нативные приложения под Windows (Qt я нативным не считаю, ибо это монстр ещё похлеще .Net). Так вот, WPF мне нравится, но иногда там встречаются настолько нетрадиционные решения, что волосы дыбом встают. Вот например есть скроллбар (ScrollBar) и мы хотим задать Thumb-у этого скроллбара некую минимальную высоту (или ширину в зависимости от того вертикальный ли это скроллбар или горизонтальный). Казалось бы что проще, ставишь MinHeight Thumb-а в нужное значение и наслаждаешься полученным результатом. А вот нет. Основной поведенческой логикой скроллбара заведует некий Track, который нисколько не волнуют всякие там MinHeight-ы и который тупо урезает Thumb до того размера, до которого сочтёт необходимым. После долгого ознакомления с MSDN-ом, выяснилось следующее: для минимального размера Thumb-а Track использует константу SystemParameters.VerticalScrollBarButtonHeightKey (точнее половину от значения этой константы), которая по умолчанию связана с дефолтным значением в Windows. И эту константу можно поменять в ресурсах Track-а примерно таким образом:
<Track.Resources>
  <sys:Double x:Key="{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}">100</sys:Double>
</Track.Resources>
Век живи, век учись, так руки бы и оторвал тем индусам, которые такое наворотили.
К слову не могу не заметить, что ни в одном из видимых мною платных WPF-ных контролов, в котором был кастомный стиль на скроллбар, не было задано нужной минимальной высоты, поэтому во всех них наблюдались некоторые баги при достижении минимального значения. И это определённо свидетельствует о недостаточном качестве этих самых контролов. Вот посмотришь на чужие контролы и так и хочется заняться создание правильных контролов для WPF-а (и silverlight-а тоже), а то продаваемые сторонними конторами контролы в большинстве своём абсолютно никакие.

Стиль для круглой кнопки


В Window Vista (а также судя по бета версии и в Windows 7) кнопка "Пуск" перестала выглядеть как унылый прямоугольник, и стала красивой круглой. Также аналогичная кругла кнопка была использована в Windows Media Player, в Windows Photo Viewer , в Windows Live Gallery и, с другой расцветкой, в Microsoft Office 2007.
Стиль для круглой кнопки
Реализовать аналогичную кнопку в WPF достаточно легко.

Читать далее...

Тултипы как в офисе 2007


В 2007-ом офисе появилось множество всяческих достаточно интересных элементов управления. В том числе достаточно привлекательная всплывающая подсказка (tooltip).
Тултипы как в офисе 2007

Читать далее...

Выпадающий по нажатию на кнопку Popup


Собственно говоря я совсем не собирался писать о такой элементарной вещи, как выпадающий по нажатию на кнопку Popup, если бы не увидел, как некоторые выполняют эту достаточно примитивную операцию путём написания обработчика клика кнопки и присваивания в нем IsOpen=true (а некоторые особо извращённые ещё и позиционируют попап прям в коде используя PointToScreen/PointFromScreen).
Выпадающий по нажатию на кнопку Popup

Читать далее...

Просмотрщик XPS


В свое время, вместе с выходом висты, если я не ошибаюсь, компания Microsoft ввела такой формат как xps. Этот формат вроде был призван потеснить адобовский pdf, но микрософт не утрудили себя каким-либо его продвижением. В целом формат достаточно неплох для такого рода вещей, как всякие отчёты, мануалы и прочие документы не требующие модификации. Вот только присутствует один большой недостаток. У данного формата отсутствует толковый просмотрщик, поскольку просматривать его предлагают в интернет эксплорере, с помощью плагина который шёл в комплекте с вистой, а в xp и 2003 ставился вместе с 3-им дотнет фреймворком, что крайне неудобно, плюс просмотрщик внутри ie не поддерживает, ни структуры документа, ни внутрених ссылок. В общем достаточно хороший формат был бездарно загублен убогим просмотрщиком. Чуть позже в микрософте опомнились и сварганили Xps Essentials Pack, который несмотря на пафосность названия и представлял собой вполне нормальный (за исключением того, что этого просмотрщика существует как минимум 4 разных версии, под разные версии windows) просмотрщик для этого самого xps-а. Плюс в windows 7 такой просмотрщик(явный наследник essential pack) включён по умолчанию, плюс плагин для ie серьезно доработан.
Так вот, чему я это все. А к тому, что в 3-ем дотнет фреймворке встроена функциональность для работы с этим самым xps-ом. И сейчас я покажу, как написать свой просмотрщик для него.
Просмотрщик XPS

Читать далее...

Bling


Какую славную библиотечку для wpf-а я отрыл. Просто полный отпад. Особо радует возможность писать пиксельные шейдеры без возьни с hlsl-ем - это просто пять с плюсом. Я в глубоком восторге, хоть и не все шейдеры работают (выдают какие-то ошибки компиляции, судя по всему, связанные с тем, что конверсия числа в строку идёт с системными параметрами и, соответственно, вместо точки, дробная часть отделяется запятой).

Метки: wpfhlslc#

ColorPicker на WPF


Нашел статейку (http://www.codeproject.com/KB/WPF/WPF_CustomerControl.aspx) про то как делать собственные контролы на WPF. Если не придираться к использованию терминов и формулировкам, то с приведенным способом написания своих контролов можно согласиться. А вот выбранный пример абсолютно неадекватен, т.к. ColorPicker в WPF можно сделать гораздо проще и быстрее с помощью DataTemplate.
ColorPicker на WPF

Читать далее...

TextBox с описанием и картинкой в WPF


Недавно с ужасом заметил, что для создания TextBox с описанием (не знаю как это правильно называется: в общем, когда в TextBox нет текста и фокуса, там написано, что это за поле ввода, как в висте в проводнике в правом верхнем углу окошко поиска) некоторые люди создают новый UserControl, тогда как гораздо проще(и с гораздо меньшим количеством кода) можно сделать это стилями и ControlTemplate.
TextBox с описанием и картинкой в WPF

Читать далее...

Entity Framework


Entity Framework меня глубоко поражает, при работе с Compact Sql Server он не поддерживает автоинкрементные поля. При этом на вопросы по этому поводу создатели отвечают, что мол так получилось и рекомендуют сделать поле обычным и увеличивать его ручками, я в шоке, ещё в 21-ом веке буду поля ручками увеличить… Пойду SQL вспоминать, а на будущее надо запомнить, что надо держаться от этого Sql Server CE подальше.

Баг в Sql Server CE


В проклятом Sql Server CE есть весёленький баг - иногда когда к нему обращаешься через LINQ он выдаёт шикарный exception: "The ntext and image data types cannot be used in WHERE, HAVING, GROUP BY, ON, or IN clauses, except when these data types are used with the LIKE or IS NULL predicates.", хотя ни ntext ни image в таблице не присутствуют вообще. Обходится все это составление строкового запроса типа: entities.Where("it.ID == '" ID "'"). Вот так вот всё оригинально.
И вообще весь этот компактный sql сервер мне весьма не нравится. Тормозной, малофункциональный, лучше конечно, чем sqlite, но до Sql Server Express очень сильно недотягивает. Зато его ставить не надо.

Double click в WPF-е


Обнаружил, что для контролов, у которых отсутствует OnMouseDoubleClick, обработчик двойного клика можно получать следующим способом:
private void OnItemMouseDown(object sender, MouseButtonEventArgs e)
{
    if(e.ClickCount==2)
    {
        // Здесь даблклик
    }
}
Тем же способом можно получить и тройной клик и т.д.

Создал тестовый проектик на XNA для Zune


Наваял тестовый проект на XNA под Zune, с ходящим роботом (гандамчег, с турбосквида скачал)
Создал тестовый проектик на XNA для Zune
Обнаружилась редкостная гадость: проклятая Zune понимает исключительно единственный формат картинки - 32-х битный, а учитывая 16-ти метровое ограничение на память это выглядит крайне печально, ибо только анимации хождения для робота весят 2,5 метра. Походу придётся придумывать, как использовать подгрузку данных с жесткого диска. Эх, нет чтоб поддерживать мой любимый l4a4.

Внезапно


День великих открытий: я до сих пор не знал, что можно так делать:
public bool IsUsing
{
      get { return (bool)GetValue(IsUsingProperty); }
      private set { SetValue(IsUsingPropertyKey, value); }
}

Очередной баг в WPF


Наткнулся сегодня в WPF на неприятный баг - если у окна установить ResizeMode в ResizeWithGrip, то из другого потока уже не получится создать окно с ResizeMode = ResizeWithGrip. Поскольку при этом выскакивает ошибка доступа к Brush из другого потока. Как я понимаю, это связано с тем, что либо стиль окна у них там кэшируется, либо Brush, либо ещё что-то. Всегда подозревал, что для локальных ресурсов кэширование - это зло. Час убил на этот баг. (Что-то я сегодня торможу :) первый день после трёхдневного выходного сказывается. К слову как-то раз на такой фокус мы нарывались и с BitmapImage, но там это лечилось просто отключением кэширования либо Freeze.

PS. Хотел было мелкософтам отписать о баге, да лень стало это на ангельском формулировать. Ладно, глядишь кто другой отпишет.

Метки: bugswpfc#

Работа с zip-архивами


Всё таки в Microsoft были неправы, сделав интернальными столько полезных классов в .Net Framework.
Вот например, работа с *.zip файлами. Класс есть, но он интернальный, а возможность работать дана тока с пакэйджами (package - это такие zip-архивы, которые содержат Content_Types.xml, например документы 2007-го офиса). И вот зачем спрашивается надо было закрывать? Пришлось воспользоваться рефлекшеном для работы:
Assembly asm = Assembly.GetAssembly(typeof (ZipPackage));
Type ZipArchiveType = asm.GetType("MS.Internal.IO.Zip.ZipArchive");
Type ZipFileInfoType = asm.GetType("MS.Internal.IO.Zip.ZipFileInfo");
MethodInfo openOnStreamMethod = ZipArchiveType.GetMethod("OpenOnStream", BindingFlags.Static | BindingFlags.NonPublic);
object archive = openOnStreamMethod.Invoke(null, new object[] {stream, FileMode.Open, FileAccess.Read, false});
MethodInfo getFileMethod = ZipArchiveType.GetMethod("GetFile", BindingFlags.NonPublic | BindingFlags.Instance);
object contentFile = getFileMethod.Invoke(archive, new object[] {"content.xml"});
MethodInfo getStreamMethod = ZipFileInfoType.GetMethod("GetStream", BindingFlags.NonPublic | BindingFlags.Instance);
using (Stream contentStream = (Stream)getStreamMethod.Invoke(contentFile, new object[] { FileMode.Open, FileAccess.Read }))
{
// Здесь можно без проблем использовать распакованные данные
}

Метки: c#dotnetzip

MS Source Analysis


Microsoft-ы выпустили MS Source Analysis for C#, в отличии от FxCop, который анализируют уже скомпилированный код, эта утилита проверяет исходники на соответствие правилам (а правила там зверские, но их можно отключать/подключать). Также её вроде можно встроить в MSBuild и проверять на корректность кода на этапе компиляции. В общем отличная штука.
PS. В рабочем проекте в каждом файле под тысячу нарушений, впрочем, учитывая, что мы кодируем по своим правилам, а не по тем, что заложены в этой утилите, не удивительно.

Работа с неклиентской областью окна


Давно собирался написать о том, как сделать окно с элементами в неклиентской части. Такое, как, например, в 2007-ом офисе.
Работа с неклиентской областью окнаРабота с неклиентской областью окна

Читать далее...

Окошко в стиле Yahoo Messenger


Увидел недавно Yahoo Messenger for Vista и решил сделать аналогичное окно.
Окошко в стиле Yahoo Messenger

Читать далее...