WPF:在 UserControl 的构造函数中加载数据会破坏设计器
Posted
技术标签:
【中文标题】WPF:在 UserControl 的构造函数中加载数据会破坏设计器【英文标题】:WPF: Loading data in the constructor of a UserControl breaks the Designer 【发布时间】:2010-10-08 22:17:28 【问题描述】:我有一个带有用户控件的主窗口。在用户控件的默认构造函数中添加代码时,设计器停止显示主窗口。它给出了一条信息:
加载问题
文档包含在加载设计器之前必须修复的错误。 修复错误后重新加载设计器。
重新加载设计器
这是为什么?
这是我在构造函数中的代码:
using (var context = new Data.TVShowDataContext())
var list = from show in context.Shows
select show;
listShow.ItemsSource = list;
如果我不能使用构造函数来填充 gui 数据,我应该什么时候做呢?用绑定来做这件事会更好吗?有什么建议吗?
【问题讨论】:
错误列表显示此消息:“无法创建 BrowseShow 类型的实例”。设计区域显示问题中引用的消息。 我测试并更新了我的答案 【参考方案1】: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;
【讨论】:
我将其标记为答案,尽管我现在已经学会了 MVVM 的乐趣并且我的控件中不再有任何代码:-)【参考方案2】:我个人会为我的数据源使用可观察的集合。那里有很多例子,但基本上你的代码看起来像这样。我没有测试过这段代码。如果有任何问题,请添加一些 cmets。
这里有两个要点。一,除非您不在设计模式下,否则不要加载任何数据(如果您需要设计支持,您可以放置和 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);
【讨论】:
简单的推论是,如果您必须加载数据,请执行以下操作: 1) 通过检查“DesignMode”的默认构造函数或; 2) 拥有一个用于“实时”数据的更复杂的构造函数和一个不进行数据库调用的默认构造函数。 时间太少,要学的东西太多... :-) 我对新的 Thread(....) 行有疑问。 “错误 2 委托 'System.Threading.ParameterizedThreadStart' 不采用 '0' 参数”你有解决方案吗? 我对在默认构造函数中启动一个新线程持谨慎态度。你能把它移到更“复杂”的构造函数上吗?以上是关于WPF:在 UserControl 的构造函数中加载数据会破坏设计器的主要内容,如果未能解决你的问题,请参考以下文章