2010-07-19 3 views
0

고객과 연락처가 다 대다 관계 인 엔티티 프레임 워크가 있습니다.RIA 도메인 서비스를 통해 xaml에서 데이터 바인딩 문제가 발생했습니다.

도메인 서비스 클래스를 생성하고 다음 메소드를 수동으로 추가했습니다.

public Customer GetCustomerById(int Id) 
{ 
    return this.ObjectContext.Customer.Include("Contacts").SingleOrDefault(s => s.Id == Id); 
} 

이제 고객 세부 정보와 해당 고객과 관련된 연락처 목록을 보여주는 페이지를 만들고 싶습니다.

페이지로 전달되는 Id 매개 변수를 읽으려면 customerdetails.xaml의 코드 숨김에서 다음을 수행해야합니다.

public int CustomerId 
{ 
    get { return (int)this.GetValue(CustomerIdProperty); } 
    set { this.SetValue(CustomerIdProperty, value); } 
} 

public static DependencyProperty CustomerIdProperty = DependencyProperty.Register("CustomerId", typeof(int), typeof(CustomerDetails), new PropertyMetadata(0)); 

// Executes when the user navigates to this page. 
protected override void OnNavigatedTo(NavigationEventArgs e) 
{ 
    if (this.NavigationContext.QueryString.ContainsKey("Id")) 
    { 
     CustomerId = Convert.ToInt32(this.NavigationContext.QueryString["Id"]); 
    } 
} 

나는 페이지에 대해 다음 XAML을 사용 :이 작업을 수행 할 때

<Grid x:Name="LayoutRoot" DataContext="{Binding ElementName=customerByIdSource, Path=Data}"> 
    <riaControls:DomainDataSource Name="customerByIdSource" AutoLoad="True" QueryName="GetCustomerById"> 
     <riaControls:DomainDataSource.QueryParameters> 
      <riaControls:Parameter ParameterName="Id" Value="{Binding ElementName=CustomerDetailsPage, Path=CustomerId}" /> 
     </riaControls:DomainDataSource.QueryParameters> 
     <riaControls:DomainDataSource.DomainContext> 
      <sprint:Customer2DomainContext/> 
     </riaControls:DomainDataSource.DomainContext> 
    </riaControls:DomainDataSource> 
    <StackPanel x:Name="CustomerInfo" Orientation="Vertical"> 
     <StackPanel Orientation="Horizontal" Margin="3,3,3,3"> 
      <TextBlock Text="Id"/> 
      <TextBox x:Name="idTextBox" Text="{Binding Id}" Width="160"/> 
     </StackPanel> 
     <StackPanel Orientation="Horizontal" Margin="3,3,3,3"> 
      <TextBlock Text="Name"/> 
      <TextBox x:Name="nameTextBox" Text="{Binding Name}" Width="160"/> 
     </StackPanel> 

     <ListBox ItemsSource="{Binding Contact}" DisplayMemberPath="FullName" Height="100" /> 
    </StackPanel> 
</Grid> 

는 텍스트 상자 멋지게 데이터 바인딩을 통해 채워하지만, 목록 상자는 비어 있습니다.

두 질문 : 나는이 (가) 등록 GUI를 통해 바인딩을 지정 때

  1. 내가 어떻게 든 GetCustomerById 쿼리의 반환 유형을 지정할 수 있습니다 은 그래서 이름을 볼 수 있습니까?

  2. 무엇을하고 있습니까? 여기에 잘못 되었나요? 내 ListBox 이 채워지지 않는 이유는 무엇입니까? 이 올바른 방법에 대한 건가요 또는 코드 숨김 목록 상자에 대한 데이터 바인딩을 설정해야합니까? 그렇다면 어떻게? 프로그래밍 방식으로 도메인 데이터 소스를 통해 연락처 속성에 액세스하는 방법을 찾지 못했습니다.

    협회 속성 Contacts가 생성되는 도메인 서비스 개체 유형에 포함되지 않습니다 :

은 내가 내 질문 2에 대한 답변을 발견 실버 엔티티 프레임 워크 4

답변

0

를 사용합니다. 포함될 수 있도록 [Include] 속성을 지정해야합니다. 그러나 include 특성에는 [Association] 특성이 필요합니다.속성은 다 대다 관계이므로 연관 속성은 사용자가 외래 키를 지정하도록 요구하기 때문에 지정할 수 없습니다.

해결 방법은 데이터 전송 개체 (DTO)에 개체를 래핑하는 것입니다. 이미 내 질문에있는 코드를 크게 변경하지 않아도됩니다. 변경된 유일한 것은 도메인 서비스 클래스에서 고객의 검색했다 :

솔루션의 주요 부분은 기본 엔티티 프레임 워크 모델에 DTO 클래스를 추가 변경했다
public CustomerDTO GetCustomerById(int Id) 
{ 
    return new CustomerDTO(this.ObjectContext.Customers.Include("Contacts").SingleOrDefault(s => s.Id == Id)); 
} 

:

[DataContract] 
public partial class CustomerDTO : Customer 
{ 

    public CustomerDTO() { } 
    public CustomerDTO(Customer customer) 
    { 
     if (customer != null) 
     { 
      Id = customer.Id; 
      Name = customer.Name; 
      CustomerContacts = new Collection<ContactDTO>(); 
      foreach (Contact d in customer.Contacts) 
      { 
       CustomerContacts.Add(new ContactDTO(d, Id)); 
      } 
     } 
    } 

    [DataMember] 
    [Include] 
    [Association("CustomerContacts", "CustomerId", "Id")] 
    public Collection<ContactDTO> CustomerContacts 
    { 
     get; 
     set; 
    } 
} 

[KnownType(typeof(CustomerDTO))] 
public partial class Customer 
{ 
} 

[DataContract()] 
public partial class ContactDTO : Contact 
{ 
    public ContactDTO() { } 
    public ContactDTO(Contact contact, int customerId) 
    { 
     if (contact != null) 
     { 
      Id = contact.Id; 
      FullName = contact.FullName; 
      CustomerId = customerId; 
     } 
    } 

    [DataMember] 
    public int CustomerId { get; set; } 
} 

[KnownType(typeof(ContactDTO))] 
public partial class Contact 
{ 
} 

이 기능을 사용하려면 KnownType, DataMemberDataContract 속성이 필요합니다. 실제로 객체를 인스턴스화하려면 생성자에서 속성을 조금 더 복사해야합니다. 명백한 복사본을 작성하는 코드를 피하는 쉬운 방법이 있습니까? 나는 제안을 위해 열려 있습니다.

나는 여분의 클래스의 도입을 피하려고했지만 외래 키 사양이 필요한 Association 속성이 필요하기 때문에 다 대다 관계의 경우에는 피할 수없는 것처럼 보입니다. 내 경우에 Contact.CustomerId.

아무도 더 잘 할 수 있습니까 (== 적은 코딩)?

관련 문제