Jyrkka
Jyrkka

Reputation: 536

Binding single record

I'm playing around with WPF and LINQ, and stuck at the following point with no clue on how to show a single record, all of the examples I found show how to present a list, but not a single record.
I have prepared a user control that should show one record at a time, in my example a Customer, showing its' Id, Given Name and Surname, here it is:

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

I also have created a table with several records and a class to represent a customer which also implements 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
    }

Now in the code behind the user control I have a realy simple code that connect to the db and gets a record:

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();

        }
    }

But how can I bind the textboxes to the current selected Customer? You can see my last guess, after defining resources etc. But every time I miss something. I would like to know how can I achieve that in XAML, and in code behind. Basically after that I would be able to use the curCustSeqNum to skip to the following record.

Upvotes: 0

Views: 178

Answers (3)

sa_ddam213
sa_ddam213

Reputation: 43616

The CustomerData does not implement INotifyPropertyChanged so when you set Customer in the constructor the xaml has no Idea it has changed.

Example:

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));
        }
    }
}

also mentioned by someone else, you DataContext binding on the Grid is invalid

 <Grid DataContext="Binding Customer">

should be

 <Grid DataContext="{Binding Customer}">

Upvotes: 1

Wombelite
Wombelite

Reputation: 303

Try set your Datacontext to

DataContext="{Binding Path=Customer}"

I realise that path is implied, however i have run into this problem myself and this solved it for me.

Upvotes: 0

Jon Douglas
Jon Douglas

Reputation: 13176

Typically you'd make a "CurrentItem" object inside of your ViewModel in which you'd initialize on a SelectionCommand. In your case, you'd bind your "Customer" on your SelectionCommand in which you'd run a Customer.Get(id) command to obtain the current customer. You can then bind your controls to the "CurrentCustomer" object of the fields for each control.

Upvotes: 0

Related Questions