Ласкаво просимо до dev.net.ua Увійти | Приєднатися | Допомога
Silverlight 3 - Байндинг по несуществующему пути

Как известно, механизмы связывания в Silverlight довольно либеральны, и не выводят никаких жутких ошибок в случае неуспеха связывая с данными (Только вывод в Output Window).

Однако, при декларативном связывании с участием ElementName валидация осуществляется еще на стадии компиляции. Рассмотрим пример:

<src:TagCloudControl x:Name="myTagCloud" Width="400" Height="400">
<src:TagCloudControl.ItemTemplate>
	<DataTemplate>
      	<Border BorderThickness="2,2,2,2" BorderBrush="Cyan" Margin="4">
            	<TextBlock Text="{Binding}" />
		</Border>
	</DataTemplate>                
</src:TagCloudControl.ItemTemplate>
</src:TagCloudControl>


<CheckBox Content="Clip to bounds" 
          Checked="{Binding ElementName=myTagCloud, 
                    Path=ClipToBounds, 
                    Mode=TwoWay}" />

 

TagCloudControl - наследник от UserControl. Умеет рисовать такое:

image 

В данном примере я хотел включить отсечение для элементов, которые выходят за пределы контрола. Свойство ClipToBounds я нашел в MSDN, но не обратил внимание, что оно поддерживается только в WPF. Итак, наш чекбокс связывается с несуществующим свойством...

Build...Build started...

