UserControl + ViewModelBase

时间:2015-05-27 21:02:25

标签: c# wpf mvvm user-controls

我有一个名为ContactExpander

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

我还有一个名为ContactViewModel

的ViewModelBase
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");
            }
        }
    }
  }
}

我有多个联系人我想跟踪一家公司。我将从SQL数据库中检索联系人,我希望应用程序在堆栈面板中自动生成多个扩展器,如下所示。

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

我不知道如何将ContactViewModel绑定到ContactExpander用户控件。

1 个答案:

答案 0 :(得分:1)

为了连接任何绑定,您需要将元素视图的DataContext属性设置为viewmodel的实例。 DataContext充当所有绑定的源(除非绑定本身指定自定义源)。然后,您可以使用xaml中的{Binding PropertyName}语法正常设置绑定。 DataContext将适用于您设置的元素以及该元素的所有后代。

作为一个单独的观点,你真的不应该从代码隐藏中动态填充StackPanel的子元素。 WPF使用名为ItemsControl的控件提供了一种自动执行此类操作的方法。您只需将ItemsSource属性绑定到您定义的ObservableCollection<ContactViewModel>属性,并将ItemTemplate属性设置为包含您的视图的DataTemplate。然后,从那时起您需要做的就是管理集合中的项目,让ItemsControl管理添加,删除和排序视图。如果默认布局不符合您的需要,它也可以自定义。