2009-07-08 12 views
3

これはかなり簡単なはずですが、重大なループのためにVS2008がスローされます。ユーザーコントロールのDataContextをコードビハインドから設定する

私はMVVMを使ってWPFを試しています。私は約15年間開発していましたが、初心者でもありました。 sci。度。現在のクライアントでは、VB.Netを使用する必要があります。

私は自分自身の変数の名前を変更し、以下のコードでいくつかの注意散漫を取り除いたので、100%構文的に完璧でないなら、私を許してください!質問を理解するためにコードを実際には必要としないかもしれませんが、それが役に立つ場合は含めます。

<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> 

は、私はまた、データグリッドで構成され、ユーザーコントロールと呼ばれるデータビューを持っている:

私は非常に単純なMainView.xamlファイルを持っている

<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 

T

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でそれをインスタンス化した場合さて、このユーザーコントロールがうまく動作します。この(多くはViewModelBaseではありません)のように見える彼は、DataViewのためのモデルを表示します。私はコードを実行すると、グリッドが表示され、ちょうど良い値を入力します。

グリッドはデータのロードに時間がかかり、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割り当てになっているようです。私がそれをコメントアウトすると、アプリケーションは期待どおりに動作します(もちろん、グリッドには何も表示されません)。私は(基本的にレベルをDataEntryのコンストラクタコードを上に移動)のButton1 Clickにこのコードブロックを移動した場合

、アプリはまだ失敗:

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

私は困惑します。誰かが私に間違ってやっていることについてのヒントを教えてもらえますか?また、私のアプリがどんな無限ループになっているのかをデバッグする方法さえありますか?

多くのありがとうございます。

+0

グリッドには多くのデータがありますか?ロックアップ後にグリッドが表示され、表示されますか?(仮想化から)スクロールする間に遅延がありますか? –

+0

グリッドは実際には約4000レコードしかありませんが、ロードに約5〜6秒かかるので、宣言的にロードする必要はありません。ユーザーがデータのロードを待つ必要があり、 グリッドがロックアップ後に終了して表示されないデバッグを停止する必要があるこの問題は、Button1_Click内からDataViewをインスタンス化しようとすると発生します。 XAML内でDataViewを作成すると、正常に動作します(ただし、データソースを読み込んでデータグリッドを作成するには約5〜6秒かかります)。 – TimH

答えて

1

私は最終的にUserControl(XAMLまたはコードのいずれか)のインスタンス化中にUserControlセットでDataContextを取得しようとしました。今すぐデータをロードし、UserControlのDataContextをUserControlのイベントに設定します(IsVisibleChanged、私は信じています)。 XAMLでUserControlをインスタンス化すると、VisibilityがHiddenに設定されます。 Button1をクリックすると、UserControlのVisibilityをVisibleに設定します。したがって、UserControlが表示され、データが読み込まれ、DataContextが設定されます。仕事に見えるだけでなく、非常にクルージシと思われる。 :-(助けてくれてありがとう)

-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

助けてくれてありがとう、ガード。残念ながら、それは単に人口を埋めるのに時間がかかるという問題ではありません。それは約4000レコードだけです。上記のコードを実行すると、VS2008は無限に回転し、数百MBのRAMを消費し、CPUをロードします。 しかし、私はあなたが提案するデリゲートアプローチを試み、報告する予定です。 – TimH

+0

これは動作しません。 DataViewは2番目のスレッドが所有しており、UIスレッドに追加することはできません。私は、何も成功せずに、それをマーシャリングするいくつかの方法を試しました。最後の手段として、XamlWriterとXamlReaderを使用してXAMLを取得して最初のスレッドに追加しようとしましたが、XamlReaderはXamlWriterが作成したルート要素が存在しないことに不満を抱いています。 実行時にユーザーコントロールをインスタンス化するのが難しいとは思えません。 – TimH

+0

コンストラクタを使用してデータをロードする代わりに、別個のメソッドを使用してデータをロードし、別のスレッドでデータを実行し、メインスレッドの可視コントロールにデータをロードすることができます。コンストラクタで両方を実行すると、そのことができなくなります。 –

1

あなたの問題の根本的な原因は、あなたがロードしているデータの生の量またはあなたがそのデータをロードする方法で、いくつかの非効率性のいずれかであるように思われます。あなたがアプリケーションロックアップを見ている理由は、データをロードするときにUIスレッドをロックしているということです。

私はあなたの最初のケースでは、データ読み込みがデータを読み込むために別のスレッドに読み込まれていないと思います。 2番目の例では、UIスレッドのコントロールをインスタンス化しています。その結果、すべてのコンストラクタとロードロジックが現在のスレッド(UIスレッド)で実行されます。この作業を別のスレッドにオフロードすると、最初の例と同様の結果が表示されます。

+0

XAMLからDataViewをインスタンス化すると、約5秒で読み込まれます(目的には長すぎますがまだ、それは悪くない)。 DataViewをコードからインスタンス化すると、VS2008は正常にロードされず、約500MBのRAMが消費され、数分後には何もしないので、デバッグを停止する必要があります。だから、私は「遅い」問題をただ見ているとは思わない。私は "VS2008は間違いなく無限ループに戻り、決して戻ってこない"と思っています。 2番目のスレッドを使用するとまだ助けてくれると思いますか?私は本当にこのようにUIをねじ込むことができますか? – TimH

+0

ありがとうございました。 2番目のスレッドにデータを読み込んでも機能しません - 「これは動作しません」から始まるGuardへの私のコメントを参照してください。 – TimH

関連する問題