WPF: загрузка данных в конструктор UserControl нарушает конструктор - PullRequest
7 голосов
/ 20 февраля 2009

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

Проблема загрузки

Документ содержит ошибки, которые должны быть исправлены до загрузки конструктора.
Перезагрузите конструктор после исправления ошибок.

Перезагрузить конструктор

Почему это?

Это код, который у меня есть в конструкторе:

using (var context = new Data.TVShowDataContext())
{
    var list = from show in context.Shows
               select show;

    listShow.ItemsSource = list;
}

Если я не могу использовать конструктор для заполнения графического интерфейса данными, когда мне еще это делать? Было бы лучше сделать это с привязкой? Любые предложения, как?

Ответы [ 2 ]

13 голосов
/ 20 февраля 2009

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

if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
  using (var context = new Data.TVShowDataContext())
  {
    var list = from show in context.Shows
               select show;

    listShow.ItemsSource = list;
  }    
}
1 голос
/ 20 февраля 2009

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

Здесь есть два основных момента. Во-первых, не загружайте никакие данные, если только вы не в режиме разработки (вы можете поместить оператор else, а затем загрузить данные заглушки POCO, если вам нужна поддержка разработки). Во-вторых, вы должны загрузить свои данные в отдельном потоке, а затем в потоке пользовательского интерфейса.

Обновлено

Было несколько обновлений кода. Я изменил (новый поток) на использование QueueUserWorkItem, я изменил метод AddItems, потому что ObservableCollection не поддерживает AddRange, и я изменил написание на IEnumerable

public class TvShowsDataSource
{
    public ObservableCollection<Show> Shows { get; set; }

    private void AddItems(IEnumerable<Show> shows)
    {
            foreach(var show in shows)
                   Shows.Add(show);
    }

    public void LoadShowsAsync(Dispatcher dispatcher)
    {
            ThreadPool.QueueUserWorkItem((state) =>
                   LoadShows(dispatcher));
    }

    private void LoadShows(Dispatcher dispatcher)
    {
        if (dispatcher == null)
            throw new ArgumentNullException("dispatcher");

        using (var context = new Data.TVShowDataContext())
        {
            var list = from show in context.Shows
                       select show;

            dispatcher.Invoke(AddItems(list));
        }
    }
}

public class UserControl1
{
    private readonly TvShowsDataSource tvShowsDataSource;

    public UserControl1() : this(new TvShowsDataSource()) {}

    public UserControl1(TvShowsDataSource tvShowsDataSource )
    {
        InitializeComponent();
        this.tvShowsDataSource = tvShowsDataSource;
        listShow.ItemsSource = tvShowsDataSource.Shows;
        this.Loaded += UserControl1_Loaded;
    }

    public void UserControl1_Loaded(object sender, RoutedEventArgs e)
    {
        if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
        {
            tvShowsDataSource.LoadShowsAsync(this.Dispatcher);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...