2009-03-09 3 views
52

Я занимаюсь созданием своего первого реального приложения WPF (т. Е. Первого, предназначенного для использования кем-то, кроме меня), и я все еще обворачиваю голову лучший способ сделать что-то в WPF. Это довольно простое приложение для доступа к данным, использующее еще довольно новую Entity Framework, но я не смог найти много рекомендаций в Интернете, чтобы наилучшим образом использовать эти две технологии (WPF и EF) вместе. Поэтому я подумал, что выброшу, как я подхожу к нему, и посмотрю, есть ли у кого-нибудь лучшие предложения.Рекомендации по использованию инфраструктуры Entity Framework с WPF DataBinding

  • Я использую Entity Framework с SQL Server 2008. EF поражает меня, как и гораздо более сложным, чем это должно быть, и еще не созрели, но Linq к SQL-видимому, умер, так Я мог бы также использовать технологию, на которую, похоже, сосредотачивается MS.

  • Это простое приложение, поэтому я еще не видел, как он может создавать отдельный слой данных вокруг него. Когда я хочу получить на данные, я использую довольно простых запросов Linq-на-Сущности, как правило, прямо из моего кода-за, например:

    var families = from family in entities.Family.Include("Person") 
          orderby family.PrimaryLastName, family.Tag 
          select family; 
    
  • Linq к Entity запросы возвращают IOrderedQueryable результат, который Безразлично автоматически отражают изменения в базовых данных, например, если я добавлю новую запись через код в модель данных сущности, существование этой новой записи не будет автоматически отражено в различных элементах управления, ссылающихся на запрос Linq. Следовательно, я бросал результаты этих запросов в ObservableCollection, захватить основные изменения данных:

    familyOC = new ObservableCollection<Family>(families.ToList()); 
    
  • Я тогда карту ObservableCollection к CollectionViewSource, так что я могу получить фильтрацию, сортировку и т.д., без необходимости возвращаться в базу данных.

    familyCVS.Source = familyOC; 
    familyCVS.View.Filter = new Predicate<object>(ApplyFamilyFilter); 
    familyCVS.View.SortDescriptions.Add(new System.ComponentModel.SortDescription("PrimaryLastName", System.ComponentModel.ListSortDirection.Ascending)); 
    familyCVS.View.SortDescriptions.Add(new System.ComponentModel.SortDescription("Tag", System.ComponentModel.ListSortDirection.Ascending)); 
    
  • Я тогда связать различные элементы управления и что-нет к этому CollectionViewSource:

    <ListBox DockPanel.Dock="Bottom" Margin="5,5,5,5" 
        Name="familyList" 
        ItemsSource="{Binding Source={StaticResource familyCVS}, Path=., Mode=TwoWay}" 
        IsSynchronizedWithCurrentItem="True" 
        ItemTemplate="{StaticResource familyTemplate}" 
        SelectionChanged="familyList_SelectionChanged" /> 
    
  • Когда мне нужно добавлять или удалять записи/объекты, я вручную сделать это как из данных объекта модель и ObservableCollection:

    private void DeletePerson(Person person) 
    { 
        entities.DeleteObject(person); 
        entities.SaveChanges(); 
        personOC.Remove(person); 
    } 
    
  • Я обычно с использованием StackPanel и DockPanel управления для позиционирования элементов. Иногда я использую Grid, но мне сложно поддерживать: если вы хотите добавить новую строку в верхнюю часть сетки, вам нужно прикоснуться к каждому элементу управления, непосредственно размещенному в сетке, чтобы сообщить ему использовать новую строку. Uggh. (Microsoft никогда, казалось, не получала концепцию DRY.)

  • Я почти никогда не использую конструктор VS WPF для добавления, изменения или управления позициями. Дизайнер WPF, который поставляется с VS, несколько смутно полезен, чтобы увидеть, как будет выглядеть ваша форма, но даже тогда, ну, на самом деле, особенно если вы используете шаблоны данных, которые не привязаны к данным, доступным на время разработки. Если мне нужно отредактировать мой XAML, я беру его как человек и делаю это вручную.

  • Большая часть моего реального кода находится на C#, а не на XAML. Как я уже говорил, elsewhere, полностью исключая тот факт, что я еще не привык к «мышлению» в нем, XAML поражает меня как неуклюжий, уродливый язык, который также случается с плохой поддержкой дизайнера и intellisense, и что нельзя отлаживать. Uggh. Следовательно, всякий раз, когда я могу ясно видеть, как сделать что-то в коде C#, я не могу легко увидеть, как это сделать в XAML, я делаю это на C#, не извиняясь.Там было много написано о том, как хорошая практика почти никогда не использовать код на странице WPF (скажем, для обработки событий), но по крайней мере, по крайней мере, это не имеет для меня никакого смысла. Почему я должен что-то делать с уродливым, неуклюжим языком с ужасным синтаксисом, ужасно плохим редактором и практически без безопасности типа, когда я могу использовать хороший, чистый язык, такой как C#, который имеет редактор мирового класса, почти идеально intellisense и безопасность беспрецедентного типа?

