将 EF4 与 Caliburn.Micro 绑定:我应该将我的实体公开为 ViewModel 的属性吗?

发布于 2024-12-04 12:17:59 字数 2454 浏览 1 评论 0原文

对于 Caliburn.Micro,我想知道将 EF4 实体公开为 ViewModel 的属性的优缺点(讨论的技术 此处 和此处)。这使我可以避免为每个字段编写 getter 和 setter(请参阅下面的 OneCustomer)。缺点是我需要在 XAML 中编写所有绑定语句(下面的 LastName 不在 ViewModel 中,但确实需要 XAML 绑定)。如果我坚持使用每个字段的属性填充 ViewModel 的规定技术(如下面的 FirstName),我最终将不得不编写大量额外的代码,以便调用 NotifyOfProperyChange。该应用程序将相当大。 我应该将每个实体公开为 ViewModel 的属性吗?

在我的 ViewModel 中:

private MyEntities _context = new MyEntities();
private BindableCollection<Customer> _custBindableCollection; 
private Customer _oneCustomer;
private string _firstName;

public void Load() 
{
    _custBindableCollection = new BindableCollection<Customer>(_context.Customers.Where(row => row.CustomerType == "FOO"));
    AllCustomers = _custBindableCollection;
    _oneCustomer = _custBindableCollection.FirstOrDefault();
    FirstName = _oneCustomer.FirstName;
    OneCustomer = _oneCustomer;
}

public BindableCollection<Customer> AllCustomers
{ 
get { return _custBindableCollection;}
set {_custBindableCollection = value;
      NotifyOfPropertyChange(() => AllCustomers);}
}

public Customer OneCustomer
{
 get { return _oneCustomer;}
 set { _oneCustomer = value;
        NotifyOfPropertyChange(() => OneCustomer);}
} 

public string FirstName
{
    get { return _firstName; }
    set {
        _firstName = value;
        _oneCustomer.FirstName = value;
        NotifyOfPropertyChange(() => FirstName);
        NotifyOfPropertyChange(() => CanSaveChanges);
    }
}

public void SaveChanges()
{ _context.SaveChanges(); }

public bool CanSaveChanges { get { return IsValid; } }

在我的视图中:

<StackPanel>
<StackPanel Orientation="Horizontal">
    <Label Content="First Name:" />
    <TextBox x:Name="FirstName" />
</StackPanel>
<StackPanel Orientation="Horizontal" DataContext="{Binding Path=OneCustomer}">
    <Label Content="Last Name:" />
    <TextBox x:Name="LastName" Text="{Binding LastName}" />
</StackPanel>
<Button Content="Load Data" x:Name="Load" />
<Button Content="Save" x:Name="SaveChanges"  />
<DataGrid x:Name="AllCustomers" />

提前致谢。

With Caliburn.Micro I'd like to know the pros and cons of exposing an EF4 Entity as a property of the ViewModel (a technique discussed here and here). This allows me to avoid writing getters and setters for every field (see OneCustomer below). The drawback is I need to write all of the binding statements in XAML (below LastName is not in the ViewModel but does require XAML binding). If I stick to the prescribed technique of filling my ViewModel with properties for each field (as FirstName below) I'll ultimately have to write a ton of extra code just so NotifyOfProperyChange will get called. The application will be quite large. Should I expose each entity as a property of the ViewModel?

In My ViewModel:

private MyEntities _context = new MyEntities();
private BindableCollection<Customer> _custBindableCollection; 
private Customer _oneCustomer;
private string _firstName;

public void Load() 
{
    _custBindableCollection = new BindableCollection<Customer>(_context.Customers.Where(row => row.CustomerType == "FOO"));
    AllCustomers = _custBindableCollection;
    _oneCustomer = _custBindableCollection.FirstOrDefault();
    FirstName = _oneCustomer.FirstName;
    OneCustomer = _oneCustomer;
}

public BindableCollection<Customer> AllCustomers
{ 
get { return _custBindableCollection;}
set {_custBindableCollection = value;
      NotifyOfPropertyChange(() => AllCustomers);}
}

public Customer OneCustomer
{
 get { return _oneCustomer;}
 set { _oneCustomer = value;
        NotifyOfPropertyChange(() => OneCustomer);}
} 

public string FirstName
{
    get { return _firstName; }
    set {
        _firstName = value;
        _oneCustomer.FirstName = value;
        NotifyOfPropertyChange(() => FirstName);
        NotifyOfPropertyChange(() => CanSaveChanges);
    }
}

public void SaveChanges()
{ _context.SaveChanges(); }

public bool CanSaveChanges { get { return IsValid; } }

