Question Dynamically Creating Textblocks and Grids

glasswizzard

Well-known member
Joined
Nov 22, 2019
Messages
126
Programming Experience
Beginner
This might seem pointless but I'd like to know if this is possible and practice doing it.

I want to type into a text box and have the text mirrored onto the form, say below the textbox. I don't want to bind a textblock to a string property even though that will do exactly as I just described. I want the word that is mirrored onto the form to consists of an individual textblock in an individual grid column for each letter, this would go into a cell on the main grid, likely centered in the form below the textbox.

So if I type the word "Hello" into the text box a five column grid would be created, in each column would be one textblock showing a single letter of the word "Hello". It's hard for me to think about attempting this because I don't know how this can be done without explicitly creating and naming the controls. I imagine using a "foreach (char c in stringName)" loop, each time a column is made, a textblock is made, added to the grid and changed to the appropriate letter but maybe I'm thinking about that wrong? How would I do this?

Thanks
 
Wow, thank you very much for the confidence boost! You'll find, however, that my ego leans in the direction of self-deprecation so it could do with being raised a bit :)

I come close to quitting most days, and on occasion when I have quit I'm back the next day, the drive to learn programming keeps me going, I find it thrilling and exciting! But the only reason I feel like quitting sometimes is simply because it can be difficult to know what step to take next as a self learner (especially when I'm up against something that feels impossible to understand), I have no path laid out before me and trying to scrape one together is difficult, so I tend to bounce around topics randomly. I keep making progress though, bit by bit, so I suppose I just need to stick at it, no matter how difficult things seem at times.

You seem to have more confidence in my potential then I do, I don't have much of that at all really, it just feels so good to learn this stuff, that's what drives me, I just love it.

As for Skydivers generous examples, I know I have some excellent material there to get my research going, I'm not done with them yet.
 
I have another question about this line:

C#:
TextBlock Text="{Binding}"

If the banner class contained more then just one property would you need to explicity bind to that property instead of just using the binding keyword alone?
 
It depends. The binding defaults to the results of calling ToString(). If your implementation of ToString() already maps to the property you are interested in, then do nothing. If you are interested in a different property, obviously you'll need to bind to that property.
 
OK great.

I'm trying to modify/play around with your example. What I want to do is make another banner right below the first one, the same in every way except it will show the next letter of the alphabet, so if I type A I'll see two "boxes", one on top of the other, A on top and B on the bottom.

The way I thought about doing this is to make another List<string> just like the Chars list you made. In the Text property's setter I would copy the Text string character by character but copy one character ahead in the alphabet instead. I think after that the ItemsControl should be duplicated and modified to be bound to the other list<string>.

I think that would do it right?
 
It will work only if the banner goes infinitely long left to right, then you can stack two ItemsControls on top of each other.

If you don't want it infinitely long left to right, and want things to wrap correctly so that you get something like:

C#:
H e l l o
A B C D E
W o r l d
F G H I J
Then you'll need to make the DataTemplate a Border that wraps a vertical StackPanel which then contains two TextBlocks where the first binds to a string representing the character typed in, and the second binds to the alphabet letter in your sequence.
 
It will work only if the banner goes infinitely long left to right, then you can stack two ItemsControls on top of each other.

If you don't want it infinitely long left to right, and want things to wrap correctly so that you get something like:

C#:
H e l l o
A B C D E
W o r l d
F G H I J
Then you'll need to make the DataTemplate a Border that wraps a vertical StackPanel which then contains two TextBlocks where the first binds to a string representing the character typed in, and the second binds to the alphabet letter in your sequence.

Oh, I didn't think of putting a second label in the border, I feel a bit stupid for that. I'm gonna play around with this and see if I can make it happen.
 
My idea hasn't worked. Here is how the code looks:

MainWindow.xaml:
<Window x:Class="BannerApp.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:BannerApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <StackPanel>
        <TextBox Text="{Binding Path=Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />

        <ItemsControl ItemsSource="{Binding Chars}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"
                                HorizontalAlignment="Center"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderThickness="1"
                            BorderBrush="Black"
                            Width="50">
                        <StackPanel>
                            <TextBlock Text="{Binding Chars}"
                                   FontSize="20"
                                   Margin="10"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Bottom"/>
                            <TextBlock Text="{Binding NextChars}"
                                   FontSize="20"
                                   Margin="10"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Bottom"/>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</Window>

BannerViewModel.cs:
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;

namespace WpfBanner
{
    class BannerViewModel : INotifyPropertyChanged
    {
        readonly Banner _banner;

