2009-07-08 28 views
3

这应该很简单,但它会引发VS2008严重的循环。从代码隐藏设置用户控件的DataContext

我正在尝试WPF与MVVM,并且我是一个总新手,虽然我已经开发了大约15年,并有一个comp。 SCI。度。在当前的客户端,我需要使用VB.Net。

我已经重新命名了我自己的变量,并删除了下面代码中的一些分心,所以请原谅我,如果它不是100%的句法完美!你可能不需要代码来理解这个问题,但我会加入它以防万一。

我有一个非常简单的MainView.xaml文件:

<Window x:Class="MyApp.Views.MainView" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Main Window" Height="400" Width="800" Name="MainWindow"> 

<Button Name="Button1">Show Grid</Button> 
<StackPanel Name="teststack" Visibility="Hidden"/> 

</Window> 

我也有一个用户控件称为数据视图,它由一个DataGrid的:

<UserControl x:Class="MyApp.Views.DataView" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:WpfToolkit="http://schemas.microsoft.com/wpf/2008/toolkit" > 
<Grid> 
    <WpfToolkit:DataGrid 
     ItemsSource="{Binding Path=Entries}" SelectionMode="Extended"> 
    </WpfToolkit:DataGrid> 
</Grid> 
</UserControl> 

的数据视图构造用户控件设置了DataContext绑定到视图模型,如下所示:

Partial Public Class DataView 

    Dim dataViewModel As ViewModels.DataViewModel 

    Public Sub New() 
     InitializeComponent() 

     dataViewModel = New ViewModels.DataViewModel 
     dataViewModel.LoadDataEntries() 
     DataContext = dataViewModel 
    End Sub 

End Class 

T他查看模型数据视图看起来像这样(没有太多的ViewModelBase):

Public Class DataViewModel 
    Inherits ViewModelBase 

Public Sub New() 
End Sub 

Private _entries As ObservableCollection(Of DataEntryViewModel) = New ObservableCollection(Of DataEntryViewModel) 
Public ReadOnly Property Entries() As ObservableCollection(Of DataEntryViewModel) 
    Get 
     Return _entries 
    End Get 
End Property 

Public Sub LoadDataEntries() 

    Dim dataEntryList As List(Of DataEntry) = DataEntry.LoadDataEntries() 
    For Each dataentry As Models.DataEntry In dataEntryList 
     _entries.Add(New DataEntryViewModel(dataentry)) 
    Next 

    End Sub 
End Class 

现在,如果我在XAML实例化它这个用户控件的工作就好了。当我运行代码时,网格显示并填充它就好了。

但是,网格需要很长时间来加载它的数据,我想在按钮点击之后以编程方式创建此用户控件,而不是在XAML中声明性地实例化网格。我想实例化用户控件,然后将其插入作为StackPanel控件的子:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click 

    Dim dataView As New DataView 
    teststack.Children.Add(dataView) 

End Sub 

当我做到这一点,只要Button1_Click的结束,我的应用程序锁定,该吃的RAM,并点击了CPU约50%。

我没有正确实例化我的UserControl?这一切似乎都归结于DataEntry构造函数中的DataContext赋值。如果我评论说,应用程序按预期工作(当然,没有任何网格)。

如果我提出这个代码块成的button1_Click(基本上是移动的DataEntry的构造函数的代码了一个级别),应用程序仍然失败:

dataViewModel = New ViewModels.DataViewModel 
dataViewModel.LoadDataEntries() 
dataView.DataContext = dataViewModel 

我难倒。任何人都可以给我一些提示,说明我可能会做错什么,甚至是如何调试我的应用程序陷入的无限循环?

非常感谢。

+0

网格中是否有大量数据?网格在锁定后是否完成填充和显示?滚动(从虚拟化)时是否有任何延迟? – 2009-07-08 20:26:29

+0

网格实际上只有大约4000条记录,但需要大约5或6秒才能加载,所以我不想声明式地加载它,因为用户必须等待数据加载,并且可能永远不会看它(因为他们只会看到它,如果他们只看到它,如果他们点击某个按钮) 网格没有完成,并显示锁定后,我不得不停止调试只有当我尝试实例化从Button1_Click内的DataView如果我在XAML中创建DataView,它工作正常(尽管如此,读取数据源并填充数据网格大约需要5或6秒钟)。 – TimH 2009-07-09 02:27:33

回答

1

我最终放弃了尝试在UserControl实例化(在XAML或代码中)时在UserControl集上获取DataContext。现在我加载数据并将UserControl的DataContext设置在UserControl(IsVisibleChanged,我相信)中的一个事件中。当我在XAML中实例化UserControl时,我将它的Visibility设置为Hidden。当单击Button1时,我将UserControl的可见性设置为可见。所以UserControl弹出视图,并加载它的数据并设置DataContext。似乎工作,但也似乎很kludgey。 :-(感谢您的帮助,伙计们!

-1

如果这只是你的控制花费很长的时间来填充数据的问题,您应该填充在另一个线程控制,然后通过委托添加:

因为我不是在写VB太好。 NET,但这里的C#相当于:

private void Button1_Click(Object sender, RoutedEventArgs e) 
{ 
    Thread thr = new Thread(delegate() 
    { 
    DataView dataView = new DataView(); 

    this.Dispatcher.BeginInvoke((Action) delegate() 
    { 
     teststack.Children.Add(dataView); 
    }); 
    }); 
    thr.Start(); 
} 
+0

感谢您的帮助,Guard。不幸的是,这不仅仅是需要花费很长时间来填充的问题。它只有大约4000条记录,当我运行上面的代码时,VS2008不停地旋转,耗用数百MB的RAM,并加载CPU。 但是,我会尝试您建议的委托方式,并将回报。 – TimH 2009-07-09 02:23:17

1

您的问题的根源似乎是无论你在加载数据的原始金额或你如何加载数据的一些低效率。话虽如此,你看到应用程序锁定的原因是你在加载数据时锁定了UI线程。

我相信在你的第一种情况下,数据加载已被卸载到另一个线程来加载数据。在第二个示例中,您正在实例化UI线程上的控件,因此所有构造函数和加载逻辑都在当前线程(UI线程)上执行。如果将此工作卸载到另一个线程上,则应该看到与第一个示例类似的结果。