1

XAML で ObjectDataProvider を使用して最初の WPF を正常に動作させました。

<ObjectDataProvider x:Key="WaitingPatientDS" ObjectType="{x:Type local:clsPatients}">
    <ObjectDataProvider.ConstructorParameters>
        <sys:Boolean>True</sys:Boolean>
    </ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>

ただし、接続エラーが発生した場合、それをトラップすることができず、プログラムは単にバーフアウトするため、これを使用するのは好きではありません。

だから、私がやろうとしてきたのは、分離コードでコレクションオブジェクトを直接インスタンス化することです...

public partial class MainWindow : Window
{
  ListBox _activeListBox;
  clsPatients oPatients;

public MainWindow()
{
  oPatients = new clsPatients(true);

...そして、私のデータバインディングでそれを次のように参照します:

<StackPanel x:Name="stkWaitingPatients" Width="300" Margin="0,0,0,-3"
   DataContext="{Binding Mode=OneWay, Source={StaticResource local:oPatients}}">

しかし、「local:oPatients was not found」というメッセージが表示されます。

それで...これを参照する際に私が間違っていること、および/または他の誰かがこのデータバインディングをどのように達成して、実際に接続エラーをトラップし、メインフォームをユーザーフレンドリーなエラーフォームに迂回させることができますか?

ありがとう!

4

2 に答える 2

3

データアクセスロジックを別のサービスに移動し、おそらく関心の分離を強制するために完全に独自のアセンブリに移動します。次に、ビューモデルに上記のサービスを使用してデータを取得し、ビューに公開します。次に、ビューはビューモデルにバインドするだけで、データがデータベースからのものかどうかは関係ありません。

関心の分離、サービスロケーター/依存性注入、およびMVVMについて読むことをお勧めします。

于 2009-08-18T14:18:18.720 に答える
3

oPatientsではないため、そのエラーが発生していますStaticResourceResourceDictionaryあなたのように定義する必要がありますObjectDataProviderが、クラスメンバーとしてはそうではありません。パブリック プロパティとして公開できます。

public clsPatients Patients { get; set; }

次に、それに直接バインドします。

<!-- MainWindowRoot is the x:Name of your Window element. -->
<StackPanel x:Name="stkWaitingPatients" Width="300" Margin="0,0,0,-3"
   DataContext="{Binding Patients, ElementName=MainWindowRoot, Mode=OneWay}">

私が愚かな間違いを犯していないと仮定すると、それはうまくいくはずです。ただし、コンストラクターにデータをロードしているため、それでも問題は解決しません。つまり、例外があるとclsPatients構築が失敗し、MainWindow構築が失敗し、ラットであるため適切に処理できません。次のスタック トレースは、正当な構築の失敗と見分けがつきません。

Kent は 100% 正しいです。データは外部プロバイダーから取得する必要があります。

リソースの制限があるかもしれませんが、階層型アーキテクチャを実装できなくても、優れた設計を確立できます。最低限、別のデータ プロバイダー クラスにデータをロードし、完全な形式のデータをウィンドウに渡すことによって、関心の分離を確立します。これにより、障害が発生した場所を分離し、コードを多少疎結合に保つことができます。

public class PatientDataProvider
{
    public PatientDataProvider(WhatItNeedsToConnect whatItNeedsToConnect) 
    { 
        // this doesn't connect because the constructor shouldn't fail because of a connection failure
    }
    public clsPatients GetPatientData(bool yesOrNo) 
    {
        // this can fail because of a connection error or some other data loading error
    }
}

そしてそれを次のように呼び出します:

PatientDataProvider provider = new PatientDataProvider(whatItNeedsToConnect);
clsPatients patients = null;
try { 
    patients = provider.GetPatientData(true); 
    MainWindow w = new MainWindow { Patients = patients; };
    w.Show();
}
catch (WhateverExceptionGetsThrownByProvider e) 
{ 
    MessageBox.Show("Could not load patients: " + e.Message);
}

また、clsPatientsが自動更新の場合は、データが変更されたときにバインディング ターゲットが更新されるように、INotifyPropertyChangedまたはINotifyCollectionChangedが適切に実装されていることを確認してください。

于 2009-08-26T07:57:49.050 に答える