WPF:在UserControl的构造函数中加载数据会破坏Designer

时间:2009-02-20 19:40:21

标签: c# wpf constructor user-controls

我有一个带有usercontrol的主窗口。在usercontrol的默认构造函数中添加代码时,设计器停止显示主窗口。它给出了一个信息:

  

加载问题

     

该文档包含在加载设计器之前必须修复的错误   修复错误后重新加载设计器。

     

重新加载设计师

为什么会这样?

这是我在构造函数中的代码:

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

    listShow.ItemsSource = list;
}

如果我不能使用构造函数来填充gui数据,我应该在什么时候进行呢?用绑定做这个会更好吗?任何吸烟怎么样?

2 个答案:

答案 0 :(得分:13)

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 :(得分:1)

我个人会为我的数据源使用一个可观察的集合。有很多例子,但基本上你的代码看起来像这样。我还没有测试过这段代码。如果您有任何问题,请添加一些评论。

这里有两个要点。一,除非你没有处于设计模式,否则不要加载任何数据,(如果你需要设计支持,你可以把if和else语句加载存根POCO数据)。第二,你应该在一个单独的线程上加载你的数据然后你的UI线程。

更新

代码有几处更新。我将(新线程)更改为使用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);
        }
    }
}