Search code examples
c#xamldata-bindingwinui-3winui

Binding Custom Data To Textbox Headers


I am trying to make a custom header template in which I can show errors in addition to the name of the textbox. For some reason this line of code in the header template never seems to work:

<TextBlock Text="{x:Bind Errors, Mode=OneWay}" Foreground="Green" />

It always shows as blank.

But this near identical code which isn't in the header template does work:

<TextBlock Text="{x:Bind Supplier.Errors, Mode=OneWay}" Foreground="Green" Grid.Row="7" Grid.Column="1" />

This is what my program currently looks like when i make it give an error: enter image description here

I want the green text at the bottom "Name should be longer..." to display next to the "Errors: " at the top in the header template of the textbox.

Also in the future I would like to make a sort of generic version of this that I could attach to all of my textboxes so they can all display error messages in their headers using a style or template from a resource dictionary.

Ie something like this:

<Style TargetType="TextBox"  x:Key="ValidatedTextBox">
    <Setter Property="HeaderTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <ContentControl Content="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                    <TextBlock Text="{Binding Errors, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

My current xaml code for what is shown in the image:

<TextBox x:Name="NameTextBox" Header="Name" PlaceholderText="Enter Name" PlaceholderForeground="Gray"  IsColorFontEnabled="True" Text="{x:Bind Supplier.Name, Mode=TwoWay}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
    <TextBox.HeaderTemplate >
        <DataTemplate x:DataType="models:Supplier">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding}" Foreground="Red" />
                <TextBlock>Errors: </TextBlock>
                <TextBlock Text="{x:Bind Errors, Mode=OneWay}" Foreground="Green" />
            </StackPanel>
        </DataTemplate>
    </TextBox.HeaderTemplate>
</TextBox>


<TextBox Style="{StaticResource ValidatedTextBox}" Header="Ciao" Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="2"/>
<TextBlock Text="Name Errors: " Grid.Row="7" Grid.Column="0" />
<TextBlock Text="{x:Bind Supplier.Errors, Mode=OneWay}" Foreground="Green" Grid.Row="7" Grid.Column="1" />
<TextBlock Text="{x:Bind Supplier.Name, Mode=OneWay}" Foreground="Green" Grid.Row="8" Grid.Column="0" />
<Button Click="Button_Click" Content="Click" Grid.Row="8" Grid.Column="1"/>


Solution

  • You need to bind the Supplier to the Header.

    <TextBox Header="{x:Bind Supplier.Errors, Mode=OneWay}" .../>