自适应TextBlock:根据宽度更改文本。优选仅XAML溶液

时间:2018-01-06 16:05:55

标签: xaml uwp uwp-xaml

我有一个function gg_stringformat() { var argcount = arguments.length, string, i; if (!argcount) { return ""; } if (argcount === 1) { return arguments[0]; } string = arguments[0]; for (i = 1; i < argcount; i++) { string = string.replace(new RegExp('\\{' + (i - 1) + '}', 'gi'), arguments[i]); } return string; } ,其TextBlock属性设置为HorizontalAlignment,并希望它根据宽度的不同值显示不同的文本,例如:

  • Stretch如果宽度&lt; 70
  • VSTS如果70&lt; = width&lt; 150
  • VS Team Services如果150&lt; 1宽度

使用Visual Studio Team Services

SizeChanged事件可以实现此行为
TextBlock

然而,我正在寻找一种更优雅的基于XAML的解决方案,看起来像是:

<TextBlock HorizontalAlignment="Stretch" TextTrimming="CharacterEllipsis" SizeChanged="VisualStudioTeamServicesTextBlock_SizeChanged"/>

private void VisualStudioTeamServicesTextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
    if (e.NewSize.Width < 70)
        (sender as TextBlock).Text = "VSTS";
    else if (e.NewSize.Width < 150)
        (sender as TextBlock).Text = "VS Team Services";
    else
        (sender as TextBlock).Text = "Visual Studio Team Services";
}

我想它可以通过几种不同的方式完成(使用样式触发器或可视状态管理器,甚至可能是某些第三方库),但由于我不是专家,我只想问哪个是最简单的给定的任务。非常感谢工作样本。

1 个答案:

答案 0 :(得分:2)

Adaptive triggers将是您问题的最佳解决方案,因为所有内容都是基于XAML的,但不幸的是视觉状态只能基于窗口属性应用。 通过继承StateTriggerBase类,您可以将Adaptive Triggers暴露给几个附加触发器情况,例如Internet连接,但是从那里访​​问运行时依赖项对象似乎不可行,至少对我来说(我是& #39; t也没有专家)。

根据您的控件尺寸创建自己的视觉状态并在状态之间跳转将是另一种可能的解决方案。

但所有这些解决方案共享相同的逻辑背后,即:在某处有代码隐藏,它跟踪依赖属性并对结果进行木偶操作。 这可能是XY Problem吗?

我创建了一个非常乏味的解决方案,我创建了自己的UserControl,并创建了一个自定义依赖项属性,它可以共享3种状态:Small,Medium,Big。但在那之后,我意识到我设想的解决方案没有我想象的那么有用。

理论上,有一个控件暴露了一个自定义依赖属性,只要控件大小发生变化就会设置它(再次我们无法从事件逻辑运行)。只有在依赖属性设置器中,我实际上为TextBox设置了Text。属性设置器被定义为私有,因此您无法从外部设置此用户控件的此属性值。 但是你可以阅读它,就像它从依赖属性中预期的那样。

这个解决方案的目的实际上是强迫我去探索创建自定义控件,依赖属性或附加属性的主题,而不是制作具有极高价值的东西。但希望你可以从中获取一些价值,

用户控件:

代码隐藏

public sealed partial class TextBox : UserControl
{
    public enum TextBoxOptions
    {
        Small = 0,
        Medium = 1,
        Big = 2
    }

    public static readonly DependencyProperty TrackingWidthProperty =
    DependencyProperty.Register(
        "Dependency",
        typeof(TextBoxOptions),
        typeof(TextBox),
        new PropertyMetadata(false)
    );

    public TextBoxOptions TrackingWidth
    {
        get
        {
            return (TextBoxOptions)GetValue(TrackingWidthProperty);
        }

        private set
        {
            if (value == TextBoxOptions.Small) TextBoxRoot.Text = "VSTS";
            else if (value == TextBoxOptions.Medium) TextBoxRoot.Text = "VS Team Services";
            else TextBoxRoot.Text = "Visual Studio Team Services";

            SetValue(TrackingWidthProperty, value);
        }
    }

    public TextBlock()
    {
        this.InitializeComponent();
        this.DataContext = this;

        TextBoxRoot.SizeChanged += TextBoxRoot_SizeChanged;
    }

    private void TextBoxRoot_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (TextBoxRoot.ActualWidth < 600) TrackingWidth = TextBoxOptions.Small;
        else if (TextBoxRoot.ActualWidth < 800) TrackingWidth= TextBoxOptions.Medium;
        else TrackingWidth = TextBoxOptions.Big;
    }
}

XAML:

<UserControl
    x:Class="VisualStateTrigger.TextBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:VisualStateTrigger"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <TextBox x:Name="TextBoxRoot"/>
    </Grid>
</UserControl>

在UserControl之外:

<Page
    x:Class="VisualStateTrigger.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:VisualStateTrigger"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="200"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="150"/>
            </Grid.ColumnDefinitions>
            <local:TextBlock Grid.Column="1" Grid.Row="1" x:Name="myTextBox" HorizontalAlignment="Stretch"/>
        </Grid>

    </Grid>
</Page>

<强>结果

enter image description here

<强>结论:

  • 我遇到了您所定义的低宽度尺寸问题,这就是为什么这些数字会被提升的原因。
  • 像我在用户控件上所做的那样定义数据上下文是我所聚集的错误,但这是有效的......

  • 创建自己的控件可以将所有其他逻辑封装在控件本身中。如果您需要一堆这些元素来共享相同类型的行为,那么您不需要公开多个事件处理程序或为它们创建一个公共位置来访问这些处理程序,因为它实际上是它们的一部分实现。 对于一些更复杂的场景,我可以想象,暴露几个依赖属性可能非常有用。即使在这种情况下,检查TrackingWidth依赖属性也会告诉您控件的当前视觉状态,这可能对于几个非常具体的情况非常重要。