2
\$\begingroup\$

What I'm trying to do is bind the controls generated by a ItemsControl.ItemTemplate to a new instance of my ContactInterface class that is created whenever I run my query function.

ContactInterface.cs

class ContactInterface : INotifyPropertyChanged
{
    public string Type { get; set; }

    private string firstname;
    public string FirstName { 
        get{return this.firstname;}
        set {
            if (this.firstname != value) {
                this.firstname = value;
                this.NotifyPropertyChanged("FirstName");
            }
        }
    }
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

SQL.cs

partial class MainWindow
{
    private void selectContact(int? contactID)
    {
    using (ContactsDataContext context = new ContactsDataContext("Data Source=ds;Initial Catalog=db;Integrated Security=True"))
    {
        Contact contact = context.Contacts.SingleOrDefault(x => x.ContactID == contactID);
        Contact spouse = context.Contacts.SingleOrDefault(x => x.ContactID == contact.Spouse);
        Property property = context.Properties.SingleOrDefault(x => x.PropertyID == contact.Address);

        ContactInterface selectedContact= new ContactInterface();

        selectedContact.FirstName = contact.FirstName;

        profileGrid.DataContext = selectedContact;
    }

 }

MainWindow.xaml

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="300" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <ItemsControl Name="Profile_Page_Controls">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid Margin="15">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition Width="30" />
                        <ColumnDefinition Width="100" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                    <RowDefinition Height="43" />
                    <RowDefinition Height="43" />
                    <RowDefinition Height="43" />
                    <RowDefinition Height="43" />
                    <RowDefinition Height="43" />
                    <RowDefinition Height="43" />
                    <RowDefinition Height="43" />
                    <RowDefinition Height="43" />

                </Grid.RowDefinitions>
                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding TextContent}"/>
                    <TextBox Height="23" Text="{Binding Path=FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }"/>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column" Value="{Binding profile_Column}" />
            <Setter Property ="Grid.Row" Value="{Binding profile_Row}" />
            <Setter Property="Grid.ColumnSpan" Value="{Binding profile_Colspan}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>
    <CheckBox Name="profile_SpouseCheck" Grid.Column="1" Margin="0,0,0,0" Checked="profile_SpouseCheck_Checked_1" Unchecked="profile_SpouseCheck_Checked_1"> Spouse</CheckBox>


</Grid>

My plan is to make a new ContactInterface instance every time a user runs the selectContact() function. That new instance will be bound to the generated controls, so when the user makes and saves a change, the textboxes will update that ContactInterface instance and my other functions can grab the data from that ContactInterface to make changes to the database. Any ideas?

\$\endgroup\$
2
\$\begingroup\$

ContactInterface? The word interface has a specific meaning in programming and it just feels wrong here.


this.NotifyPropertyChanged("FirstName");: avoid magic strings, use a lambda.


Your use of brackets is inconsistent: sometimes they are on the same line (e.g. if (this.firstname != value) {), other times they're on a new line. Stick to the second style, which is the common C# way.


Avoid indentation when possible. Instead of this:

  if (this.firstname != value) 
  {
     this.firstname = value;
     this.NotifyPropertyChanged("FirstName");
  }

Do this:

 if (this.firstname == value) 
 {
    return;
 }

 this.firstname = value;
 this.NotifyPropertyChanged("FirstName");

SQL.cs contains the code for MainWindow? In any case, SQL.cs isn't a good class name anyway, since it violates naming rules: "When using acronyms, use Pascal case or camel case for acronyms more than two characters long."


This is becoming an unmanageable mess:

<Grid Margin="15">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="30" />
        <ColumnDefinition Width="100" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="43" />
        <RowDefinition Height="43" />
        <RowDefinition Height="43" />
        <RowDefinition Height="43" />
        <RowDefinition Height="43" />
        <RowDefinition Height="43" />
        <RowDefinition Height="43" />
        <RowDefinition Height="43" />
    </Grid.RowDefinitions>
</Grid>

It will become complicated to keep track of which element is where, so consider alternative UI elements, e.g. the StackPanel.


private void selectContact(int? contactID): methods should be Pascalcase.


I'm a bit surprised by this:

context.Contacts.SingleOrDefault(x => x.ContactID == contact.Spouse);
context.Properties.SingleOrDefault(x => x.PropertyID == contact.Address);

Because if Spouse and Address are ID fields, it doesn't look like it from reading this code. Which is confusing. I'd expect an ID field to be named somethingID. Spouse and Address look like strings containing a name or even better a related class.


You should really consider adding layers to separate your concerns (a ContactsDataContext in your MainWindow? Bad!). Also look into using MVVM.

\$\endgroup\$
  • \$\begingroup\$ I agree, my naming horrible at best and things like the bracket spacing are just things I haven't gotten around to cleaning up yet. I realize that makes your job harder, and I really should of done that before I posted. I took out a lot of code from my original post because I felt it strayed from the real problem I'm having, Which is binding the ContactInterface instance to the ItemControl. \$\endgroup\$ – Corvertbibby May 28 '15 at 14:15
  • \$\begingroup\$ Also, I am using a Grid instead of a StackPanel because, unless I'm mistaken, I could not have multiple controls in the the same row without creating another StackPanel. And if I opted for multiple StackPanels, I wouldn't be able to stretch controls across multiple panels, would I? \$\endgroup\$ – Corvertbibby May 28 '15 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.