2013-11-18 2 views
0

Я играю с WPF и LINQ и придерживаюсь следующего пункта, не имея понятия о том, как показать одну запись, все примеры, которые я нашел, показывают, как представить список, но не один запись.
Я подготовил пользовательский элемент управления, который должен показать одну запись в то время, в моем примере клиента, показывая его Id, имя и фамилия, здесь:Binding single record

<UserControl x:Class="SportsClubsManagement.CustomersManagement.CustomerData" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="500"> 
    <Grid DataContext="Binding Customer"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="*" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition /> 
      <ColumnDefinition /> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 
     <Label Grid.Row="0" Grid.Column="0" Content="Id" Height="30" Width="70" /> 
     <TextBox Grid.Row="0" Grid.Column="1" Height="20" Width="70" Name="Id" Text="{Binding Path=Id}" /> 
     <Label Grid.Row="1" Grid.Column="0" Content="Given Name" Height="30" Width="70" /> 
     <TextBox Grid.Row="1" Grid.Column="1" Height="20" Width="70" Name="GivenName" Text="{Binding Path=GivenName}" /> 
     <Label Grid.Row="1" Grid.Column="2" Content="Surname" Height="30" Width="70" /> 
     <TextBox Grid.Row="1" Grid.Column="3" Height="20" Width="70" Name="Surname" Text="{Binding Path=Surname}" /> 
     <Button Grid.Row="2" Grid.Column="0" Content="New record" /> 
     <Button Grid.Row="2" Grid.Column="3" Content="Next record" /> 
     <Button Grid.Row="2" Grid.Column="2" Content="Prev record" /> 
    </Grid> 
</UserControl> 

Я также создал таблицу с несколькими записями и классом для представления клиента, который также реализует INotifyPropertyChanged.

[Table(Name = "Customers")] 
    public class Customer : INotifyPropertyChanged 
    { 
     #region Fields 

     private String id; 

     private String givenName; 
     private String surname; 

     #endregion 
     #region Properties 

     [Column(IsPrimaryKey=true, Storage="id", Name="Id")] 
     public String Id 
     { 
      get { return this.id; } 
     } 

     [Column(Storage="givenName", Name="GivenName")] 
     public String GivenName 
     { 
      get { return this.givenName; } 
      set { 
       if (this.givenName != value) 
       { 
        this.givenName = value; 
        this.OnPropertyChanged("GivenName"); 
       } 
      } 
     } 

     [Column(Storage="surname", Name="Surname")] 
     public String Surname 
     { 
      get { return this.surname; } 
      set { 
       if (this.surname != value) 
       { 
        this.surname = value; 
        this.OnPropertyChanged("Surname"); 
       } 
      } 
     } 

     #endregion 

     #region INotifyPropertyChanged Members" 

     public event PropertyChangedEventHandler PropertyChanged; 

     public void OnPropertyChanged(String name) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(name)); 
      } 
     } 

     #endregion 
    } 

Теперь в коде позади пользовательского элемент управления У меня есть действительно простой код, который подключение к БД и получает запись:

public partial class CustomerData : UserControl 
    { 

     private int curCustSeqNum; 

     private Data.Customer customer; 

     public Data.Customer Customer 
     { 
      get 
      { 
       return customer; 
      } 
      set 
      { 
       this.customer = value; 
      } 
     } 

     private IQueryable<Data.Customer> custQuery; 

     public CustomerData() 
     { 
      InitializeComponent(); 

      DataContext db = new DataContext(@"server=WIN-EL78137MUMS\SQLEXPRESS;database=PlayGround;integrated security=SSPI"); 

      // Get a typed table to run queries. 
      Table<Data.Customer> Customers = db.GetTable<Data.Customer>(); 
      //db.Log = Console.Out; 

      custQuery = 
       from cust in Customers 
       orderby cust.Id 
       select cust; 

      curCustSeqNum = 0; 

      Customer = custQuery.Skip(curCustSeqNum).Take(1).First(); 

     } 
    } 

