dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
6.94k stars 1.15k forks source link

TextBlock.Style end tag has 2 > symbols but xaml not seeing them- Causing the symbol to be shown as part of render. #9358

Open vsfeedback opened 3 weeks ago

vsfeedback commented 3 weeks ago

This issue has been moved from a ticket on Developer Community.


The GT symbol in the end tag of TextBlock.Style is rendered when it is entered twice at the end of the endtag as shown in the screenshot. I thought the render was an error in the Trigger since the text is supposed to be changed to Yes! when the Checkbox is checked. It would change the color of the text 'NO' to green but would not change the text to 'Yes!' as per the code.

tb issue


Original Comments

Feedback Bot on 10/3/2023, 00:51 PM:

(private comment, text removed)

Feedback Bot on 12/28/2023, 02:19 PM:

(private comment, text removed)


Original Solutions

(no solutions)


Repro steps

1.Create a WPF Application (.NET7.0) 2.Replace Grid with the blow code.

<Grid>

    <TextBlock HorizontalAlignment="Center" Margin="0,20,0,0" FontSize="48">
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Text" Value="No"/>
                <Setter Property="Foreground" Value="red"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=cdSample, Path=IsChecked}" Value="True">
                        <Setter Property="Text" Value="Yes"/>
                        <Setter Property="Foreground" Value="Green"/>
                    </DataTrigger>
                </Style.Triggers>

            </Style>
        </TextBlock.Style>
    </TextBlock>
    <CheckBox x:Name="cdSample" Content="CheckBox" HorizontalAlignment="Left" Margin="72,99,0,0" VerticalAlignment="Top"/>

</Grid>

3.Press F5 to run the app. Issue1: TextBlock.Style end tag has 2 > symbols but xaml not seeing them, and > symbol is rendered in running app. Issue 2: When the Checkbox is checked. the text is supposed to be changed to Yes! but not.

miloush commented 3 weeks ago

I am not sure what "xaml not seeing them" means. You can set the Text property by two means, either using attribute, <TextBlock Text="no" /> or using content: <TextBlock>no</TextBlock>. Your second > is simply treated as a content.

According to the dependency property precedence, local values are above both styles and style triggers, so the checkbox not working is expected (since the extra > makes Text source a local value).

The interesting question is how come that "No" is combined with the local value. However, does the above address the issue? If not, what is the expected behavior?

ThomasGoulet73 commented 2 weeks ago

The content property of TextBlock is Inlines: https://github.com/dotnet/wpf/blob/3f568fe4be8492816666afacf8f7b09c3ec36f22/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextBlock.cs#L55

Which means that the Xaml sets Text to "No" from the style and adds ">" to Inlines from the body of the TextBlock Xaml node. These 2 properties are then combined as "No>" when rendered. Adding an item to Inlines adds to Text but setting Text erases the previous items added to Inlines so depending on which property is initialized first you might get different results.

The Xaml in the issue is equivalent to this:

<Window x:Class="WpfApp42.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp42"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBlock x:Name="textBlock">

        </TextBlock>
    </Grid>
</Window>
using System.Windows;

namespace WpfApp42
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            textBlock.Text = "No";
            textBlock.Inlines.Add(">");
        }
    }
}

I don't think this is a bug but just something that works by design while a bit confusing.

miloush commented 2 weeks ago

Thanks @ThomasGoulet73. I guess I was looking at the wrong place (likely TextBox) because I was convinced the content property is Text and concluded KnownTypes.GetCollectionForCPA is the one that provides Inlines as the target for content nevertheless. Either way, I think the original issue is much simpler, i.e. that of the author not realizing the text can be also set using element content.