Так вот, где я нахожусь. Какие-либо предложения? Я пропустил какие-то большие части этого? Что-нибудь, что я действительно должен думать о том, чтобы делать по-другому?

+0

vs2010/fw4.0: кажется, что ItemsSource должен быть привязан к familyCVS.View (вместо familyCVS) –

ответ

19

Вы должны реализовать хранилище шаблон для того чтобы отделить WPF проблемы с EF

Затем вы можете использовать дженерики, чтобы уменьшить сложность обработки EF для CollectionViewSource

Хорошо спроектированный репозиторий должен снизить уровень кода и позволить заменять любой ORM (требуется для достойного тестирование)

Некоторые идеи для этого здесь

http://blog.nicktown.info/2008/12/10/using-a-collectionviewsource-to-display-a-sorted-entitycollection.aspx

+0

Это, скорее всего, большая часть, которую мне не хватало, и это кажется ценным. Благодарю. –

+0

Ссылка в конце этого ответа теперь мертва. – Cylindric

+1

Правда, но машина Wayback [по-прежнему имеет копию] (http://web.archive.org/web/20130924230947/http://blog.nicktown.info/2008/12/10/using-a-collectionviewsource- to-display-a-sorted-entitycollection.aspx) (также подумайте о пожертвовании!). – sorrell

4

Мои рекомендации, если возможно, использовать Expression Blend для проектирования вашего интерфейса, вместо кода Behind и вместо использования дизайнера Visual Studio это сэкономит вам много времени. Также попробуйте переосмыслить использование C# вместо xaml. Xaml не так уродлив, если вы делаете это «WPF Way». Часто, когда я думаю, что проще использовать код вместо xaml, это потому, что я делаю это неправильно и мне нужно переосмыслить, как лучше работать с WPF/xaml. Xaml отлично подходит, когда вы привыкнете к нему. Я также использовал структуру сущностей, которая еще не слишком велика. Я предпочитаю NHibernate.

+0

Я попробую с XAML. Но трудно переоценить тот факт, что редакторы XAML каменного возраста (без intellisense в Blend !! ??), и что синтаксис XAML настолько ужасен и уродлив. Yeccch. –

+7

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

7

Кроме того, я не думаю, что вам нужно сделать ToList() здесь. Я полагаю, ObservableCollection() принимает IEnumerable, какие уже есть. Если вы делаете ToList, а затем передаете это ObservableCollection, то я думаю, что вы будете прокручивать все свои записи дважды.

familyOC = new ObservableCollection<Family>(families.ToList()); 

Вместо этого попробуйте это, который должен быть немного быстрее:

familyOC = new ObservableCollection<Family>(families); 
+0

Спасибо. Я добавил, что при устранении неполадок с другой ошибкой и никогда не выходил. –

5

Я понимаю, где вы и откуда. Этот article by Josh Smith помог мне изменить (или начать менять) мышление, чтобы вы могли извлечь выгоду из WPF, а не видеть его как странную, обструктивную, трудно отладочную и недружественную структуру!

1

Другой инструмент может быть BindableLINQ

Bindable LINQ представляет собой набор расширений для LINQ, добавляющие привязки данных и изменить возможности распространения на стандартный LINQ запросов

2

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

Я заметил некоторые сумасшедшие проблемы с производительностью с EF при использовании .Include. MS объясняет, почему в статье на своем веб-сайте я фактически начал перекладывать большую часть своего кода, чтобы вместо этого использовать метод .Load.

Потому что это утомительная задача, и потому что я не мог найти другой способ сделать это ... Я создал свой собственный метод под названием «IncludeByRoundTrip». Что он делает, это путь объекта и обеспечивает загрузку всего пути.Конечный результат такой же, как при использовании, однако, за кадром, я просто вызываю Load для всех свойств в графе объектов.

Он был бы похож на выполнение чего-то вроде order.Load («Customer.Address»), если такой механизм существует. В любом случае, проверьте это в своем блоге и дайте мне знать ваши выводы. Мне было бы интересно узнать, заметили ли другие замедление с помощью Include, и если у вас есть другие подходы к атаке ситуации.

С подробностями относительно моего решения: http://blog.nicktown.info/2009/07/27/method-to-load-an-entire-object-graph-using-adonet-entity-framework.aspx.

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

Смежные вопросы