WPF:依赖项属性和DataContext

时间:2010-08-11 13:43:43

标签: c# wpf data-binding datacontext dependency-properties

我正在努力在WPF中创建可重用的自定义控件(而不是用户控件)。我在Themes / Generic.xaml文件中创建了XAML,并在控件的CS文件中设置了“lookless”功能:

AddressField.cs

using ...;

namespace MyNamespace
{
    [TemplatePart(Name = AddressField.ElementAddress1TextBox,    Type = typeof(TextBox))]
    public class AddressField : Control
    {
        private const String ElementAddress1TextBox     = "PART_Address1TextBox";

        public AddressEntity Address
        {
            get { return (AddressEntity)GetValue(AddressProperty); }
            set { SetValue(AddressProperty, value); }
        }
        public static readonly DependencyProperty AddressProperty =
            DependencyProperty.Register("Address", typeof(AddressEntity), typeof(AddressField), new UIPropertyMetadata(null, new PropertyChangedCallback(OnAddressPropertyChangedCallback)));

        static AddressField()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(AddressField), new FrameworkPropertyMetadata(typeof(AddressField)));
        }
    }
}

主题\ Generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyNamespace"
    >
    <Style TargetType="{x:Type local:AddressField}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:AddressField}">
                    <StackPanel>
                        <Grid x:Name="StandardView">
                            <Grid.Resources>
                                <Style TargetType="TextBlock">
                                    <Setter Property="Height" Value="17" />
                                    <Setter Property="Margin" Value="3,3,3,3" />
                                </Style>
                                <Style TargetType="TextBox">
                                    <Setter Property="Height" Value="23" />
                                    <Setter Property="Margin" Value="3,3,3,3" />
                                </Style>
                            </Grid.Resources>

                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="1*" />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>

                            <!-- Address 1, Address2-->
                            <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Text="Address:" TextWrapping="NoWrap" />
                            <TextBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="8" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MinWidth="300"
                                     x:Name="PART_Address1TextBox" Text="{Binding Path=Address1}" />
                        </Grid>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Form.xaml

<Window x:Class="NIC.BackOffice.Casino.RegistrationEntryForm"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:nic="clr-namespace:MyNamespace;assembly=MyStuff">

    <Canvas>
        <nic:AddressField Canvas.Left="10" Canvas.Top="10"
                          x:Name="OfficeAddressField" Address={Binding Path=OAddress} />
    </Canvas>
</Window>

Form.cs

using ...;

namespace MyNamespace
{
    public partial class Form : Window
    {
        public Form()
        {
            InitializeComponent();
            OAddress = new AddressEntity("1234 Testing Lane");
        }
        public AddressEntity OAddress { get; set; }
    }
}

更新:先前的代码是我之前代码的更新(删除了很​​多绒毛只是为了得到一个例子)。虽然,由于某种原因,即使我将OAddress的绑定设置为AddressField对象,也永远不会更新Address(在OfficeAddressField中)。

2 个答案:

答案 0 :(得分:1)

您无需刷新DataContext。实际上,您的控件不应该使用它。将Address设为DependencyProperty,然后在控件的模板中使用TemplateBinding

<TextBox Text="{TemplateBinding Address.Address1}"/>

答案 1 :(得分:0)

当地址dp发生变化时,您应该考虑提出一个事件。