locked
How to programmatically change elements within a grid.resources?

    Question

  • Please look at this xaml.

    <Grid.Resources>
                    <local:StringFormatConverter x:Key="StringFormat"/>
                    <DataTemplate x:Key="pageTemplate">
                        <Grid Margin="4" x:Name="pageGrid">
                            <Border BorderThickness="1" BorderBrush="Black" Grid.Row="1" Grid.Column="1" Background="{Binding ViewManager.PresenterInfo.Background}">
                            </Border>
                            <Grid x:Name ="PresenterGrid"  Height="{Binding ViewManager.PresenterInfo.Height}" Width="{Binding ViewManager.PresenterInfo.Width}">
                                <RTB:RichTextPresenter Source="{Binding}" Grid.Row="1" Grid.Column="1" Margin="{Binding ViewManager.PresenterInfo.Padding}"/>
                                <TextBlock x:FieldModifier="public" x:Name="HeaderTextBlock" Text="{Binding Index, Converter={StaticResource StringFormat}, ConverterParameter='Header on Page : {0}'}" HorizontalAlignment="Center" VerticalAlignment="Top" FontSize="16" Margin="50" Foreground="Black" />
                                <TextBlock Text="{Binding Index, Converter={StaticResource StringFormat}, ConverterParameter='Footer on Page : {0}'}" HorizontalAlignment="Right" VerticalAlignment="Bottom" FontStyle="Italic" FontSize="14" Margin="50" Foreground="Black" />
                            </Grid>
                        </Grid>
                    </DataTemplate>
                </Grid.Resources>

    How do I in c# change the textblock "HeaderTextBlock"?

    Many thanks.


    • Edited by RandyPete Friday, February 13, 2015 6:59 PM
    Wednesday, February 11, 2015 4:54 PM

Answers

  • A better way would be to keep the state in the code behind and databind the HorizontalAlignment. Climbing the visual tree is unnecessary for the given scenario, a lot more work, and more error prone:

     <TextBlock x:FieldModifier="public" x:Name="HeaderTextBlock" Text="{Binding Index, Converter={StaticResource StringFormat}, ConverterParameter='Header on Page : {0}'}" HorizontalAlignment="{Binding HorzAlign}" VerticalAlignment="{Binding VertAlign}" FontSize="16" Margin="50" Foreground="Black" />
                               

          
    Hard-coding the foreground to "Black" is a accessibilitybug. This needs to be bound to resource that can adjust to the user's contrast settings. A word processor probably also wants it to be directly controllable by the user outside of high contrast settings, but that's a feature rather than a bug.

    • Marked as answer by RandyPete Thursday, February 12, 2015 5:06 PM
    Thursday, February 12, 2015 12:55 AM
    Owner

