3

这应该很容易,但它会引发 VS2008 的严重循环。

我正在尝试使用 MVVM 的 WPF,尽管我已经开发了大约 15 年,并且有一个比较,但我还是一个新手。科学。程度。在当前客户端,我需要使用 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>

我还有一个名为 DataView 的 UserControl,它由一个 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>

DataView 用户控件的构造函数通过将 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

DataView 的视图模型如下所示(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 中实例化它,这个 UserControl 就可以正常工作。当我运行代码时,网格会显示出来并很好地填充它。

但是,网格需要很长时间才能加载其数据,我想在单击按钮后以编程方式创建此用户控件,而不是在 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,并占用大约 50% 的 CPU。

我没有正确实例化我的 UserControl 吗?这一切似乎都归结为 DataEntry 构造函数中的 DataContext 分配。如果我将其注释掉,则该应用程序将按预期工作(当然,网格中没有任何内容)。

如果我将此代码块移动到 Button1_Click (基本上将 DataEntry 的构造函数代码向上移动一个级别),应用程序仍然失败:

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

我难住了。谁能给我一些关于我可能做错了什么的提示,或者甚至如何调试我的应用程序正在进入的无限循环?

非常感谢。

4

3 回答 3

1

问题的根本原因似乎是您正在加载的原始数据量或加载该数据的方式效率低下。话虽如此,您看到应用程序锁定的原因是您在加载数据时锁定了 UI 线程。

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

于 2009-07-09T02:12:53.057 回答
1

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

于 2009-07-10T00:55:23.160 回答
-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();
}
于 2009-07-08T21:20:49.297 回答