error MSB4018: The "ValidateXaml" task failed unexpectedly.
error MSB4018: System.InvalidOperationException: Stack empty.
error MSB4018:    at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
error MSB4018:    at System.Collections.Generic.Stack`1.Peek()
error MSB4018:    at MS.MarkupCompiler.ValidationPass.ValidateXaml(String fileName, Assembly[] assemblies, Assembly callingAssembly, TaskLoggingHelper log, Boolean shouldThrow)
error MSB4018:    at Microsoft.Silverlight.Build.Tasks.ValidateXaml.XamlValidator.Execute()
error MSB4018:    at Microsoft.Silverlight.Build.Tasks.ValidateXaml.XamlValidator.Execute()
error MSB4018:    at Microsoft.Silverlight.Build.Tasks.ValidateXaml.Execute()
error MSB4018:    at Microsoft.Build.BuildEngine.TaskEngine.ExecuteInstantiatedTask(EngineProxy engineProxy, ItemBucket bucket, TaskExecutionMode howToExecuteTask, ITask task, Boolean& taskResult)

 

Компилятор честно нам сказал, что не смог провести валидацию XAML-кода. Это уже хорошо, т.к заставляет задуматься и подумать, где мы накосячили.

Плохо только то, что не выводится вообще никакого упоминания о том, что-же именно не понравилось валидатору.

Будем надеяться в релизной версии SL3 исправят.

Silverlight - DataBinding к анонимным типам

Вот, случайно обнаружил, что механизм привязки данных некорректно работает с анонимными типами. Рассмотрим пример:

<ItemsControl x:Name="TagsList" >
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Path=TagName, Mode=OneWay}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
</ItemsControl>

 

Привязываемся к коллекции:

TagsList.ItemsSource = new[] 
            {
                new { TagName = "Test 1" }, 
                new { TagName = "Test 2" },
                new { TagName = "Test 3" } 
            };

 

И получаем пустой экран и следующий текст в окне Output:

System.Windows.Data Error:
Cannot get 'TagName' value (type 'System.String') from '{ TagName = Test 1 }' (type '<>f__AnonymousType0`1[System.String]').
BindingExpression: Path='TagName' DataItem='{ TagName = Test 1 }' (HashCode=-796385373);
target element is 'System.Windows.Controls.TextBlock' (Name='');
target property is 'Text' (type 'System.String').. System.MethodAccessException: <>f__AnonymousType0`1.get_TagName()

at System.Reflection.MethodBase.PerformSecurityCheck(Object obj, RuntimeMethodHandle method, IntPtr parent, UInt32 invocationFlags)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
   at System.Windows.CLRPropertyListener.get_Value()
   at System.Windows.PropertyAccessPathStep.ConnectToProperty().

 

Судя по выводимой информации - не найден get-метод для указаного свойства, что наводит на мысль о том, что автоматические свойства в анонимных типах реализованы как-то иначе, чем для регулярных классов.

Кто предупрежен, тот вооружен!

Коротенькая заметка о Blend 3 Preview

Чисто случайно обнаружил что….

Blend3 

В бленде появилась возможность писать код! Коллега по dev.net.ua уже писала об этой возможности, поэтому я сосредоточусь на отличиях редактора от студийного. Итак:

1) Всплывающие подсказки выглядят красивее:

image

Видимо, это позволяют возможности WPF. Даю пророчество – в VS 2010 сделают как-минимум такие-же :).

2) Ключевое слово var ему (редактору) не по зубам. Вывести тип из LINQ выражения и отобразить его во всплывающем окошке не получается. А если и работает – то неправильно:

image

3) Нельзя настроить цветовую схему как в VS. Общая цветовая схема бленда очень сильно контрастирует с белым редактором кода.

4) Эти прикольные вертикальные серые линии показывающие уровни вложенности. Милая фенечка :)

5) Контекстное меню непривычно маленькое:

image

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

IMHO – У MS получился ход конем – с одной стороны классное нововведение в бленд, с другой – неявное тестирование редактора кода на WPF, который, возможно является прототипом редактора для VS2010.

Несколько слов о .NET RIA Services

Сегодня речь пойдет о новой технологии от MS именуемой .NET RIA Services. Людям, которым посчастливилось попасть на MIX '09 об этой технологии расскажут модные люди из Редмонда, а всем остальным прийдется слушать меня :)

Краткий обзор

Итак, что такое .NET RIA Services? Это библиотека, которая содержит в себе все необходимое для построения многоуровневых приложений и которая ориентируется на упрощение и стандартизацию механизмов передачи данных между отдельными слоями приложения. Достигается это за счет следующих механизмов (цитата из Whitepaper):

"Framework components support prescriptive patterns for writing application logic and validation so that it can be easily used on the presentation tier. Tools add to existing Visual Studio capabilities by linking the client and mid-tier projects in a single solution and by enabling smart code generation in client projects. Accompanying services utilize the prescriptive pattern to support commonly used capabilities such as authentication and user settings management."

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

Ключевыми особенностями данной технологии заявлены:

  1. Поддержка непрерывного использования данных.
  2. Унифицированная модель разработки клиентской и серверной частей приложения.
  3. Улучшенная производительность за счет набора шаблонов и служб для основных сценариев.

На рисунке 1 представлена упрощенная схема трехуровневого приложения. В рамке обведена целевая область применения .NET RIA Services.

 Целевая область применения .NET RIA Services

Рисунок 1 - Целевая область применения .NET RIA Services

.NET RIA Services сосредотачиваются на непрерывном использовании данных. Новые компоненты позволяют получать данные из DAL, производить их трансформацию в уровне представления, дополнять их метаданными и правилами для валидации. Переход данных с одного уровня на другой осуществляется через четко оговоренный протокол.

.NET RIA Services упрощают создание приложений за счет вспомогательных утилит для построения многоуровневых приложений. Обещают, что логика приложения станет изолированной и независимой от источников и потребителей данных. В итоге мы получим ядро приложения, содержащее основную логику работы приложения отделенное от кода представления и доступа к данным. В Microsoft это видят так:

.NET RIA Services

Прелесть заключается в том, что пользовател сам описыват тот контракт по которому будут "течь" данные. Поддержка валидации осуществляется декларативно, через аттрибуты.

На данный момент поддерживаются проекты ASP.NET и Silverlight.

В ближайшее время планирую написать продолжение с описанием практического применения.

 

Ссылки по теме:

http://code.msdn.microsoft.com/RiaServices

Microsoft .NET RIA Services March '09 Preview

Code Contracts

Наверняка, все знают, что такое Design by Contract, и какой ценой он дается .NET разработчику :)

Кучи пост-/пред- условий, Debug.Assert, Dbc фреймворки и т.д и т.п.. А проверка условий DbC всегда подразумевает запуск програм и выход по assert-у. К сожалению, C# не поддерживает DbC на языковом уровне. Частично, эту проблему пытается решить Spec#. Но это надо учить новый язык, хоть и основанным на С#.

А что делать, если хочется честного DbC для C# на стадии компиляции?

Использовать Code Contracts!

Что это такое и с чем его едят: небольшое (4.66Mb) расширение для VS 2008, которое позволяет внедрить статическую проверку условий контракта в ваши проекты на C#! После установки нам становится доступно пространство имен System.Diagnostics.Contracts и класс Contract:

image

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

Прелесть заключается в том, что все проверки выполняются на стадии компиляции! Тоесть, предположим у нас имеется некий класс:

public class Foo
{

    public void Compute(string prefix)
    {
        Contract.Requires(prefix != null);
    }

}

И, если какой-то индус программист напишет:

Foo c = new Foo();
c.Compute(null);

То при компиляции кода, он получит предупреждение о нарушении контракта:

image

Как это работает: После сборки проекта запускается утилита cccheck для статической проверки условий. Она анализирует IL код и проверяет все условия, которые могут быть проверены еще до запуска приложения.

Кроме статической проверки кода, выполняется также и проверка в рантайме. Для этого собранная библиотека пропускется через утилиту ccrewrite, которая замещает все вызовы класса Contract рантаймовыми проверками.

Условия проверок гибко настраиваются на новой вкладке "Code Contracts":

image

Помимо этого, статический анализатор порадовал умной реакцией на доступ к значению у Nullable типа без проверки на HasValue:

    public static int Sum(int? optX, int? optY)
    {
      var result = 0;

      result += optX.Value; <--- requires unproven: HasValue

      if (optY.HasValue)
      {
        result += optY.Value;
      }
      return result;
    }

Резюме

Отличный DbC фреймворк на мой взгляд. На порядок лучше тех, что я видел. Рекомендую всем к ознакомлению.

PS: По слухам, будет частью нового C# в VS 2010.

Ссылки по теме:

http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx

Знаете-ли вы как...
#1 Как запретить дальнейшую перегрузку метода в классах-наследниках?

Очень просто - оказывается, ключевое слово sealed можно применять не только к классам, но и к методам:

    class A
    {
        protected virtual void Foo()
        {
            Console.Write("A.Foo");           
        }       
    }

    class B : A
    {
        protected sealed override void Foo()
        {
            Console.Write("B.Foo");           
        }
    }
С почином!

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

http://dev.net.ua/blogs/eugenekhvedchenya/pages/7688.aspx

Анонс сервиса SmartWeb

Речь пойдет о реализации одной из концепций Web 3.0 - предоставлении актуального для конкретного пользователя контента из различных источников. Цель благая - избавить человека от нужды читать тонны RSS каналов, посещать кучу сайтов и следить за обновлениями на любимых ресурсах.

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

В идеале я вижу это так: Например, я хочу получать на свой e-mail все новости, касающиеся Silverlight, но не касающиеся Expression Blend. Для этого, я на некотором сайте ввожу свой e-mail, указываю предпочтения и все - я получаю актуальные для меня новости.

Идею данного концепта я попытался реализовать в проекте SmartWeb. На данный момент, реализован сбор данных через RSS каналы с блогов dev.net.ua, blogs.msdn.com & blogs.gotdotnet.com. На картинке ниже представлена схема связей тегов всех материалов с ресурса dev.net.ua глазами этой системы:

Click here ->  (Осторожно, большая картинка).

Visual Studio 2008 Russian vs Silverlight Tools

Возникло желание пощупать локализованную версию VS 2008. Поставили, все работает. Поначалу, непривычно видеть русские термины и сообщения компилятора (да и зачем оно олдскульным девелоперам?), но для стартапа или знакомства со средой разработки и языком - самое оно.

Но речь не о том. Проблемы возникли при установке Silverlight Tools - они в упор не воспринимают локализованную версию. На странице загрузки Silverlight Tools русский язык в списке доступных отсутствует. Так что англо-неговорящим Silverlight-разработчикам не повезло.

Интересно, будет-ли ситуация исправлена в будущем?

Боремся с OutOfMemoryException своими силами.

Что будет, если в программе слишком часто создается слишком много больших объектов, которые успевают дожить до 2-го поколения? Рано или поздно возникнет одно из самых страшных исключений - OutOfMemoryException.

Однако, несмотря на его кажущуюся ужасность, это не одно из 3-х смертельных исключений, так что можно попытаться исправить ситуацию руками. Возникновение OutOfMemoryException не всегда означает ошибку в программе. Бывает, что с ними приходится мириться.

В случае, когда разработчик уверен в том, что ошибка нехватки памяти вызвана засорением второго поколения, или GC попросту не успевает удалять неиспользуемые объекты, я предлагаю следущее решение:

    public delegate R Function<R>(); 

    public static class Allocator
    {
        public static T New<T>(Function<T> constructor)
        {
            try
            {
                return constructor();
            }
            catch(OutOfMemoryException)
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                return constructor();
            }
        }
    }

Теперь, в Allocator.New можно скармливать фабричные методы, делегаты-конструкторы; словом, все, что может вызвать исключение OutOfMemoryException. В случае, если первый вызов конструктора вызовет исключение, класс попытается освободить память и повторит попытку. В случае, если ничего не получится - исключение все-же выброшено наружую.

Логику поведения аллокатора можно значительно расширить:

  • NewOrNull - Возвращает объект или null в случае неудачи.
  • NewAnyway - Блокирует вызывающий поток до тех пор, пока не удастся создать требуемый объект.
  • Любая другая политика...

PS: А как вы обрабатываете OutOfMemoryException?

Silverlight & 3D
Что Silverlight не поддерживает 3д-графику, знают все. Но некоторые несогласные пишут свои софтварные растеризаторы 3д-сцен. Получается очень даже здорово - http://www.denebspace.com/blog/2008/12/10/silverlight-3d/
Демосцена оживает!

Сегодня утром пришел очередной выпуск MSDN Flash, а в нем, о чудо! - предложение создать Web-приложение размером...10 килобайт!

"...What would you create for the Web if you only had 10 Kbytes of code? Can you optimize like your life depended on it? Enter the contest and find out. The grand prize winner will live large at MIX09 with a free pass to the MIX09 event, three nights at The Venetian Hotel, and a US$1,500 Visa gift card. There are lots of other great prizes, so submit your entry soon."

Стало интересно. Нельзя использовать сторониие библиотеки, приложение должно использовать Silverlight, можно использовать внешние веб-сервисы. 10 кб - размер некомпилированного кода + картинки. Вы как хотите, а я попробую свои силы :)

Подробнее тут: http://2009.visitmix.com/MIXtify/TenKGallery.aspx\