开发者

WPF: Dependency Properties and DataContext

开发者 https://www.devze.com 2023-01-10 22:24 出处:网络
I was working on creating a reusable custom control (not a user control) in WPF. I created the XAML in the Themes/Generic.xaml file and I setup the \"lookless\" functionality in the control\'s CS file

I was working on creating a reusable custom control (not a user control) in WPF. I created the XAML in the Themes/Generic.xaml file and I setup the "lookless" functionality in the control's CS file:

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

Themes\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开发者_如何学JAVA"
                          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; }
    }
}

UPDATED: The prior code is an update from my previous code (removed a lotta fluff just to get down to the ONE example). Though, for some reason Address (within OfficeAddressField) is never ever updated even though I set the binding of OAddress to the AddressField object.


You don't need to refresh the DataContext. In fact, your control shouldn't be using it. Make Address a DependencyProperty and then use a TemplateBinding in your control's template:

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


You should consider raising an event when the address dp changes.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号