        public string Text
        {
            get => _banner.Text;

            set
            {
                _banner.Text = value;
                NotifyPropertyChanged();
                NotifyPropertyChanged("Chars");
                NotifyPropertyChanged("NextChars");
                UpdateNextChars();
            }
        }

        private void UpdateNextChars()
        {
            NextChars = Chars;

            for (int i = 0; i < Chars.Count; i++)
            {
                NextChars[i] = Chars[i] switch
                {
                    "a" => "b",
                    "b" => "c",
                    "c" => "d",
                    "d" => "e",
                    "e" => "f",
                    "f" => "g",
                    "g" => "h",
                    "h" => "i",
                    "i" => "j",
                    "j" => "k",
                    "k" => "l",
                    "l" => "m",
                    "m" => "n",
                    "n" => "o",
                    "o" => "p",
                    "p" => "q",
                    "q" => "r",
                    "r" => "s",
                    "s" => "t",
                    "t" => "u",
                    "u" => "v",
                    "v" => "w",
                    "w" => "x",
                    "x" => "y",
                    "y" => "z",
                    "z" => "a",
                    _ => " "
                };
            }
        }

        public List<string> Chars => Text.Select(c => c.ToString()).ToList();
        public List<string> NextChars = new List<string>();

        public BannerViewModel(Banner banner)
            => _banner = banner;

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged([CallerMemberName] string info = "")
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
    }
}

MainWindow.xaml.cs and Banner.cs haven't been modified. My idea didn't involve changing anything in the Banner class, maybe that's part of my mistake?

Edit: I just had the genius idea of actually including in this post what code does :)

The stackpanel is extended and is twice it's height, but the area below the upper letter is left empty. Visually all that happens is the "boxes" are now "rectangles".
 
Last edited:
I've not yet had a chance look closely or try running your code, but these stood out for me:

This does not copy the contents of the list, it just takes a reference.
C#:
NextChars = Chars;

You need to update the data first before you send the notifications otherwise those subscribed for changes will pick the the old data:
C#:
_banner.Text = value;
NotifyPropertyChanged();
NotifyPropertyChanged("Chars");
NotifyPropertyChanged("NextChars");
UpdateNextChars();
 
OK, I modified them like so:

C#:
get => _banner.Text;
set
{
    _banner.Text = value;
    NotifyPropertyChanged();
    NotifyPropertyChanged("Chars");
    UpdateNextChars();
    NotifyPropertyChanged("NextChars");
}

C#:
for (int i = 0; i < Chars.Count; i++)
{
    NextChars.Add(Chars[i]);
}

Visually, there are no changes when the app is run. Here's a pic of it:

GPDNlPsuNf.png
 
Forget my last question, what about this. How do I add one extra "element" (I don't know the correct terminology).

Untitled.png


If you look at the image above, how do I add one extra "square" on the end that will take up both "rows". Its content will be a simple binding, I don't need any help with that, I just need help creating that type of layout. The square on the end will always be visible if there is text in the banner, and it will always be on the right side. I'm hoping this will require only a simple modification of the template.
 
 
At first I didn't understand what you meant, but for some reason after seeing that "Hello, World!" image again I had a moment of inspiration and am quite certain I solved the problem. Unfortunately I ran into another problem before I could confirm it, but that's a question for another post (which I'll be making in about 30 mins or so).
 
Well, if the link resolved your problem, please edit your original post, and mark this topic as answered. If I have the time, I will take a look at your next question.
 
I don't know if it resolved the problem, I have to solve the other problem first before I can tell.

I didn't realize I could mark threads as solved, I'll go through my posts and do that to all that are resolved, I haven't done that even once yet. Could you tell me how to do it?
 
I don't know if it resolved the problem, I have to solve the other problem first before I can tell.
What is the other problem? If it's unrelated to the current one, we can ask as moderator to split the topics later on.

I'll go through my posts and do that to all that are resolved, I haven't done that even once yet. Could you tell me how to do it?
This screenshot shows where to go and how to do it.

There is an edit link beside the report link on your first post in your topic. Edit that and change the prefix to Answered. I don't see an edit link on your topics, so I can't change it for you because I am not a moderator.

Screenshot :

Screenshot_87.jpg

Just like I can do on my own posts here. This is where the prefix is upon editing the topic :
Screenshot_88.jpg


Do not change any of the content in the topic when changing the status prefix of your topics.
 
Last edited:
Back
Top Bottom