【问题标题】:How NOT to use an ObjectDataProvider?如何不使用 ObjectDataProvider?
【发布时间】:2009-08-18 13:16:04
【问题描述】:

我的第一个 WPF 与 XAML 中的 ObjectDataProvider 一起正常工作:

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

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

谢谢!

【问题讨论】:

  • + 1 - 标记中的 ODS 和 SQL 参数总是让我觉得不新鲜。我已经完全用代码成功地制作了 ReportDataSourses,但从未让难以捉摸的 ODS 工作。

标签: wpf objectdataprovider


【解决方案1】:

您收到该错误是因为 oPatients 不是 StaticResource。它必须在ResourceDictionary 中定义,就像你的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 是自刷新的,请确保它适当地实现INotifyPropertyChangedINotifyCollectionChanged,以便在数据更改时更新绑定目标。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 希望我有时间兄弟,希望我有时间! ;)
    • 好吧,无论谁继承了你的代码,都会有同样的愿望;)
    猜你喜欢
    • 2010-10-12
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多