WPF 将 Horizo​​ntalAlignment 绑定到 TextAlignment [英] WPF binding HorizontalAlignment to TextAlignment

查看:40
本文介绍了WPF 将 Horizo​​ntalAlignment 绑定到 TextAlignment的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ListBoxItem,它的 Horizo​​ntalAlignment 属性根据 Window 的宽度由转换器更改.我在这个 ListBoxItem 中有一个 TextBlock,它的 TextAlignment 属性绑定到 ListBoxItem 的 Horizo​​ntalAlignment 属性.

I have a ListBoxItem whose HorizontalAlignment property is changed by an Converter, according to the width of the Window. I have a TextBlock inside this ListBoxItem whose TextAlignment property is binded to the HorizontalAlignment property of the ListBoxItem.

ListBoxItemHorizo​​ntalAlignment 属性正在正确更改;但是,TextBlock 的文本对齐方式保持不变.错误在哪里?

The HorizontalAlignment property of the ListBoxItem is changing correctly; however, the text alignment of the TextBlock remains unchanged. Where is the error?

这是绑定的代码(我没有显示ListBoxItem的Converter,因为它工作正常(根据Window width,它从LeftCenter)):

Here is the code of the binding (I didn't show the Converter of the ListBoxItem because it is working correctly (according to the Window width, it changes from Left to Center)):

<ListBox>
    <ListBoxItem>
        <TextBlock TextWrapping="Wrap" Text="Some text" 
                   TextAlignment="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=HorizontalAlignment}"/>
    </ListBoxItem>
</ListBox>

伙计,你是个侦探!我做了一个有效的实验,但我无法解释为什么.我使用了 MultiBinding 而不是 Binding,传递 AcualWidth 属性,实际上转换器没有使用它.现在 TextAlignment 正在工作并在 ListBoxItem 的 Horizo​​ntalAlignment 更改时更新.我使用了以下代码:

Man, you are a detective! I did an experiment that worked, but I can't explain why. I used a MultiBinding instead of a Binding, passing AcualWidth property, which actually is not used by the Converter. Now the TextAlignment is working and is updated when ListBoxItem's HorizontalAlignment changes. I used the following code:

<TextBlock TextWrapping="Wrap" Text="Some text">
    <TextBlock.TextAlignment>
        <MultiBinding Converter="{StaticResource HorizontalToTextAlignmentConverter}">
            <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
            <Binding Path="HorizontalAlignment" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}"/>
        </MultiBinding>
    </TextBlock.TextAlignment>
</TextBlock>

您能解释一下为什么它适用于 MultiBind 而不是简单的 Binding 吗?无论如何,非常感谢您的帮助!

Could you explain why it worked with MultiBind rather than a simple Binding? Anyway, thanks a lot for your help!

推荐答案

它们是两种不同的枚举:

They are two different enumerations:

TextAlignment 枚举: http://msdn.microsoft.com/en-us/library/system.windows.textalignment(v=vs.110).aspx

Horizo​​ntalAlignment 枚举: http://msdn.microsoft.com/en-us/library/system.windows.horizo​​ntalalignment(v=vs.110).aspx

虽然 TextAlignment 包含 CenterJustifyLeftRightHorizo​​ntalAlignment 包含 CenterLeftRightStretch.所以,如您所见,它们并不相同.

While TextAlignment contains Center, Justify, Left and Right, HorizontalAlignment contains Center, Left, Right and Stretch. So, as you see, they are not the same.

如果您想在另一个基础上使用一个转换器,请创建一个转换器.

Create a converter if you want to use one based on the other.

这是一个非常基本的转换器(根据您的喜好进行调整):

Here's a very basic converter (adjust to your liking):

public class HorizontalToTextAlignmentConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        TextAlignment textAlignment;

        // All I'm doing here is simply getting the integer value of the Enumeration.
        switch ((int)value)
        {
            case 0:
                // Left to Left
                textAlignment = TextAlignment.Left;
                break;
            case 1:
                // Center to Center
                textAlignment = TextAlignment.Center;
                break;
            case 2:
                // Right to Right
                textAlignment = TextAlignment.Right;
                break;
            default:
                // Stretch to Justify
                textAlignment = TextAlignment.Justify;
                break;
        }

        return textAlignment;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        HorizontalAlignment horizontalAlignment;

        // All I'm doing here is simply getting the integer value of the Enumeration.
        switch ((int)value)
        {
            case 0:
                // Left to Left
                horizontalAlignment = HorizontalAlignment.Left;
                break;
            case 1:
                // Right to Right
                horizontalAlignment = HorizontalAlignment.Right;
                break;
            case 2:
                // Center to Center
                horizontalAlignment = HorizontalAlignment.Center;
                break;
            default:
                // Justify to Stretch
                horizontalAlignment = HorizontalAlignment.Stretch;
                break;
        }

        return horizontalAlignment;
    }
}

XAML 测试代码:

<Window.Resources>
    <local:HorizontalToTextAlignmentConverter x:Key="h2tAlignmentConverter"/>
</Window.Resources>
<Grid>
    <ListBox>
        <ListBoxItem HorizontalAlignment="Right">
            <TextBlock TextWrapping="Wrap" Text="Some text" 
                       TextAlignment="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=HorizontalAlignment, Converter={StaticResource h2tAlignmentConverter}}"
                       Width="400"/>
        </ListBoxItem>
    </ListBox>
</Grid>

MSDN 这些编号的顺序有点偏离,所以我只是进入代码来弄清楚它们.这是他们的代码供您参考:

MSDN order of these numerations was a bit off, so I just went into the code to figure them out. Here's their code for your reference:

public enum TextAlignment
{
    Left = 0,
    Right = 1,
    Center = 2,
    Justify = 3,
}

public enum HorizontalAlignment
{
    Left = 0,
    Center = 1,
    Right = 2,
    Stretch = 3,
}

我对您的上一条评论进行了一些思考,我认为由于 TextBlock 本身未在 ListBoxItem 父项中对齐,您可能看不到文本对齐方式的更改.因此,作为一种可能的情况,如果 ListBoxItem 大于 TextBlock,您将看不到正确的更改.您可以通过将 ListBoxItemHorizo​​ntalContentAlignment 绑定到它自己的 Horizo​​ntalAlignment 来实现它们对齐的同步.

I thought a bit about your last comment, and I think you may not be seeing changes to the text alignment due to the TextBlock itself not aligning within the ListBoxItem parent. So, as one of the possible scenarios, if ListBoxItem is bigger than TextBlock, you won't see the proper changes. You can accomplish synchronization of their alignments by binding HorizontalContentAlignment of ListBoxItem to its own HorizontalAlignment.

这是XAML:

<Grid>
    <ListBox>
        <ListBoxItem HorizontalAlignment="Left" BorderThickness="1" BorderBrush="Red"
                     Width="400" HorizontalContentAlignment="{Binding RelativeSource={RelativeSource Self}, Path=HorizontalAlignment}">
            <TextBlock TextWrapping="Wrap" Text="Some text" Background="Green" Foreground="White"
                       TextAlignment="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=HorizontalAlignment, Converter={StaticResource h2tAlignmentConverter}}"
                       Width="300"/>
        </ListBoxItem>
    </ListBox>
</Grid>

这是不同对齐方式的直观表示.ListBoxItemRedTextBlockGreenListBox 占据了整个 网格 &窗口.

Here's a visual representation of the different alignments. ListBoxItem is Red, TextBlock is Green and ListBox occupies the entire Grid & Window.

对齐:

对齐:

居中对齐:

Stretch 对齐(文本为Justified):

最好的部分是 Horizo​​ntalContentAlignment 只是一个 Horizo​​ntalAlignment,所以不需要转换.

The best part is that HorizontalContentAlignment is simply a HorizontalAlignment, so no conversion is needed.

这篇关于WPF 将 Horizo​​ntalAlignment 绑定到 TextAlignment的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