【问题标题】:Custom control dynamically update text properties自定义控件动态更新文本属性
【发布时间】:2020-09-23 12:40:36
【问题描述】:

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

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), typeof(TextButtonControl), 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 更新时,如何使控件的文本从大写变为小写(反之亦然)?

示例用法:

<!-- inside some window or user control -->
<ToggleButton x:Name="tbCaseToggle" />
<custom:TextButtonControl Text="some text" Capitalised="{Binding ElementName=tbCaseToggle, Path=IsChecked}" />

在切换按钮被选中或取消选中时更改按钮内容的大小写。

【问题讨论】:

    标签: c# wpf .net-core custom-controls


    【解决方案1】:

    多值转换器

    您可以为此创建一个多转换器,它需要一个布尔值来指示大写和文本。

    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, object parameter, 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), typeof(TextButtonControl), 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"/>
    

    【讨论】:

    • 我试试看!
    • 你真是个救命稻草,我第一次尝试了普通绑定,但我无法绕过绑定到模板绑定!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-06
    • 2012-11-03
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多