РЕДАКТИРОВАТЬ: я обновил код в соответствии с вашим комментарием.Подводя итог, можно сказать, что, поскольку это пользовательский элемент управления, вы меньше зависите от шаблона MVVM для построения логики вашего компонента (и, следовательно, используете код в своем компоненте), как только сам компонент отвечает этим требованиям (для сортировки, для настройки его свойств).быть настолько привязываемым, насколько это возможно).Например, в обновленном коде вы теперь можете связать свойство по умолчанию, но вы также можете представить экспонирующие свойства для установки цветов переднего плана, используемых для имени элемента управления отображением, когда значение отсутствует, и т. Д.
Я попробовал несколько вещей с вашим исходным кодом (включая решение, предоставленное J cooper), и ничего не получалось.Кажется, что с вашим кодом много проблем.
Мне удалось найти решение, сделав текстовое поле настраиваемым элементом управления.
Вот 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:Question_6514447">
<Style TargetType="{x:Type local:SuperTB2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:SuperTB2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBox x:Name="PART_Input">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsRequired}" Value="False">
<Setter Property="Text" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DefaultTextValue}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
А вот код элемента управления:
[TemplatePart(Name = "PART_Input")]
public class SuperTB2 : Control
{
private TextBox PART_Input;
static SuperTB2()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SuperTB2), new FrameworkPropertyMetadata(typeof(SuperTB2)));
}
public SuperTB2()
{
Loaded += SuperTb2Loaded;
}
public override void OnApplyTemplate()
{
PART_Input = GetTemplateChild("PART_Input") as TextBox;
if (PART_Input != null)
{
PART_Input.GotFocus += PartInputGotFocus;
PART_Input.LostFocus += PartInputLostFocus;
}
}
void PartInputLostFocus(object sender, RoutedEventArgs e)
{
if (PART_Input.Text == string.Empty)
{
PART_Input.Text = Name;
PART_Input.Foreground = new SolidColorBrush(Colors.Gray);
}
}
void PartInputGotFocus(object sender, RoutedEventArgs e)
{
if (PART_Input.Text.Equals(Name))
{
PART_Input.Text = string.Empty;
PART_Input.Foreground = new SolidColorBrush(Colors.Black);
}
}
void SuperTb2Loaded(object sender, RoutedEventArgs e)
{
if (PART_Input.Text == string.Empty)
{
PART_Input.Text = Name;
PART_Input.Foreground = new SolidColorBrush(Colors.Gray);
}
}
private static DependencyProperty myNameProperty =
DependencyProperty.Register("MyName", typeof(string), typeof(SuperTB2), new PropertyMetadata("Unicorns !", NameChanged));
private static void NameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
public string MyName
{
get { return (string)GetValue(myNameProperty); }
set { SetValue(myNameProperty, value); }
}
DependencyProperty isRequiredProperty =
DependencyProperty.Register("IsRequired", typeof(bool), typeof(SuperTB2), new PropertyMetadata(false, IsReqChanged));
private static void IsReqChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
public bool IsRequired
{
get { return (bool)GetValue(isRequiredProperty); }
set { SetValue(isRequiredProperty, value); }
}
public string DefaultTextValue
{
get { return (string)GetValue(DefaultTextValueProperty); }
set { SetValue(DefaultTextValueProperty, value); }
}
// Using a DependencyProperty as the backing store for DefaultTextValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DefaultTextValueProperty =
DependencyProperty.Register("DefaultTextValue", typeof(string), typeof(SuperTB2), new UIPropertyMetadata("100"));
}
И пример использования компонента:
<Grid>
<StackPanel>
<Question_6514447:SuperTB2 x:Name="FirstName" IsRequired="true" DefaultTextValue="200"/>
</StackPanel>
</Grid>
С этим обновленным кодом, я думаю, вы можете достичь практически всех видов поведения, которые вам нужны!
Надеюсь, это поможет!