WPF:依赖属性和 DataContext

发布于 2024-09-14 12:56:58 字数 5149 浏览 0 评论 0原文

我正在致力于在 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)));
        }
    }
}

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"
                          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 对象,地址(在 OfficeAddressField 内)也永远不会更新。

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"
                          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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夕色琉璃 2024-09-21 12:56:58

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

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

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}"/>
辞取 2024-09-21 12:56:58

您应该考虑在地址 dp 更改时引发事件。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文