自定义控件动态更新文本属性

问题描述

我有一个基于按钮的自定义控件,该按钮可以包含以下文本:

ORDER BY
public class TextButtonControl : Button
{
    public bool AllCaps
    {
        get => (bool)GetValue(AllCapsProperty);
        set => SetValue(AllCapsProperty,value);
    }
    public static readonly DependencyProperty AllCapsProperty =
        DependencyProperty.Register("AllCaps",typeof(bool),typeof(TextButtonControl),new PropertyMetadata(false));

    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty,value);
    }
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text",typeof(string),new PropertyMetadata(""));

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

当依赖项属性<ControlTemplate targettype="{x:Type local:TextButtonControl}"> <Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" BorderBrush="Red" BorderThickness="2"> <TextBlock Text="{TemplateBinding Text}" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center"/> </Border> </ControlTemplate> 更新时,如何使控件的文本从大写更改为小写(反之亦然)?

用法示例:

AllCaps

要在切换按钮处于选中状态或未选中状态时更改按钮内容的大写字母。

解决方法

多值转换器

您可以为此创建一个多转换器,该转换器使用布尔值表示大写字母和文本。

public class CapitalizationConverter : IMultiValueConverter
{
   public object Convert(object[] values,Type targetType,object parameter,CultureInfo culture)
   {
      var capitalize = (bool)values[0];
      var text = (string)values[1];

      // Change the capitalization here as you need
      return capitalize ? text.ToUpper() : text.ToLower();
   }

   public object[] ConvertBack(object value,Type[] targetTypes,CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}

在控制模板可以访问的资源字典中创建转换器的实例。

<local:CapitalizationConverter x:Key="CapitalizationConverter"/>

然后在控件模板中使用多重绑定,该绑定绑定AllCapsText属性,并使用转换器根据AllCaps的值将文本大写。

<ControlTemplate x:Key="TextButtonControlTemplate" TargetType="{x:Type local:TextButtonControl}">
   <Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" BorderBrush="Red" BorderThickness="2">
      <TextBlock FontFamily="{TemplateBinding FontFamily}"
                 FontSize="{TemplateBinding FontSize}"
                 VerticalAlignment="Center"
                 HorizontalAlignment="Center"
                 TextAlignment="Center">
         <TextBlock.Text>
            <MultiBinding Converter="{StaticResource CapitalizationConverter}">
               <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="AllCaps"/>
               <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Text"/>
            </MultiBinding>
         </TextBlock.Text>
      </TextBlock>
   </Border>
</ControlTemplate>

公开其他财产

另一种方法是公开只读依赖项属性DisplayText

private static readonly DependencyPropertyKey DisplayTextPropertyKey = DependencyProperty.RegisterReadOnly(
   nameof(DisplayText),typeof(string),typeof(TextButtonControl),new FrameworkPropertyMetadata(default(string),FrameworkPropertyMetadataOptions.None));

public static readonly DependencyProperty DisplayTextProperty = DisplayTextPropertyKey.DependencyProperty;

public string DisplayText
{
   get => (string)GetValue(DisplayTextProperty);
   private set => SetValue(DisplayTextPropertyKey,value);
}

AllCapsText属性更改时,将重新格式化DisplayText属性。这仅是AllCaps的示例,但对Text的工作方式也相同。

public static readonly DependencyProperty AllCapsProperty = DependencyProperty.Register(
   "AllCaps",typeof(bool),new PropertyMetadata(false,OnAllCapsChanged));

private static void OnAllCapsChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
   var textButtonControl = (TextButtonControl)d;
   textButtonControl.DisplayText = textButtonControl.FormatText();
}

private string FormatText()
{
   return AllCaps ? Text.ToUpper() : Text.ToLower();
}

在控制模板中,您只需绑定到DisplayText

<TextBlock Text="{Binding DisplayText,RelativeSource={RelativeSource TemplatedParent}}"
           FontFamily="{TemplateBinding FontFamily}"
           FontSize="{TemplateBinding FontSize}"
           VerticalAlignment="Center"
           HorizontalAlignment="Center"
           TextAlignment="Center"/>