如何不使用ObjectDataProvider?

时间:2009-08-18 13:16:05

标签: wpf objectdataprovider

我的第一个WPF在XAML中使用ObjectDataProvider正常工作:

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

但是,我不喜欢使用它,因为如果出现连接错误,我就无法捕获它,程序只是barfs了。

所以,我一直想做的是直接在代码隐藏中实例化集合对象...

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

但是,我得到“本地:o没有找到客户”。

那么......在引用这个时我做错了什么和/或其他人如何完成这个数据绑定以便我可以实际捕获连接错误并将主表单转移到用户友好的错误表单?

谢谢!

2 个答案:

答案 0 :(得分:2)

我将数据访问逻辑移动到一个单独的服务中,并且可能完全转移到它自己的程序集中,以强制执行您想要的关注点分离。然后我有一个视图模型使用所述服务来检索数据并为视图公开它。然后视图将简单地绑定到视图模型,而不关心数据是来自数据库还是其他任何内容。

我建议阅读关注点分离,服务定位器/依赖注入和MVVM。

答案 1 :(得分:2)

您收到该错误是因为oPatients不是StaticResource。它必须以ResourceDictionaryObjectDataProvider的方式定义,但作为类成员则不是。{1}}。您可以将其公开为公共财产:

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是自我刷新的,请确保它适当地实施INotifyPropertyChangedINotifyCollectionChanged,以便在数据更改时更新绑定目标。