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.
精彩评论