In My View:

<StackPanel>
<StackPanel Orientation="Horizontal">
    <Label Content="First Name:" />
    <TextBox x:Name="FirstName" />
</StackPanel>
<StackPanel Orientation="Horizontal" DataContext="{Binding Path=OneCustomer}">
    <Label Content="Last Name:" />
    <TextBox x:Name="LastName" Text="{Binding LastName}" />
</StackPanel>
<Button Content="Load Data" x:Name="Load" />
<Button Content="Save" x:Name="SaveChanges"  />
<DataGrid x:Name="AllCustomers" />

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酒浓于脸红 2024-12-11 12:17:59

对于 Caliburn.Micro,我想了解暴露的优点和缺点
EF4 实体作为 ViewModel 的属性(此处讨论的技术
和这里)。

我不确定优点/缺点,但我可以告诉你这两种方法都被使用。例如,以一个简单的登录屏幕为例,通常我将 UserName 放在 ViewModel 上的一个属性,但在表单更复杂的情况下,ViewModel 可以聚合其他 ViewModel(显示模型)来完成相同的事情。 CM 不会影响优缺点,更多的是关于 MVVM 的优缺点是什么。 CM 将帮助您绑定两者。

  • 如果 ViewModel 上有一个名为 CustomerName 的属性,只需命名
    文本框 x:name="CustomerName"。
  • 如果 ViewModel 上有一个属于类实例的属性
    名为 Customer,将文本框命名为 x:name="Customer_Name" 并再次命名为 CM
    将处理绑定。

因此,从上面的 xaml 来看:

 <TextBox x:Name="LastName" Text="{Binding LastName}" />

您不需要在 StackPanel 上设置 DataContext。相反:

<TextBox x:Name="OneCustomer_LastName"/>

可以更轻松地绑定到 DataForms 和 DataGrid 的一件事是遵循一种方法,为数据在屏幕上的表示方式创建显示模型。

这是我的观点,但我个人永远不会直接绑定到 EF/Linq 实体。相反,我将创建一个显示模型来表示该实体以及我希望其显示的方式,并使用 AutoMapper 进行映射。在很多情况下,它是一对一的映射。这可能看起来是浪费时间,但它具有优势,特别是对于更复杂的数据模型布局,显示模型允许您展平数据以用于显示目的,并属性属性以进行验证,而无需将它们粘贴在数据模型实体上。有关更多信息,请参阅ASP.NET MVC in Action一书中的相关章节。

With Caliburn.Micro I'd like to know the pros and cons of exposing an
EF4 Entity as a property of the ViewModel (a technique discussed here
and here).

I'm not sure of the pros/cons but I can tell you both methods are used. For example take a simple Login Screen, generally I put the UserName a property on the ViewModel but in cases where the form is more complex the ViewModel can aggregate other ViewModels(display models) to accomplish the same thing. CM doesn't effect the pros/cons much as its more a question of With MVVM, what are the pros/cons. CM is going to help you in binding to both.

  • If you have a property on the ViewModel called CustomerName, simply name
    a TextBox x:name="CustomerName".
  • If you have a property on the ViewModel that is a instance of a class
    called Customer, name the TextBox x:name="Customer_Name" and again, CM
    will handle the bindings.

So from your xaml above:

 <TextBox x:Name="LastName" Text="{Binding LastName}" />

you don't need to set the DataContext on the StackPanel. Instead:

<TextBox x:Name="OneCustomer_LastName"/>

One thing that can make binding to DataForms and DataGrids easier is following a method where you create display models for the way the data is represented on the screen.

This is my opinion but I personally will never bind directly to an EF/Linq entity. Instead I'll create a display model to represent that entity and how I want it displayed and use AutoMapper to do the mappings. In a lot of cases its a one to one mapping. This might seem like a waste of time but it has advantages especially with more complex data model layouts, display models allow you to flatten the data for display purposes and attribute up properties for validation without sticking them on the data model entity. For more on that check out the chapter on it in ASP.NET MVC in Action book.

无尽的现实 2024-12-11 12:17:59

由于公开实体还有其他优点(例如,通过属性进行验证),因此我个人会直接公开它们。

但我想正确的答案是“这取决于”,因为也总是存在一些缺点(主要是架构上的)。

顺便说一句:您可以调用文本框“OneCustomer_LastName”,CM 的约定绑定将起作用。

Since there are other advantages of exposing entities (for example, validation through attributes), I personally do expose them directly.

But I guess the proper answer would be "it depends" as there are always some drawbacks too (mainly architectural).

BTW: you can call the textbox "OneCustomer_LastName" and C.M's convention binding will work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文