All replies

  • Can you explain more specifically what you're trying to do and why?

    Typically you'd set the text in a data template by binding, which appears to be what you are doing.

    Otherwise you can wait for the template to be and then find the object in the visual tree. The details will depend on how you use the data template and when and where you want to update it.

    Wednesday, February 11, 2015 5:12 PM
    Owner
  • Can you explain more specifically what you're trying to do and why?

    Typically you'd set the text in a data template by binding, which appears to be what you are doing.

    Otherwise you can wait for the template to be and then find the object in the visual tree. The details will depend on how you use the data template and when and where you want to update it.


    I'm just trying to make it possible for the user to make the header and footer on the right, middle, or left.  In other words, I'm trying to change the horizontalalignment property.
    Wednesday, February 11, 2015 8:40 PM
  • When you say "the user" I guess you mean the developer because the user never sets the HorizontalAlignment property.

    The DataTemplate is a template as the name applies and the way to change the HorizontalAlignment property of the TextBlock in the template is to edit the template in the XAML markup where it is defined.

    If you want to change the HorizontalAlignment property of the TextBlock of an element to which the template has been applied, you could do this by finding the TextBlock in the visual tree once the element has been loaded.

    Here is an example where the template is applied to the items of a ListBox:

    <ListBox x:Name="lb" ItemTemplate="{StaticResource pageTemplate}" Loaded="lb_Loaded"/>
    private void lb_Loaded(object sender, RoutedEventArgs e)
            {
                ListBoxItem lbi = lb.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem; //get the visual container for the first item in the ListBox
                TextBlock HeaderTextBlock = FindVisualChild<TextBlock>(lbi, "HeaderTextBlock");
                HeaderTextBlock.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Right;
    
            }
    
            private static T FindVisualChild<T>(DependencyObject parent, string childName) where T : DependencyObject
            {
                if (parent == null)
                    return null;
    
                T foundChild = null;
    
                int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
                for (int i = 0; i < childrenCount; i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    T childType = child as T;
                    if (childType == null)
                    {
                        foundChild = FindVisualChild<T>(child, childName);
    
                        if (foundChild != null) break;
                    }
                    else if (!string.IsNullOrEmpty(childName))
                    {
                        var frameworkElement = child as FrameworkElement;
                        if (frameworkElement != null && frameworkElement.Name == childName)
                        {
                            foundChild = (T)child;
                            break;
                        }
                    }
                    else
                    {
                        foundChild = (T)child;
                        break;
                    }
                }
    
                return foundChild;
            }
    

    Hope that helps.

    Please remember to mark helpful posts as answer to close your threads and then start a new thread if you have a new question.

    Wednesday, February 11, 2015 9:41 PM
  • When you say "the user" I guess you mean the developer because the user never sets the HorizontalAlignment property.

    The DataTemplate is a template as the name applies and the way to change the HorizontalAlignment property of the TextBlock in the template is to edit the template in the XAML markup where it is defined.

    If you want to change the HorizontalAlignment property of the TextBlock of an element to which the template has been applied, you could do this by finding the TextBlock in the visual tree once the element has been loaded.

    Here is an example where the template is applied to the items of a ListBox:

    <ListBox x:Name="lb" ItemTemplate="{StaticResource pageTemplate}" Loaded="lb_Loaded"/>
    private void lb_Loaded(object sender, RoutedEventArgs e)
            {
                ListBoxItem lbi = lb.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem; //get the visual container for the first item in the ListBox
                TextBlock HeaderTextBlock = FindVisualChild<TextBlock>(lbi, "HeaderTextBlock");
                HeaderTextBlock.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Right;
    
            }
    
            private static T FindVisualChild<T>(DependencyObject parent, string childName) where T : DependencyObject
            {
                if (parent == null)
                    return null;
    
                T foundChild = null;
    
                int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
                for (int i = 0; i < childrenCount; i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    T childType = child as T;
                    if (childType == null)
                    {
                        foundChild = FindVisualChild<T>(child, childName);
    
                        if (foundChild != null) break;
                    }
                    else if (!string.IsNullOrEmpty(childName))
                    {
                        var frameworkElement = child as FrameworkElement;
                        if (frameworkElement != null && frameworkElement.Name == childName)
                        {
                            foundChild = (T)child;
                            break;
                        }
                    }
                    else
                    {
                        foundChild = (T)child;
                        break;
                    }
                }
    
                return foundChild;
            }

    Hope that helps.

    Please remember to mark helpful posts as answer to close your threads and then start a new thread if you have a new question.

    When I said the user, I really meant the user of my app.

    I've been working on a word processor app.  This part is where the user can put in header and footer (page number and stuff).  Sometimes, they want it on the right side.  Sometimes, they want it on the left.  Sometimes, they want it in the middle.  I'm giving them those options among other things.

    When I got to this part, I realized that I didn't know how to programmatically control the alignments.

    Thank you for your answer.  I will try to implement your code.  Hopefully, it works out.

    Thursday, February 12, 2015 12:44 AM
  • A better way would be to keep the state in the code behind and databind the HorizontalAlignment. Climbing the visual tree is unnecessary for the given scenario, a lot more work, and more error prone:

     <TextBlock x:FieldModifier="public" x:Name="HeaderTextBlock" Text="{Binding Index, Converter={StaticResource StringFormat}, ConverterParameter='Header on Page : {0}'}" HorizontalAlignment="{Binding HorzAlign}" VerticalAlignment="{Binding VertAlign}" FontSize="16" Margin="50" Foreground="Black" />
                               

          
    Hard-coding the foreground to "Black" is a accessibilitybug. This needs to be bound to resource that can adjust to the user's contrast settings. A word processor probably also wants it to be directly controllable by the user outside of high contrast settings, but that's a feature rather than a bug.

    • Marked as answer by RandyPete Thursday, February 12, 2015 5:06 PM
    Thursday, February 12, 2015 12:55 AM
    Owner