简体   繁体   中英

UserControl + ViewModelBase

I have a UserControl called ContactExpander

<UserControl x:Class="Outreach_Alpha2.ContactExpander"
         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"
         xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
         xmlns:outreach="clr-namespace:Outreach_Alpha2"
         mc:Ignorable="d"
         d:DesignHeight="225" d:DesignWidth="400">
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="1" Margin="1">
    <telerik:RadExpander Header="{Binding Path=ContactHeader}" x:Name="ExpanderRoot">
        <StackPanel>
            <DockPanel>
                <StackPanel>
                    <Label Content="Name" FontWeight="Bold" Margin="0, 26, 0, 0"/>
                    <Label Content="Position" FontWeight="Bold"/>
                    <Label Content="Email" FontWeight="Bold"/>
                    <Label Content="Phone" FontWeight="Bold"/>
                    <Label Content="Fax" FontWeight="Bold"/>
                </StackPanel>
                <StackPanel>
                    <DockPanel>
                        <Label Content="Title" Width="50" Margin="1" HorizontalContentAlignment="Center"/>
                        <Label Content="First" Width="125" Margin="1" HorizontalContentAlignment="Center"/>
                        <Label Content="MI" Width="30" Margin="1" HorizontalContentAlignment="Center"/>
                        <Label Content="Last" Width="125" Margin="1" HorizontalContentAlignment="Center"/>
                    </DockPanel>
                    <DockPanel HorizontalAlignment="Left">
                        <!-- Title -->
                        <ComboBox Width="50" Margin="1" 
                                  SelectedValue="{Binding Path=Title, 
                                                          Mode=TwoWay}" 
                                  ItemsSource="{Binding Path=TitleSource, 
                                                        Mode=TwoWay}"/>
                        <!-- First Name -->
                        <TextBox Width="125" Margin="1" 
                                 Text="{Binding Path=FirstName, 
                                                Mode=TwoWay, 
                                                NotifyOnValidationError=True, 
                                                ValidatesOnExceptions=True}" />
                        <!-- Middle Initial -->
                        <TextBox Width="30" Margin="1" 
                                 Text="{Binding Path=MiddleInitial, 
                                                Mode=TwoWay}"/>
                        <!-- Last Name -->
                        <TextBox Width="127" Margin="1" 
                                 Text="{Binding Path=LastName, 
                                                Mode=TwoWay, 
                                                NotifyOnValidationError=True, 
                                                ValidatesOnExceptions=True}"/>
                    </DockPanel>
                    <!-- Position -->
                    <TextBox Margin="2" Text="{Binding Path=Position, 
                                                       Mode=TwoWay}"/>
                    <!-- Email -->
                    <TextBox Margin="2" Text="{Binding Path=Email, 
                                                       Mode=TwoWay, 
                                                       NotifyOnValidationError=True, 
                                                       ValidatesOnExceptions=True}"/>
                    <DockPanel>
                        <!-- Phone Number -->
                        <telerik:RadMaskedNumericInput Margin="2" BorderBrush="LightGray" 
                                                       Value="{Binding Path=PhoneNumber, 
                                                                       Mode=TwoWay, 
                                                                       NotifyOnValidationError=True, 
                                                                       ValidatesOnExceptions=True}" />
                        <Label Content="Ext." FontWeight="Bold"/>
                        <!-- Phone Extension -->
                        <telerik:RadMaskedNumericInput Margin="2" Mask="" BorderBrush="LightGray" 
                                                       Text="{Binding Path=PhoneExtension, 
                                                                      Mode=TwoWay, 
                                                                      NotifyOnValidationError=True, 
                                                                      ValidatesOnExceptions=True}"/>
                    </DockPanel>
                    <!-- Fax Number -->
                    <telerik:RadMaskedNumericInput Margin="2" BorderBrush="LightGray" 
                                                   Value="{Binding Path=FaxNumber, 
                                                                   Mode=TwoWay, 
                                                                   NotifyOnValidationError=True, 
                                                                   ValidatesOnExceptions=True}"/>
                </StackPanel>
            </DockPanel>
            <Border BorderBrush="Black" BorderThickness="0,0,0,1" Margin="0 6" />
            <Button Content="Edit" Width="50" FontWeight="Bold" Margin="1"/>
        </StackPanel>
    </telerik:RadExpander>
</Border>
</UserControl>