Но как я могу связать с текстовыми полями для текущего выбранного Клиента ? Вы можете увидеть мое последнее предположение после определения ресурсов и т. Д. Но каждый раз, когда я что-то пропускаю. Я хотел бы знать, как я могу добиться этого в XAML и в коде. В основном после этого я смог бы использовать curCustSeqNum, чтобы перейти к следующей записи.

ответ

1

CustomerData не реализует INotifyPropertyChanged поэтому, когда вы устанавливаете Customer в конструкторе, у xaml нет Idea, он изменился.

Пример:

public partial class CustomerData : UserControl, INotifyPropertyChanged 
{ 
    private int curCustSeqNum; 
    private Data.Customer customer; 
    private IQueryable<Data.Customer> custQuery; 

    public Data.Customer Customer 
    { 
     get { return customer; } 
     set { this.customer = value; OnPropertyChanged("Customer"); } 
    } 

    public CustomerData() 
    { 
     InitializeComponent(); 

     // set the datacontext 
     DataContext = this; 

     ................ 

     Customer = custQuery.Skip(curCustSeqNum).Take(1).First(); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    public void OnPropertyChanged(String name) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 

также упоминается кем-то еще, вы DataContext привязки на сетке является недействительным

<Grid DataContext="Binding Customer"> 

должен быть

<Grid DataContext="{Binding Customer}"> 
+0

Кажется, что это работает, но только одним способом. Что я пропустил, что не позволяет ему писать изменения? Другой вопрос. Должен ли я удалить реализацию класса INotifyPropertyChanged из класса Customer, это кажется бесполезным? И последнее на данный момент - Какова цель «DataContext = this»; вы добавили в конструктор? без него это не сработает, насколько я понимаю, добавляет DataContext в пользовательский элемент управления, указав, что он должен выглядеть локально, но мы также указали DataContext для Grid, и это должно переписать DataContext родителя, не так ли? И огромное спасибо! – Jyrkka

+1

Вы должны сохранить 'INotifyPropertyChanged' в классе' Customer', так как это будет необходимо для обновления пользовательского интерфейса, если какое-либо из значений изменится. Набор 'DataContext' в конструкторе сообщает' UserControl' искать локально таким образом, чтобы вы могли получить доступ свойство 'Customer',' DataContext' в 'Grid' устанавливает свой контекст для объекта Customer, это означает, что все, что на' Grid', может получить доступ только к свойствам из свойства 'Customer', все они должны работать TwoWay (кроме Id), устанавливающий «UpdateSourceTrigger» в TextBoxes, например: «Text =» {Binding GivenName, UpdateSourceTrigger = PropertyChanged} »' –

+0

Насколько я понимаю, тогда мой последний вопрос касается перемещения «DataContext = this;» line out to XAML, я обнаружил, что для пользовательского управления можно указать DataContext = "{Binding RelativeSource = {x: Static RelativeSource.Self}}", и это работает, правильно ли это сделать? и есть ли другие способы сделать собственность доступной в XAML? – Jyrkka

0

Обычно вы должны создать объект «CurrentItem» внутри вашей ViewModel, в котором вы инициализировали бы SelectionCommand. В вашем случае вы связываете своего «клиента» с вашим SelectionCommand, в котором вы должны выполнить команду Customer.Get (id) для получения текущего клиента. Затем вы можете привязать свои элементы управления к объекту «CurrentCustomer» полей для каждого элемента управления.

+0

Я боюсь, что я не сделал понимайте свою точку зрения. Больше слов пожалуйста :) Если бы не пример, то, возможно, какие-то короткие рекомендации были бы идеальными ... – Jyrkka

0

Попробуйте установить DataContext в

DataContext="{Binding Path=Customer}" 

Я понимаю, что путь подразумевает, однако я столкнулся с этой проблемой сам, и это решило для меня.

+0

Ну, это не сработало ... – Jyrkka

+0

Вы включаете {}? – Wombelite

+0

add mode = twoway для привязок twoway – Wombelite

Смежные вопросы