I also have a ViewModelBase called ContactViewModel

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Telerik.Windows.Controls;

namespace Outreach_Alpha2
{
    class ContactViewModel : ViewModelBase
    {
      //Declare contact variables
      private string _title;
      private string _firstName;
      private string _middleInitial;
      private string _lastName;
      private string _position;
      private string _email;
      private string _phoneNumber;
      private string _phoneExtension;
      private string _faxNumber;


      public string ContactHeader { get; set; }
      public ObservableCollection<string> TitleSource { get; set; }

      //First Name
      //Set regex
      public string Title
      {
        get { return _title; }
        set
        {
            if (_title != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Title" });
                _title = value;
                OnPropertyChanged("Title");
            }
        }
    }

    //First Name
    [Required(AllowEmptyStrings = false)]
    [RegularExpression(@"\b^[A-Z][a-zA-Z '&-]*[A-Za-z]$\b", ErrorMessage = @"Invalid First Name.")]
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (_firstName != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "FirstName" });
                _firstName = value;
                OnPropertyChanged("FirstName");
            }
        }
    }

    //MiddleInitial
    //Set regex
    public string MiddleInitial
    {
        get { return _middleInitial; }
        set
        {
            if (_middleInitial != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "MiddleInitial" });
                _middleInitial = value;
                OnPropertyChanged("MiddleInitial");
            }
        }
    }

    //Last Name
    [Required(AllowEmptyStrings = false)]
    [RegularExpression(@"\b^[A-Z][a-zA-Z '&-]*[A-Za-z]$\b", ErrorMessage = @"Invalid last name.")]
    public string LastName
    {
        get { return _lastName; }
        set
        {
            if (_lastName != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "LastName" });
                _lastName = value;
                OnPropertyChanged("LastName");
            }
        }
    }

    //Position
    //Set regex
    public string Position
    {
        get { return _position; }
        set
        {
            if (_position != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Position" });
                _position = value;
                OnPropertyChanged("Position");
            }
        }
    }

    //Email
    //Set regex
    public string Email
    {
        get { return _email; }
        set
        {
            if (_email != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Email" });
                _email = value;
                OnPropertyChanged("Email");
            }
        }
    }

    //Phone Number
    //Set regex
    public string PhoneNumber
    {
        get { return _phoneNumber; }
        set
        {
            if (_phoneNumber != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "PhoneNumber" });
                _phoneNumber = value;
                OnPropertyChanged("PhoneNumber");
            }
        }
    }

    //Phone Extension
    //Set regex
    public string PhoneExtension
    {
        get { return _phoneExtension; }
        set
        {
            if (_phoneExtension != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "PhoneExtension" });
                _phoneExtension = value;
                OnPropertyChanged("PhoneExtension");
            }
        }
    }

    //Fax Number
    //Set regex
    public string FaxNumber
    {
        get { return _faxNumber; }
        set
        {
            if (_faxNumber != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "FaxNumber" });
                _faxNumber = value;
                OnPropertyChanged("FaxNumber");
            }
        }
    }
  }
}

I have multiple contacts I'd like to keep track of for one company. I will retrieve the contacts from a SQL database and I want the application to autogenerate multiple expanders in a stackpanel like the following.

<ScrollViewer Height="350" VerticalScrollBarVisibility="Auto" CanContentScroll="True">
    <DockPanel>
        <StackPanel Name="ContactStackPanel" Margin ="16" >
            <!-- Expanders will populate here from the code behind -->
        </StackPanel>
    </DockPanel>
</ScrollViewer>

I do not know how to go about binding the ContactViewModel to the ContactExpander user control.

In order for any bindings to be hooked up, you need to set the DataContext property of the element view to an instance of the viewmodel. The DataContext acts as the source for all of your bindings (unless the binding itself specifies a custom source). You can then set your bindings as normal using the {Binding PropertyName} syntax in xaml. The DataContext will work for the element you set it on as well as all descendants of that element.


As a separate point, you really should not be populating the children of a StackPanel dynamically from a code-behind. WPF provides an automated way of doing that sort of thing using a control called ItemsControl . You just bind the ItemsSource property to an ObservableCollection<ContactViewModel> property that you define and set the ItemTemplate property to a DataTemplate containing your view. Then, all you have to do from that point on is manage the items in your collection and let ItemsControl manage adding, removing and sorting the views. It is also very customizable if the default layout doesn't suit your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM